update for multiple servers on one host
[vpn-setup] / vpn-server-setup
index ded2a785f59250b265f2307a85ccdb3e04cfb98c..0710dc801072e749df602364226a5fbd216d082b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash -x
+#!/bin/bash
 # Copyright (C) 2016 Ian Kelling
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # Copyright (C) 2016 Ian Kelling
 
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,10 +21,13 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
 usage() {
   cat <<'EOF'
 
 usage() {
   cat <<'EOF'
-usage: ${0##*/} [-d|-h|--help]
+usage: ${0##*/} [OPTIONS] [IPV6_ADDR/BITS IPV6_DEFAULT_ROUTE]
 
 
--r  Do not push default route
+-4  I prefix of range for ipv4, default 10.8.0
 -d  Do not push dns
 -d  Do not push dns
+-n  Name. default = server. 2 servers on the same host need different names.
+-p  Port. default 1194
+-r  Do not push default route
 -s  Do not start openvpn
 -h --help print help
 
 -s  Do not start openvpn
 -h --help print help
 
@@ -32,9 +35,15 @@ Sets up a vpn server which pushes gateway route and dns server so all
 traffic goes through the vpn. requires systemd, and might have some
 debian specific paths.
 
 traffic goes through the vpn. requires systemd, and might have some
 debian specific paths.
 
+For ipv6, we assume ipv6_addr routes to the server.
+
 You can save all the keys by storing /etc/openvpn/easy-rsa/keys, and
 the script will not generate them if it sees they exist already.
 
 You can save all the keys by storing /etc/openvpn/easy-rsa/keys, and
 the script will not generate them if it sees they exist already.
 
+For future updates to this script, this is a good place to
+take inspiration.
+https://github.com/angristan/openvpn-install/blob/master/openvpn-install.sh
+
 Note: Uses GNU getopt options parsing style
 EOF
   exit $1
 Note: Uses GNU getopt options parsing style
 EOF
   exit $1
@@ -43,11 +52,16 @@ EOF
 dns=true
 route=true
 start=true
 dns=true
 route=true
 start=true
-temp=$(getopt -l help drsh "$@") || usage 1
+ip4=10.8.0
+name=server
+temp=$(getopt -l help 4:dn:p:rsh "$@") || usage 1
 eval set -- "$temp"
 while true; do
   case $1 in
 eval set -- "$temp"
 while true; do
   case $1 in
+    -4) ip4=$2; shift 2 ;;
     -d) dns=false; shift ;;
     -d) dns=false; shift ;;
+    -n) name=$2; shift 2 ;;
+    -p) port=$2; shift 2 ;;
     -r) route=false; shift ;;
     -s) start=false; shift ;;
     -h|--help) usage ;;
     -r) route=false; shift ;;
     -s) start=false; shift ;;
     -h|--help) usage ;;
@@ -56,25 +70,20 @@ while true; do
   esac
 done
 
   esac
 done
 
-apt-get update
-# suggests get's us openssl. policy-rc.d is to prevent install from starting services
-f=/usr/sbin/policy-rc.d;
-dd of=$f <<EOF
-#!/bin/sh
-exit 101
-EOF
-chmod +x $f;
-apt-get install --install-suggests -y openvpn
-rm $f
+read -r ip6 ip6route <<<"$@"
+
+source /a/bin/distro-functions/src/package-manager-abstractions
+
+pi-nostart openvpn openssl resolvconf easy-rsa uuid-runtime
 
 if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then
 
 if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then
-  vpn_service=openvpn-server@server
+  vpn_service=openvpn-server@$name
 else
 else
-  vpn_service=openvpn@server
+  vpn_service=openvpn@$name
 fi
 fi
