improve license notices
[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 mkdir -p /etc/openvpn/client-config
214
215
216 if $dns; then
217 # Be the dns server for clients
218 cat >>$conf <<EOF
219 push "dhcp-option DNS $ip4.1"
220 EOF
221 fi
222
223 if [[ $ip6 ]]; then
224 cat >>$conf <<EOF
225 push tun-ipv6 # legacy option that flidas needs, has no harm.
226 ifconfig-ipv6 $ip6 $ip6route
227 EOF
228
229 sed -i --follow-symlinks '/^ *net.ipv6.conf.all.forwarding=.*/d' /etc/sysctl.conf
230 cat >>/etc/sysctl.conf <<'EOF'
231 net.ipv6.conf.all.forwarding=1
232 EOF
233
234 fi
235
236
237 if $route; then
238 cat >>$conf <<'EOF'
239 # Be the default gateway for clients.
240 push "redirect-gateway def1"
241 EOF
242 if [[ $ip6 ]]; then
243 cat >>$conf <<'EOF'
244 push "route-ipv6 2000::/3"
245 EOF
246 fi
247 fi
248 if [[ $port ]]; then
249 cat >>$conf <<EOF
250 port $port
251 EOF
252 fi
253
254
255 sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf
256 cat >>/etc/sysctl.conf <<'EOF'
257 net.ipv4.ip_forward=1
258 EOF
259 sysctl -p /etc/sysctl.conf
260
261 gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p' | head -n1)
262
263 cat >/etc/systemd/system/vpnnat.service <<EOF
264 [Unit]
265 Description=Turns on nat iptables setting
266
267 [Service]
268 Type=oneshot
269 RemainAfterExit=yes
270 ExecStart=/sbin/iptables -t nat -A POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
271 ExecStop=/sbin/iptables -t nat -D POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
272
273 [Install]
274 WantedBy=$vpn_service.service
275 EOF
276 systemctl daemon-reload # needed if the file was already there
277 # note, no need to start it, the vpn_service does that.
278 systemctl enable vpnnat
279
280 if $start; then
281 systemctl enable $vpn_service
282 systemctl restart $vpn_service
283 fi