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