-apt-get install -y uuid-runtime easy-rsa
-mkdir -p /etc/openvpn/easy-rsa
-cd /etc/openvpn/easy-rsa
+rsadir=/etc/openvpn/easy-rsa-$name
+mkdir -p $rsadir
+cd $rsadir
 cp -r /usr/share/easy-rsa/* .
 if [[ -e openssl-1.0.0.cnf && ! -e openssl.cnf ]]; then
   # there's a debian bug about this.
 cp -r /usr/share/easy-rsa/* .
 if [[ -e openssl-1.0.0.cnf && ! -e openssl.cnf ]]; then
   # there's a debian bug about this.
@@ -84,13 +93,22 @@ fi
 server_dir=/etc/openvpn/server
 mkdir -p $server_dir
 chmod 700 $server_dir
 server_dir=/etc/openvpn/server
 mkdir -p $server_dir
 chmod 700 $server_dir
+conf=$server_dir/$name.conf
 
 
 new=true
 
 
 new=true
-keyfiles=(/etc/openvpn/easy-rsa/pki/{ca.crt,private/server.key,issued/server.crt})
+ca_origin=$rsadir/pki/ca.crt
+keyfiles=(
+  $rsadir/pki/private/$name.key
+  $rsadir/pki/issued/$name.crt
+)
 if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
   new=false
 if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
   new=false
-  keyfiles=(/etc/openvpn/easy-rsa/keys/{ca.crt,server.{crt,key}})
+  ca_origin=$rsadir/ca.crt
+  keyfiles=(
+    $rsadir/keys/$name.key
+    $rsadir/keys/$name.crt
+  )
 fi
 
 keys_exist=true
 fi
 
 keys_exist=true
@@ -101,14 +119,24 @@ for f in ${keyfiles[@]}; do
   fi
 done
 
   fi
 done
 
+f=$server_dir/dh2048.pem
+if [[ ! -e $f ]]; then
+  openssl dhparam -out $f 2048
+fi
+
+f=$server_dir/ta-$name.key
+if [[ ! -e $f ]]; then
+  openvpn --genkey --secret $server_dir/ta-$name.key
+fi
+
+
 if ! $keys_exist; then
   # newer sample configs (post stretch) use ta.key. no harm making it for earlier oses
 if ! $keys_exist; then
   # newer sample configs (post stretch) use ta.key. no harm making it for earlier oses
-  openvpn --genkey --secret $server_dir/ta.key
   if $new; then
   if $new; then
+    echo 'set_var EASYRSA_NS_SUPPORT      "yes"' >vars
     ./easyrsa init-pki
     ./easyrsa --batch build-ca nopass
     ./easyrsa init-pki
     ./easyrsa --batch build-ca nopass
-    ./easyrsa build-server-full server nopass
-    openssl dhparam -out $server_dir/dh2048.pem 2048
+    ./easyrsa build-server-full $name nopass
   else
     # dun care about settning cert cn etc from the non-example values
     source vars
   else
     # dun care about settning cert cn etc from the non-example values
     source vars
@@ -122,23 +150,23 @@ if ! $keys_exist; then
     # 'server' is the default name in our conf file for the name of the file
     # and I've seen no reason to change it.
     # Note, this is not idempotent.
     # 'server' is the default name in our conf file for the name of the file
     # and I've seen no reason to change it.
     # Note, this is not idempotent.
-    { echo -e '\n\n\n\n\n\n\n\n\n\n'; sleep 1; echo -e 'y\ny\n'; } | ./build-key-server server
+    { echo -e '\n\n\n\n\n\n\n\n\n\n'; sleep 1; echo -e 'y\ny\n'; } | ./build-key-server $name
     ./build-dh
   fi
 fi
 
 
     ./build-dh
   fi
 fi
 
 
-cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz $server_dir
-gzip -df $server_dir/server.conf.gz
-
+gzip -dc /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz >$conf
 
 
+cafile=$server_dir/ca-$name.crt
+cp $ca_origin $cafile
 cp ${keyfiles[@]} $server_dir
 # for legacy systems
 cp ${keyfiles[@]} $server_dir
 # for legacy systems
-for f in ${keyfiles[@]}; do
+for f in ${keyfiles[@]} $cafile; do
   ln -sf server/${f##*/} /etc/openvpn
 done
 
   ln -sf server/${f##*/} /etc/openvpn
 done
 
-cat >>$server_dir/server.conf <<'EOF'
+cat >>$conf <<EOF
 
 # I cat an extra blank line to start because the example config does
 # not have a final newline. ....
 
 # I cat an extra blank line to start because the example config does
 # not have a final newline. ....
@@ -153,22 +181,30 @@ cipher AES-256-CBC
 client-config-dir /etc/openvpn/client-config
 
 # duplicate in newer sample configs
 client-config-dir /etc/openvpn/client-config
 
 # duplicate in newer sample configs
-tls-auth ta.key 0 # This file is secret
+tls-auth ta-$name.key 0 # This file is secret
 
 # depending on sample config, this may not be there, which means i can't
 
 # depending on sample config, this may not be there, which means i can't
-# talk to 10.8.0.1, there might be some other way, but stretch's
+# talk to $ip4.1, there might be some other way, but stretch's
 # sample config says:
 # Should be subnet (addressing via IP)
 # unless Windows clients v2.0.9 and lower have to
 # be supported (then net30, i.e. a /30 per client)
 # Defaults to net30 (not recommended)
 topology subnet
 # sample config says:
 # Should be subnet (addressing via IP)
 # unless Windows clients v2.0.9 and lower have to
 # be supported (then net30, i.e. a /30 per client)
 # Defaults to net30 (not recommended)
 topology subnet
-EOF
 
 
+status /var/log/openvpn/openvpn-status-$name.log
+ifconfig-pool-persist /var/log/openvpn/ipp-$name.txt
+ca ca-$name.crt
+cert $name.crt
+key $name.key
+client-config-dir /etc/openvpn/client-config-$name
+server $ip4.0 255.255.255.0
+EOF
+mkdir -p /etc/openvpn/client-config-$name
 
 # dh improve security,
 # remove comp-lzo to increase perf
 
 # dh improve security,
 # remove comp-lzo to increase perf
-sed -i --follow-symlinks -f - $server_dir/server.conf <<'EOF'
+sed -i --follow-symlinks -f - $conf <<'EOF'
 s/^dh dh1024.pem/dh dh2048.pem/
 /^comp-lzo.*/d
 EOF
 s/^dh dh1024.pem/dh dh2048.pem/
 /^comp-lzo.*/d
 EOF
@@ -179,27 +215,50 @@ mkdir -p /etc/openvpn/client-config
 
 if $dns; then
   # Be the dns server for clients
 
 if $dns; then
   # Be the dns server for clients
-  cat >>$server_dir/server.conf <<'EOF'
-push "dhcp-option DNS 10.8.0.1"
+  cat >>$conf <<EOF
+push "dhcp-option DNS $ip4.1"
+EOF
+fi
+
+if [[ $ip6 ]]; then
+  cat >>$conf <<EOF
+push tun-ipv6 # legacy option that flidas needs, has no harm.
+ifconfig-ipv6 $ip6 $ip6route
 EOF
 EOF
+
+  sed -i --follow-symlinks '/^ *net.ipv6.conf.all.forwarding=.*/d' /etc/sysctl.conf
+  cat >>/etc/sysctl.conf <<'EOF'
+net.ipv6.conf.all.forwarding=1
+EOF
+
 fi
 
 fi
 
+
 if $route; then
 if $route; then
-  cat >>$server_dir/server.conf <<'EOF'
+  cat >>$conf <<'EOF'
 # Be the default gateway for clients.
 push "redirect-gateway def1"
 EOF
 # Be the default gateway for clients.
 push "redirect-gateway def1"
 EOF
+  if [[ $ip6 ]]; then
+    cat >>$conf <<'EOF'
+push "route-ipv6 2000::/3"
+EOF
+  fi
 fi
 fi
+if [[ $port ]]; then
+  cat >>$conf <<EOF
+port $port
+EOF
+fi
+
 
 sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf
 
 sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf
-sed -i --follow-symlinks '/^ *net.ipv6.conf.all.forwarding=.*/d' /etc/sysctl.conf
 cat >>/etc/sysctl.conf <<'EOF'
 net.ipv4.ip_forward=1
 cat >>/etc/sysctl.conf <<'EOF'
 net.ipv4.ip_forward=1
-net.ipv6.conf.all.forwarding=1
 EOF
 sysctl -p /etc/sysctl.conf
 
 EOF
 sysctl -p /etc/sysctl.conf
 
-gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p')
+gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p' | head -n1)
 
 cat >/etc/systemd/system/vpnnat.service <<EOF
 [Unit]
 
 cat >/etc/systemd/system/vpnnat.service <<EOF
 [Unit]
@@ -208,8 +267,8 @@ Description=Turns on nat iptables setting
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $gw -j MASQUERADE
-ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $gw -j MASQUERADE
+ExecStart=/sbin/iptables -t nat -A POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
+ExecStop=/sbin/iptables -t nat -D POSTROUTING -s $ip4.0/24 -o $gw -j MASQUERADE
 
 [Install]
 WantedBy=$vpn_service.service
 
 [Install]
 WantedBy=$vpn_service.service