--- /dev/null
+#!/bin/bash
+set -eE -o pipefail
+
+rm -f /tmp/vpn-mk-client-cert.log
+exec 2>/tmp/vpn-mk-client-cert.log
+
+name=$1
+common_name=$2
+
+echo common_name=$common_name >&2
+
+server_dir=/etc/openvpn
+if [[ -e /etc/openvpn/server ]]; then
+ server_dir=/etc/openvpn/server
+fi
+
+cafile=$server_dir/ca.crt
+
+new=true
+keyfiles=(/etc/openvpn/easy-rsa/pki/{issued/$common_name.crt,private/$common_name.key})
+if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
+ new=false
+ keyfiles=(/etc/openvpn/easy-rsa/keys/$name.{crt,key})
+fi
+
+if [[ ! -e $cafile ]]; then
+ echo: error no cafile found at $cafile >/tmp/errors
+ exit 1
+fi
+
+exists=true
+for x in ${keyfiles[@]}; do
+ if [[ ! -e $x ]]; then
+ exists=false
+ break
+ fi
+done
+
+
+if ! $exists; then
+ cd /etc/openvpn/easy-rsa
+ if $new; then
+ ./easyrsa build-client-full $common_name nopass >/dev/null
+ else
+ source vars >/dev/null
+
+ { echo -e '\n\n\n\n\n'$common_name'\n\n\n\n\n'; sleep 2; echo -e 'y\ny\n'; } | ./build-key $name >/dev/null
+ fi
+fi
+
+d=$(mktemp -d)
+cp $cafile $d/$name-ca.crt
+cp ${keyfiles[@]} $d
+
+cp $server_dir/ta.key $d/$name-ta.key
+
+tar cz -C $d .
+rm -rf $d
[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+readonly this_file="$(readlink -f -- "${BASH_SOURCE[0]}")"; cd "${this_file%/*}"
+
usage() {
- cat <<EOF
+ cat <<'EOF'
usage: ${0##*/} VPN_SERVER_HOST
-b COMMON_NAME By default, use $HOSTNAME or $CLIENT_HOST. If the cert
Note: Uses GNU getopt options parsing style
EOF
- exit ${1:-0}
+ exit ${1:-0}
}
# to get the common name
# cn=$(s openssl x509 -noout -nameopt multiline -subject \
- # -in /etc/openvpn/client/mail.crt | \
- # sed -rn 's/^\s*commonName\s*=\s*(.*)/\1/p')
+ # -in /etc/openvpn/client/mail.crt | \
+ # sed -rn 's/^\s*commonName\s*=\s*(.*)/\1/p')
####### begin command line parsing and checking ##############
name=client
custom_script=false
script=/etc/openvpn/update-resolv-conf
+client_host=$CLIENT_HOST
temp=$(getopt -l help hb:c:n:s: "$@") || usage 1
eval set -- "$temp"
while true; do
- case $1 in
- -b) common_name="$2"; shift 2 ;;
- -c) client_host=$2; shell="ssh root@$client_host"; shift 2 ;;
- -n) name="$2"; shift 2 ;;
- -s) custom_script=true; script="$2"; shift 2 ;;
- -h|--help) usage ;;
- --) shift; break ;;
- *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
- esac
+ case $1 in
+ -b) common_name="$2"; shift 2 ;;
+ -c) client_host=$2; shell="ssh root@$client_host"; shift 2 ;;
+ -n) name="$2"; shift 2 ;;
+ -s) custom_script=true; script="$2"; shift 2 ;;
+ -h|--help) usage ;;
+ --) shift; break ;;
+ *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
+ esac
done
if [[ ! $common_name ]]; then
- if [[ $client_host ]]; then
- common_name=$client_host
- else
- common_name=$HOSTNAME
- fi
+ if [[ $client_host ]]; then
+ common_name=$client_host
+ else
+ common_name=$HOSTNAME
+ fi
fi
host=$1
# bash or else we get motd spam. note sleep 2, sleep 1 failed.
-ssh root@$host bash <<EOF | $shell 'id -u | grep -xF 0 || s=sudo; $s tar xzv -C /etc/openvpn/client'
-set -eE -o pipefail
-
-server_dir=/etc/openvpn
-if [[ -e /etc/openvpn/server ]]; then
- server_dir=/etc/openvpn/server
+if ! ssh root@$host bash -s -- $name $common_name < client-cert-helper \
+ | $shell 'id -u | grep -xF 0 || s=sudo; $s tar xzv -C /etc/openvpn/client'; then
+ echo ssh root@$host cat /tmp/vpn-mk-client-cert.log:
+ ssh root@$host cat /tmp/vpn-mk-client-cert.log
+ exit 1
fi
-exists=true
-for x in /etc/openvpn/easy-rsa/keys/{$name.{crt,key},ca.crt}; do
- if [[ ! -e \$x ]]; then
- exists=false
- break
- fi
-done
-
-if ! \$exists; then
- cd /etc/openvpn/easy-rsa
- source vars >/dev/null
-
- { echo -e '\n\n\n\n\n'$common_name'\n\n\n\n\n'; sleep 2; echo -e 'y\ny\n'; } | ./build-key $name &>/dev/null
-fi
-
-d=\$(mktemp -d)
-cp /etc/openvpn/easy-rsa/keys/ca.crt \$d/$name-ca.crt
-cp /etc/openvpn/easy-rsa/keys/$name.{crt,key} \$d
-
-cp \$server_dir/ta.key \$d/$name-ta.key
-
-tar cz -C \$d .
-rm -rf \$d
-EOF
f=/etc/openvpn/client/$name.crt
if ! $shell "test -s $f"; then
- # if common name is not unique, you get empty file. and if we didn't silence
- # build-key, you'd see an error "TXT_DB error number 2"
- echo "$0: error: $f is empty or otherwise bad. is this common name unique?"
- exit 1
+ # if common name is not unique, you get empty file. and if we didn't silence
+ # build-key, you'd see an error "TXT_DB error number 2"
+ echo "$0: error: $f is empty or otherwise bad. is this common name unique?"
+ exit 1
fi
$shell "dd of=/etc/openvpn/client/$name.conf" <<EOF
-# From example config, from debian stretch as of 1-2017
+# From example config, from debian stretch to buster
client
dev tun
proto udp
EOF
if [[ $client_host ]] && $custom_script; then
- $shell "dd of=$script" <$script
- $shell "chmod +x $script"
+ $shell "dd of=$script" <$script
+ $shell "chmod +x $script"
fi
$shell 'cd /etc/openvpn; for f in client/*; do ln -sf $f .; done'
[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
usage() {
- cat <<'EOF'
+ cat <<'EOF'
usage: ${0##*/} [-d|-h|--help]
-r Do not push default route
Note: Uses GNU getopt options parsing style
EOF
- exit $1
+ exit $1
}
dns=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
+ 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
+# 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
+
if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then
- vpn_service=openvpn-server@server
+ vpn_service=openvpn-server@server
else
- vpn_service=openvpn@server
+ 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
+ # there's a debian bug about this.
+ ln -s openssl-1.0.0.cnf openssl.cnf
+fi
+
+server_dir=/etc/openvpn/server
+mkdir -p $server_dir
+chmod 700 $server_dir
+
+
+new=true
+keyfiles=(/etc/openvpn/easy-rsa/pki/{ca.crt,private/server.key,issued/server.crt})
+if [[ -e /etc/openvpn/easy-rsa/build-ca ]]; then
+ new=false
+ keyfiles=(/etc/openvpn/easy-rsa/keys/{ca.crt,server.{crt,key}})
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
+ 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
+ # 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
+ ./easyrsa init-pki
+ ./easyrsa --batch build-ca nopass
+ ./easyrsa build-server-full server nopass
+ openssl dhparam -out $server_dir/dh2048.pem 2048
+ else
+ # dun care about settning cert cn etc from the non-example values
+ source vars
+ # doesnt exist in buster
./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
# 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
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
+ ln -sf server/${f##*/} /etc/openvpn
done
cat >>$server_dir/server.conf <<'EOF'
if $dns; then
- # Be the dns server for clients
- cat >>$server_dir/server.conf <<'EOF'
+ # 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'
+ 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'
+fi
+
+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
+net.ipv6.conf.all.forwarding=1
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')
-
- cat >/etc/systemd/system/vpnnat.service <<EOF
+cat >/etc/systemd/system/vpnnat.service <<EOF
[Unit]
Description=Turns on nat iptables setting
ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $gw -j MASQUERADE
[Install]
-WantedBy=$vpn_service
+WantedBy=$vpn_service.service
EOF
- systemctl daemon-reload # needed if the file was already there
- # note, no need to start it, the vpn_service does that.
-fi
+systemctl daemon-reload # needed if the file was already there
+# note, no need to start it, the vpn_service does that.
+systemctl enable vpnnat
if $start; then
- systemctl enable $vpn_service
- systemctl restart $vpn_service
+ systemctl enable $vpn_service
+ systemctl restart $vpn_service
fi