fix a few failures
[vpn-setup] / vpn-server-setup
1 #!/bin/bash
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##*/} [OPTIONS] [IPV6_ADDR/BITS IPV6_DEFAULT_ROUTE]
25
26 -4 I prefix of range for ipv4, default 10.8.0
27 -d Do not push dns
28 -n Name. default = server. 2 servers on the same host need different names.
29 -p Port. default 1194
30 -r Do not push default route
31 -s Do not start openvpn
32 -h --help print help
33
34 Sets up a vpn server which pushes gateway route and dns server so all
35 traffic goes through the vpn. requires systemd, and might have some
36 debian specific paths.
37
38 For ipv6, we assume ipv6_addr routes to the server.
39
40 You can save all the keys by storing /etc/openvpn/easy-rsa/keys, and
41 the script will not generate them if it sees they exist already.
42
43 For future updates to this script, this is a good place to
44 take inspiration.
45 https://github.com/angristan/openvpn-install/blob/master/openvpn-install.sh
46
47 Note: Uses GNU getopt options parsing style
48 EOF
49 exit $1
50 }
51
52 dns=true
53 route=true
54 start=true
55 ip4=10.8.0
56 name=server
57 temp=$(getopt -l help 4:dn:p:rsh "$@") || usage 1
58 eval set -- "$temp"
59 while true; do
60 case $1 in
61 -4) ip4=$2; shift 2 ;;
62 -d) dns=false; shift ;;
63 -n) name=$2; shift 2 ;;
64 -p) port=$2; shift 2 ;;
65 -r) route=false; shift ;;
66 -s) start=false; shift ;;
67 -h|--help) usage ;;
68 --) shift; break ;;
69 *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
70 esac
71 done
72
73 read -r ip6 ip6route <<<"$@"
74
75 source /a/bin/distro-functions/src/package-manager-abstractions
76
77 pi-nostart openvpn openssl resolvconf easy-rsa uuid-runtime
78
79 if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then
80 vpn_service=openvpn-server@$name
81 else
82 vpn_service=openvpn@$name
83 fi
84 rsadir=/etc/openvpn/easy-rsa-$name
85 mkdir -p $rsadir
86 cd $rsadir
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 conf=$server_dir/$name.conf
97
98
99 new=true
100 ca_origin=$rsadir/pki/ca.crt
101 keyfiles=(
102 $rsadir/pki/private/$name.key
103 $rsadir/pki/issued/$name.crt
104 )
105 if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
106 new=false
107 ca_origin=$rsadir/ca.crt
108 keyfiles=(
109 $rsadir/keys/$name.key
110 $rsadir/keys/$name.crt
111 )
112 fi
113
114 keys_exist=true
115 for f in ${keyfiles[@]}; do
116 if [[ ! -e $f ]]; then
117 keys_exist=false
118 break
119 fi
120 done
121
122 f=$server_dir/dh2048.pem
123 if [[ ! -e $f ]]; then
124 openssl dhparam -out $f 2048
125 fi
126
127 f=$server_dir/ta-$name.key
128 if [[ ! -e $f ]]; then
129 openvpn --genkey --secret $server_dir/ta-$name.key
130 fi
131
132
133 if ! $keys_exist; then
134 # newer sample configs (post stretch) use ta.key. no harm making it for earlier oses
135 if $new; then
136 echo 'set_var EASYRSA_NS_SUPPORT "yes"' >vars
137 ./easyrsa init-pki
138 ./easyrsa --batch build-ca nopass
139 ./easyrsa build-server-full $name nopass
140 else
141 # dun care about settning cert cn etc from the non-example values
142 source vars
143 # doesnt exist in buster
144 ./clean-all # note: removes and creates /etc/openvpn/easy-rsa/keys
145 # accept default prompts
146 echo -e '\n\n\n\n\n\n\n\n' | ./build-ca
147
148 # This builds the server's key/cert. argument is the name of the file,
149 # but it also is the default common name of the cert.
150 # 'server' is the default name in our conf file for the name of the file
151 # and I've seen no reason to change it.
152 # Note, this is not idempotent.
153 { echo -e '\n\n\n\n\n\n\n\n\n\n'; sleep 1; echo -e 'y\ny\n'; } | ./build-key-server $name
154 ./build-dh
155 fi
156 fi
157
158
159 gzip -dc /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz >$conf
160
161 cafile=$server_dir/ca-$name.crt
162 cp $ca_origin $cafile
163 cp ${keyfiles[@]} $server_dir
164 # for legacy systems
165 for f in ${keyfiles[@]} $cafile; do
166 ln -sf server/${f##*/} /etc/openvpn
167 done
168
169 cat >>$conf <<EOF
170
171 # I cat an extra blank line to start because the example config does
172 # not have a final newline. ....
173
174 # not in example config, but openvpn outputs a warning about insecure
175 # cipher without a setting like this (the default i can understand due
176 # to compatibility issues, but not changing the example config... not
177 # cool).
178 # requires the same setting on the client side.
179 cipher AES-256-CBC
180 # just sets up the ability to have client specific configs
181 client-config-dir /etc/openvpn/client-config
182
183 # duplicate in newer sample configs
184 tls-auth ta-$name.key 0 # This file is secret
185
186 # depending on sample config, this may not be there, which means i can't
187 # talk to $ip4.1, there might be some other way, but stretch's
188 # sample config says:
189 # Should be subnet (addressing via IP)
190 # unless Windows clients v2.0.9 and lower have to
191 # be supported (then net30, i.e. a /30 per client)
192 # Defaults to net30 (not recommended)
193 topology subnet
194
195 status /var/log/openvpn/openvpn-status-$name.log
196 ifconfig-pool-persist /var/log/openvpn/ipp-$name.txt
197 ca ca-$name.crt
198 cert $name.crt
199 key $name.key
200 client-config-dir /etc/openvpn/client-config-$name
201 server $ip4.0 255.255.255.0
202 EOF
203 mkdir -p /etc/openvpn/client-config-$name
204
205 # dh improve security,
206 # remove comp-lzo to increase perf
207 sed -i --follow-symlinks -f - $conf <<'EOF'
208 s/^dh dh1024.pem/dh dh2048.pem/
209 /^comp-lzo.*/d
210 EOF
211
212
213 if $dns; then
214 # Be the dns server for clients
215 cat >>$conf <<EOF
216 push "dhcp-option DNS $ip4.1"
217 EOF
218 fi
219
220 if [[ $ip6 ]]; then
221 cat >>$conf <<EOF
222 push tun-ipv6 # legacy option that flidas needs, has no harm.
223 ifconfig-ipv6 $ip6 $ip6route
224 EOF
225
226 sed -i --follow-symlinks '/^ *net.ipv6.conf.all.forwarding=.*/d' /etc/sysctl.conf
227 cat >>/etc/sysctl.conf <<'EOF'
228 net.ipv6.conf.all.forwarding=1
229 EOF
230
231 fi
232
233
234 if $route; then
235 cat >>$conf <<'EOF'
236 # Be the default gateway for clients.
237 push "redirect-gateway def1"
238 EOF
239 if [[ $ip6 ]]; then
240 cat >>$conf <<'EOF'
241 push "route-ipv6 2000::/3"
242 EOF
243 fi
244 fi
245 if [[ $port ]]; then
246 cat >>$conf <<EOF
247 port $port
248 EOF
249 fi
250
251
252 sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf
253 cat >>/etc/sysctl.conf <<'EOF'
254 net.ipv4.ip_forward=1
255 EOF
256 sysctl -p /etc/sysctl.conf
257
258 gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p' | head -n1)
259
260 cat >/etc/systemd/system/vpnnat.service <<EOF
261 [Unit]
262 Description=Turns on nat iptables setting
263
264 [Service]
265 Type=oneshot
266 RemainAfterExit=yes
267 ExecStart=/sbin/iptables -t nat -A POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
268 ExecStop=/sbin/iptables -t nat -D POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
269
270 [Install]
271 WantedBy=$vpn_service.service
272 EOF
273 systemctl daemon-reload # needed if the file was already there
274 # note, no need to start it, the vpn_service does that.
275 systemctl enable vpnnat
276
277 if $start; then
278 systemctl enable $vpn_service
279 systemctl restart $vpn_service
280 fi