#!/bin/bash -x # Copyright (C) 2016 Ian Kelling # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -eE -o pipefail trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@" usage() { cat <<'EOF' usage: ${0##*/} [-d|-h|--help] -r Do not push default route -d Do not push dns -s Do not start openvpn -h --help print help 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. 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. Note: Uses GNU getopt options parsing style EOF exit $1 } dns=true route=true start=true temp=$(getopt -l help drsh "$@") || usage 1 eval set -- "$temp" while true; do case $1 in -d) dns=false; shift ;; -r) route=false; shift ;; -s) start=false; shift ;; -h|--help) usage ;; --) shift; break ;; *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;; esac done apt-get update # suggests get's us openssl apt-get install --install-suggests -y openvpn if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then vpn_service=openvpn-server@server else vpn_service=openvpn@server fi apt-get install -y uuid-runtime easy-rsa mkdir -p /etc/openvpn/easy-rsa cd /etc/openvpn/easy-rsa cp -r /usr/share/easy-rsa/* . if [[ -e openssl-1.0.0.cnf && ! -e openssl.cnf ]]; then # there's a debian bug about this. ln -s openssl-1.0.0.cnf openssl.cnf fi keys_exist=true keyfiles=(/etc/openvpn/easy-rsa/keys/{ca.crt,server.{crt,key},dh2048.pem,ta.key}) for f in ${keyfiles[@]}; do if [[ ! -e $f ]]; then keys_exist=false break fi done if ! $keys_exist; then source vars # dun care about setting cert cn etc from the non-example values ./clean-all # note: removes and creates /etc/openvpn/easy-rsa/keys # newer sample configs (post stretch) use ta.key. no harm making it for earlier oses openvpn --genkey --secret /etc/openvpn/easy-rsa/keys/ta.key # accept default prompts echo -e '\n\n\n\n\n\n\n\n' | ./build-ca # This builds the server's key/cert. argument is the name of the file, # but it also is the default common name of the cert. # '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 ./build-dh fi server_dir=/etc/openvpn/server mkdir -p $server_dir chmod 700 $server_dir cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz $server_dir gzip -df $server_dir/server.conf.gz cp ${keyfiles[@]} $server_dir # for legacy systems for f in ${keyfiles[@]}; do ln -sf server/${f##*/} /etc/openvpn done cat >>$server_dir/server.conf <<'EOF' # I cat an extra blank line to start because the example config does # not have a final newline. .... # not in example config, but openvpn outputs a warning about insecure # cipher without a setting like this (the default i can understand due # to compatibility issues, but not changing the example config... not # cool). # requires the same setting on the client side. cipher AES-256-CBC # just sets up the ability to have client specific configs client-config-dir /etc/openvpn/client-config # duplicate in newer sample configs tls-auth ta.key 0 # This file is secret # 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 # 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 # dh improve security, # remove comp-lzo to increase perf sed -i --follow-symlinks -f - $server_dir/server.conf <<'EOF' s/^dh dh1024.pem/dh dh2048.pem/ /^comp-lzo.*/d EOF mkdir -p /etc/openvpn/client-config if $dns; then # Be the dns server for clients cat >>$server_dir/server.conf <<'EOF' push "dhcp-option DNS 10.8.0.1" EOF fi if $route; then cat >>$server_dir/server.conf <<'EOF' # Be the default gateway for clients. push "redirect-gateway def1" EOF echo "1" > /proc/sys/net/ipv4/ip_forward sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf cat >>/etc/sysctl.conf <<'EOF' net.ipv4.ip_forward=1 EOF gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p') cat >/etc/systemd/system/vpnnat.service <