X-Git-Url: https://iankelling.org/git/?p=vpn-setup;a=blobdiff_plain;f=vpn-server-setup;h=0710dc801072e749df602364226a5fbd216d082b;hp=4dcb2158c721f709dff01a5bc977e515e8a31f0a;hb=HEAD;hpb=380c0bb2981093bb23d85eeca29e5b214de5e14a diff --git a/vpn-server-setup b/vpn-server-setup index 4dcb215..c135d4e 100755 --- a/vpn-server-setup +++ b/vpn-server-setup @@ -1,5 +1,12 @@ #!/bin/bash -# Copyright (C) 2016 Ian Kelling +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to switch +# its license to GPL. + +# Copyright 2024 Ian Kelling # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,107 +26,279 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@" -dns=true -case $1 in - -d) - dns=false - ;; - -h|--help|*) - cat <<'EOF' -usage: ${0##*/} [-d|-h|--help] - --d Do not push dns +usage() { + cat <<'EOF' +usage: ${0##*/} [OPTIONS] [IPV6_ADDR/BITS] + +-4 Prefix of range for ipv4, default 10.8.0 +-6 IP6_NETWORK Do ip6 nat for this network. ipv6 will work without nat, + but you may want it in certain circumstances. +-d Do not push dns +-i INTERFACE_NAME name of tun interface +-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 -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. +IPV6_ADDR/BITS Ipv6 address of the vpn interface. + +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. + +For ipv6, we assume ipv6_addr routes to the server. + +You can save all the keys by storing /etc/openvpn/easy-rsa-NAME/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 - ;; -esac - -apt-get update -# suggests get's us openssl & easy rsa -apt-get install --install-suggests -y openvpn -apt-get install -y uuid-runtime -mkdir -p /etc/openvpn/easy-rsa/keys -cd /etc/openvpn/easy-rsa + exit $1 +} + +dns=true +route=true +start=true +ip4=10.8.0 +name=server +temp=$(getopt -l help 4:6:di:n:p:rsh "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -4) ip4=$2; shift 2 ;; + -6) ip6net=$2; shift 2 ;; + -d) dns=false; shift ;; + -i) ifname=$2; shift 2 ;; + -n) name=$2; shift 2 ;; + -p) port=$2; shift 2 ;; + -r) route=false; shift ;; + -s) start=false; shift ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;; + esac +done + +read -r ip6 ip6route <<<"$@" + +source /a/bin/distro-functions/src/package-manager-abstractions + +pi-nostart openvpn openssl easy-rsa uuid-runtime + +if [[ -e /lib/systemd/system/openvpn-server@.service ]]; then + vpn_service=openvpn-server@$name +else + vpn_service=openvpn@$name +fi +rsadir=/etc/openvpn/easy-rsa-$name +mkdir -p $rsadir +cd $rsadir cp -r /usr/share/easy-rsa/* . -source vars # dun care about setting cert cn etc from the non-example values -./clean-all -# 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 -cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/ -cp /etc/openvpn/easy-rsa/keys/{ca.crt,server.{crt,key},dh2048.pem} /etc/openvpn -gzip -df /etc/openvpn/server.conf.gz -# dh improve security, -# remove comp-lzo to increase perf -sed -i --follow-symlinks -f - /etc/openvpn/server.conf <<'EOF' -s/^dh dh1024.pem/dh dh2048.pem/ -/^comp-lzo.*/d -EOF +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 -teeu() { - while read -r line; do - grep -xFq "$line" "$1" || echo "$line" | tee -a "$1" - done -} +server_dir=/etc/openvpn/server +mkdir -p $server_dir +chmod 700 $server_dir +conf=$server_dir/$name.conf + + +new=true +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 + ca_origin=$rsadir/ca.crt + keyfiles=( + $rsadir/keys/$name.key + $rsadir/keys/$name.crt + ) +fi + +keys_exist=true +for f in ${keyfiles[@]}; do + if [[ ! -e $f ]]; then + keys_exist=false + break + 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 $new; then + echo 'set_var EASYRSA_NS_SUPPORT "yes"' >vars + ./easyrsa init-pki + ./easyrsa --batch build-ca nopass + ./easyrsa --days=3650 build-server-full $name nopass + 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 + # 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 $name + ./build-dh + fi +fi + +if [[ -e /usr/share/doc/openvpn/examples/sample-config-files/server.conf ]]; then + cat /usr/share/doc/openvpn/examples/sample-config-files/server.conf >$conf +else + # pre-bullsye name + gzip -dc /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz >$conf +fi + +cafile=$server_dir/ca-$name.crt +cp $ca_origin $cafile +cp ${keyfiles[@]} $server_dir +# for legacy systems +for f in ${keyfiles[@]} $cafile; do + ln -sf server/${f##*/} /etc/openvpn +done + +cat >>$conf <>$conf < /proc/sys/net/ipv4/ip_forward -sed -i --follow-symlinks '/^ *net\.ipv4\.ip_forward=.*/d' /etc/sysctl.conf -teeu /etc/sysctl.conf <<'EOF' -net.ipv4.ip_forward=1 +if [[ $ifname ]]; then + cat >>$conf <>$conf <>/etc/sysctl.conf <<'EOF' +net.ipv6.conf.all.forwarding=1 +EOF -sudo dd of=/etc/systemd/system/vpnnat.service <>$conf <<'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 +if [[ $port ]]; then + cat >>$conf <>/etc/sysctl.conf <<'EOF' +net.ipv4.ip_forward=1 EOF -systemctl daemon-reload # needed if the file was already there -systemctl enable vpnnat.service -systemctl start vpnnat.service +sysctl -p /etc/sysctl.conf -systemctl restart openvpn@server +gw=$(ip route | sed -rn 's/^default via .* dev (\S+).*/\1/p' | head -n1) + +d=/etc/systemd/system/$vpn_service.service.d +mkdir -p $d +f=$d/nat.conf +cat >$f <>$f <