From 431799b73339f28ec914cea711c1af9d87533bc2 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 7 Jun 2022 23:56:11 -0700 Subject: [PATCH] Add wg-setup.sh to help with setting up wireguard in p2p mode --- wg-setup.sh | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100755 wg-setup.sh diff --git a/wg-setup.sh b/wg-setup.sh new file mode 100755 index 0000000..299f5c0 --- /dev/null +++ b/wg-setup.sh @@ -0,0 +1,210 @@ +#!/bin/bash +set -e +umask 077 + +function fail() +{ + printf "error: $@" >&2 + echo >&2 + exit 1 +} + +any_warnings=0 + +function warn() +{ + any_warnings=1 + printf "warning: $@" >&2 + echo >&2 +} + +function install_deps() +{ + if ! which wg >/dev/null; then + echo "wireguard not found, installing:" + sudo apt update + sudo apt install wireguard + fi +} + +function check_cidr_addr() +{ + local addr="$1" + [[ "$addr" =~ ^(0|[1-9][0-9]*)'.'(0|[1-9][0-9]*)'.'(0|[1-9][0-9]*)'.'(0|[1-9][0-9]*)'/'(0|[1-9][0-9]*)$ ]] \ + || fail "can't parse IPv4 CIDR address: %q" "$addr" + ((${BASH_REMATCH[1]} <= 255 && + ${BASH_REMATCH[2]} <= 255 && + ${BASH_REMATCH[3]} <= 255 && + ${BASH_REMATCH[4]} <= 255 && + ${BASH_REMATCH[5]} <= 32)) \ + || fail "invalid IPv4 CIDR address: %s" "$addr" +} + +function init_server() +{ + local server_iface_name="$1" listen_port="$2" server_iface_addr="$3" + check_cidr_addr "$server_iface_addr" + set -o noclobber + local private_key="$(wg genkey)" + local config_contents="[Interface] +PrivateKey = $private_key +ListenPort = $listen_port +Address = $server_iface_addr +SaveConfig = true +" + echo "$config_contents" > "/etc/wireguard/$server_iface_name.conf" + echo "Created config for $server_iface_name" + echo "You need to allow UDP port $listen_port through your firewall" +} + +function add_client() +{ + local server_iface_name="$1" server_public_addr="$2" client_config="$3" client_iface_addr="$4" + check_cidr_addr "$client_iface_addr" + if [[ " $(wg show interfaces) " =~ " $server_iface_name " ]]; then + fail "You need to shutdown interface %s first:\nwg-quick down %s\nor:\nsystemctl stop wg-quick@%s" \ + "$server_iface_name" "$server_iface_name" "$server_iface_name" + fi + local server_iface_conf="/etc/wireguard/$server_iface_name.conf" + local lines line key eq_value value section="" server_private_key="" + local server_iface_addr="" server_listen_port="" + mapfile -t lines < "$server_iface_conf" + for line in "${lines[@]}"; do + line="${line%%#*}" # remove comments + [[ "$line" =~ ^([^=]*)('='(.*))?$ ]] || fail "regex failed -- not supposed to happen" + key="${BASH_REMATCH[1]}" + eq_value="${BASH_REMATCH[2]}" + value="${BASH_REMATCH[3]}" + key="${key#"${key%%[![:space:]]*}"}" # remove leading whitespace + key="${key%"${key##*[![:space:]]}"}" # remove trailing whitespace + value="${value#"${value%%[![:space:]]*}"}" # remove leading whitespace + value="${value%"${value##*[![:space:]]}"}" # remove trailing whitespace + [[ "$key" == "" && "$eq_value" == "" ]] && continue + if [[ "$key" =~ ^'['(.+)']'$ && "$eq_value" == "" ]]; then + section="${BASH_REMATCH[1]}" + case "$section" in + 'Interface'|'Peer') + ;; + *) + warn "unknown config section %s" "$key" + ;; + esac + elif [[ "$section" == "Interface" ]]; then + case "$key" in + 'PrivateKey') + [[ "$value" == "" ]] && fail "empty [Interface] PrivateKey value" + server_private_key="$value" + ;; + 'Address') + [[ "$value" == "" ]] && fail "empty [Interface] Address value" + [[ "$server_iface_addr" != "" + || "$value" =~ [[:space:],] ]] && \ + fail "multiple [Interface] Address values not supported" + server_iface_addr="$value" + check_cidr_addr "$server_iface_addr" + ;; + 'ListenPort') + [[ "$value" =~ ^[1-9][0-9]* ]] || \ + fail "invalid [Interface] ListenPort value: %s" "$value" + server_listen_port="$value" + ;; + 'SaveConfig'|'FwMark'|'DNS'|'MTU') + ;; + 'Table'|'PreUp'|'PreDown'|'PostUp'|'PostDown') + ;; + *) + warn "unknown config key [Interface] %s" "$key" + ;; + esac + elif [[ "$section" == "Peer" ]]; then + case "$key" in + 'AllowedIPs'|'PublicKey'|'PresharedKey'|'Endpoint'|'PersistentKeepalive') + ;; + *) + warn "unknown config key [Peer] %s" "$key" + ;; + esac + fi + done + [[ "$server_iface_addr" != "" ]] || fail "missing [Interface] Address config key" + [[ "$server_private_key" != "" ]] || fail "missing [Interface] PrivateKey config key" + [[ "$server_listen_port" != "" ]] || fail "missing [Interface] ListenPort config key" + if ((any_warnings)); then + echo -n "Warnings generated, do you want to continue? [y/N]: " >&2 + local cont + read -r cont + if [[ "$cont" != "y" ]]; then + exit 1 + fi + fi + local client_private_key="$(wg genkey)" + local server_public_key="$(wg pubkey <<<"$server_private_key")" + local client_public_key="$(wg pubkey <<<"$client_private_key")" + local preshared_key="$(wg genpsk)" + local client_config_contents="[Interface] +PrivateKey = $client_private_key +Address = $client_iface_addr +SaveConfig = true + +[Peer] +PublicKey = $server_public_key +PresharedKey = $preshared_key +AllowedIPs = $server_iface_addr +Endpoint = $server_public_addr:$server_listen_port +PersistentKeepalive = 25 +" + set -o noclobber + echo "$client_config_contents" > "$client_config" + set +o noclobber + local server_config_new_peer=" +[Peer] +PublicKey = $client_public_key +PresharedKey = $preshared_key +AllowedIPs = $client_iface_addr +PersistentKeepalive = 25 +" + echo "$server_config_new_peer" >> "$server_iface_conf" + cat <.conf on the client, +making sure that it is owned by root and has mode 600. Make sure it is NOT +left lying around since it contains the private key for the client, as well +as the preshared key. + +Once you did that, run on the server: +wg-quick up $server_iface_name +or: +systemctl start wg-quick@$server_iface_name +and run on the client: +wg-quick up +or: +systemctl start wg-quick@ +EOF +} + +case "$1" in + init-server) + install_deps + init_server "${@:2}" + ;; + add-client) + install_deps + add_client "${@:2}" + ;; + *) + cat >&2 < + or: $0 add-client + +init-server: create a new wireguard config for the server, writes to + '/etc/wireguard/.conf' + +add-client: add a client to the wireguard config for the server at + '/etc/wireguard/.conf' + Writes the generated client config to . + The client will connect to the server through + public IP or DNS address . +EOF + exit 1 + ;; +esac -- 2.30.2