improve license notices
[vpn-setup] / vpn-server-setup
1 #!/bin/bash -x
2 # Copyright (C) 2016 Ian Kelling
3
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16
17 set -eE -o pipefail
18 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
19
20 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
21
22 usage() {
23 cat <<'EOF'
24 usage: ${0##*/} [-d|-h|--help] [IPV6_ADDR/BITS IPV6_DEFAULT_ROUTE]
25
26 -r Do not push default route
27 -d Do not push dns
28 -s Do not start openvpn
29 -h --help print help
30
31 Sets up a vpn server which pushes gateway route and dns server so all
32 traffic goes through the vpn. requires systemd, and might have some
33 debian specific paths.
34
35 For ipv6, we assume ipv6_addr routes to the server.
36
37 You can save all the keys by storing /etc/openvpn/easy-rsa/keys, and
38 the script will not generate them if it sees they exist already.
39
40 For future updates to this script, this is a good place to
41 take inspiration.
42 https://github.com/angristan/openvpn-install/blob/master/openvpn-install.sh
43
44 Note: Uses GNU getopt options parsing style
45 EOF
46 exit $1
47 }
48
49 dns=true
50 route=true
51 start=true
52 temp=$(getopt -l help drsh "$@") || usage 1
53 eval set -- "$temp"
54 while true; do
55 case $1 in
56 -d) dns=false; shift ;;
57 -r) route=false; shift ;;
58 -s) start=false; shift ;;
59 -h|--help) usage ;;
60 --) shift; break ;;
61 *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
62 esac
63 done
64
65 read -r ip6 ip6route <<<"$@"
66
67
68 apt-get update
69 # suggests get's us openssl. policy-rc.d is to prevent install from starting services
70 f=/usr/sbin/policy-rc.d;
71 dd of=$f <<EOF
72 #!/bin/sh
73 exit 101
74 EOF
75 chmod +x $f;
76 apt-get install --install-suggests -y openvpn
77 rm $f
78
79 if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then
80 vpn_service=openvpn-server@server
81 else
82 vpn_service=openvpn@server
83 fi
84 apt-get install -y uuid-runtime easy-rsa
85 mkdir -p /etc/openvpn/easy-rsa
86 cd /etc/openvpn/easy-rsa
87 cp -r /usr/share/easy-rsa/* .
88 if [[ -e openssl-1.0.0.cnf && ! -e openssl.cnf ]]; then
89 # there's a debian bug about this.
90 ln -s openssl-1.0.0.cnf openssl.cnf
91 fi
92
93 server_dir=/etc/openvpn/server
94 mkdir -p $server_dir
95 chmod 700 $server_dir
96
97
98 new=true
99 keyfiles=(/etc/openvpn/easy-rsa/pki/{ca.crt,private/server.key,issued/server.crt})
100 if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
101 new=false
102 keyfiles=(/etc/openvpn/easy-rsa/keys/{ca.crt,server.{crt,key}})
103 fi
104
105 keys_exist=true
106 for f in ${keyfiles[@]}; do
107 if [[ ! -e $f ]]; then
108 keys_exist=false
109 break
110 fi
111 done
112
113 if ! $keys_exist; then
114 # newer sample configs (post stretch) use ta.key. no harm making it for earlier oses
115 openvpn --genkey --secret $server_dir/ta.key
116 if $new; then
117 ./easyrsa init-pki
118 ./easyrsa --batch build-ca nopass
119 ./easyrsa build-server-full server nopass
120 openssl dhparam -out $server_dir/dh2048.pem 2048
121 else
122 # dun care about settning cert cn etc from the non-example values
123 source vars
124 # doesnt exist in buster
125 ./clean-all # note: removes and creates /etc/openvpn/easy-rsa/keys
126 # accept default prompts
127 echo -e '\n\n\n\n\n\n\n\n' | ./build-ca
128
129 # This builds the server's key/cert. argument is the name of the file,
130 # but it also is the default common name of the cert.
131 # 'server' is the default name in our conf file for the name of the file
132 # and I've seen no reason to change it.
133 # Note, this is not idempotent.
134 { echo -e '\n\n\n\n\n\n\n\n\n\n'; sleep 1; echo -e 'y\ny\n'; } | ./build-key-server server
135 ./build-dh
136 fi
137 fi
138
139
140 cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz $server_dir
141 gzip -df $server_dir/server.conf.gz
142
143
144 cp ${keyfiles[@]} $server_dir
145 # for legacy systems
146 for f in ${keyfiles[@]}; do
147 ln -sf server/${f##*/} /etc/openvpn
148 done
149
150 cat >>$server_dir/server.conf <<'EOF'
151
152 # I cat an extra blank line to start because the example config does
153 # not have a final newline. ....
154
155 # not in example config, but openvpn outputs a warning about insecure
156 # cipher without a setting like this (the default i can understand due
157 # to compatibility issues, but not changing the example config... not
158 # cool).
159 # requires the same setting on the client side.
160 cipher AES-256-CBC
161 # just sets up the ability to have client specific configs
162 client-config-dir /etc/openvpn/client-config
163
164 # duplicate in newer sample configs
165 tls-auth ta.key 0 # This file is secret
166
167 # depending on sample config, this may not be there, which means i can't
168 # talk to 10.8.0.1, there might be some other way, but stretch's
169 # sample config says:
170 # Should be subnet (addressing via IP)
171 # unless Windows clients v2.0.9 and lower have to
172 # be supported (then net30, i.e. a /30 per client)
173 # Defaults to net30 (not recommended)
174 topology subnet
175 EOF
176
177
178 # dh improve security,
179 # remove comp-lzo to increase perf
180 sed -i --follow-symlinks -f - $server_dir/server.conf <<'EOF'
181 s/^dh dh1024.pem/dh dh2048.pem/
182 /^comp-lzo.*/d
183 EOF
184
185
186 mkdir -p /etc/openvpn/client-config
187
188
189 if $dns; then
190 # Be the dns server for clients
191 cat >>$server_dir/server.conf <<'EOF'
192 push "dhcp-option DNS 10.8.0.1"
193 EOF
194 fi
195
196 if [[ $ip6 ]]; then
197 cat >>$server_dir/server.conf <<EOF
198 push tun-ipv6 # legacy option that flidas needs, has no harm.
199 ifconfig-ipv6 $ip6 $ip6route
200 EOF
201
202 sed -i --follow-symlinks '/^ *net.ipv6.conf.all.forwarding=.*/d' /etc/sysctl.conf
203 cat >>/etc/sysctl.conf <<'EOF'
204 net.ipv6.conf.all.forwarding=1
205 EOF
206
207 fi
208
209
210 if $route; then
211 cat >>$server_dir/server.conf <<'EOF'
212 # Be the default gateway for clients.
213 push "redirect-gateway def1"
214 EOF
215 if [[ $ip6 ]]; then
216 cat >>$server_dir/server.conf <<'EOF'
217 push "route-ipv6 2000::/3"
218 EOF
219 fi
220 fi
221
222 sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf
223 cat >>/etc/sysctl.conf <<'EOF'
224 net.ipv4.ip_forward=1
225 EOF
226 sysctl -p /etc/sysctl.conf
227
228 gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p')
229
230 cat >/etc/systemd/system/vpnnat.service <<EOF
231 [Unit]
232 Description=Turns on nat iptables setting
233
234 [Service]
235 Type=oneshot
236 RemainAfterExit=yes
237 ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $gw -j MASQUERADE
238 ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $gw -j MASQUERADE
239
240 [Install]
241 WantedBy=$vpn_service.service
242 EOF
243 systemctl daemon-reload # needed if the file was already there
244 # note, no need to start it, the vpn_service does that.
245 systemctl enable vpnnat
246
247 if $start; then
248 systemctl enable $vpn_service
249 systemctl restart $vpn_service
250 fi