From 87abf354f17c0468491bb91146f0acdf0236d6d0 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 30 Dec 2016 17:50:19 +0100 Subject: [PATCH] wg-config: use ip rules instead of tungate Signed-off-by: Jason A. Donenfeld --- contrib/wg-config/Makefile | 6 +-- contrib/wg-config/README | 76 ++++++++++++++++++------------------- contrib/wg-config/tungate | 43 --------------------- contrib/wg-config/wg-config | 41 +++++++++----------- 4 files changed, 58 insertions(+), 108 deletions(-) delete mode 100755 contrib/wg-config/tungate diff --git a/contrib/wg-config/Makefile b/contrib/wg-config/Makefile index aa81848..4fa264c 100644 --- a/contrib/wg-config/Makefile +++ b/contrib/wg-config/Makefile @@ -2,12 +2,10 @@ PREFIX ?= /usr DESTDIR ?= SBINDIR ?= $(PREFIX)/sbin -SCRIPTS := wg-config tungate - all: - @echo "These are shell scripts, so there is nothing to do. Try \"make install\" instead." + @echo "This is a shell script, so there is nothing to do. Try \"make install\" instead." install: - @install -v -m0755 -D -t$(DESTDIR)$(SBINDIR) $(SCRIPTS) + @install -v -m0755 -D -t$(DESTDIR)$(SBINDIR) wg-config .PHONY: all install diff --git a/contrib/wg-config/README b/contrib/wg-config/README index 2e594c6..93da029 100644 --- a/contrib/wg-config/README +++ b/contrib/wg-config/README @@ -43,17 +43,9 @@ options described above, and variables that may be declared in ENV_FILE: Additionally, ENV_FILE may define the bash functions pre_add, post_add, pre_del, and post_del, which will be called at their respective times. +== Basic Example == -== Helper Tool == - -tungate is a separate utility, developed originally not explicitly for -WireGuard, which acts as a poor man's way of ensuring 0/1 and 128/1 default -route overrides still work with an endpoint going over the original default -route. It's quite handy, and wg-config makes use of it for dealing with -0.0.0.0/0 routes. At the moment it only supports IPv4, but adding IPv6 -should be pretty easy. - -== Example == +This basic example might be used by a server. /etc/wireguard/wg-server.conf: @@ -83,36 +75,11 @@ Run at startup: Run at shutdown: # wg-config del wgserver0 --env-file=/etc/wireguard/wg-server.env -== Advanced Example == - -/etc/wireguard/wg-vpn-gateway.conf: - - [Interface] - PrivateKey = 6JiA3fa+NG+x5m6aq7+lxlVaVqVf1mxK6/pDOZdNuXc= - - [Peer] - PublicKey = 6NagfTu+s8+TkEKpxX7pNjJuTf4zYtoJme7iQFYIw0A= - AllowedIPs = 0.0.0.0/0 - Endpoint = demo.wireguard.io:29912 - -/etc/wireguard/wg-vpn-gateway.env: - - [[ $SUBCOMMAND == add ]] && CONFIG_FILE="$(dirname "${BASH_SOURCE[0]}")/demo-vpn.conf" || true - ADDRESSES=( 10.200.100.2/32 ) - post_add() { - printf 'nameserver 10.200.100.1' | cmd resolvconf -a "$INTERFACE" -m 0 - } - post_del() { - cmd resolvconf -d "$INTERFACE" - } - -Run to flip on the VPN: -# wg-config add wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env -The config file is not overwritten on shutdown, due to the conditional in the env file: -# wg-config del wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env - == Single File Advanced Example == +This type of configuration might be desirable for a personal access gateway +VPN, connecting to a server like in the example above. + /etc/wireguard/wg-vpn-gateway.env: CONFIG_FILE_CONTENTS=" @@ -138,3 +105,36 @@ Run to flip on the VPN: # wg-config add wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env Run to flip off the VPN: # wg-config del wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env + +== Advanced Example == + +This achieves the same as the above, but with an external file. It only sets the +configuration file when the subcommand is add, to prevent it from being overwritten. +The above is much simpler and probably preferred, but this example shows how powerful +the tool can be. + +/etc/wireguard/wg-vpn-gateway.conf: + + [Interface] + PrivateKey = 6JiA3fa+NG+x5m6aq7+lxlVaVqVf1mxK6/pDOZdNuXc= + + [Peer] + PublicKey = 6NagfTu+s8+TkEKpxX7pNjJuTf4zYtoJme7iQFYIw0A= + AllowedIPs = 0.0.0.0/0 + Endpoint = demo.wireguard.io:29912 + +/etc/wireguard/wg-vpn-gateway.env: + + [[ $SUBCOMMAND == add ]] && CONFIG_FILE="$(dirname "${BASH_SOURCE[0]}")/demo-vpn.conf" || true + ADDRESSES=( 10.200.100.2/32 ) + post_add() { + printf 'nameserver 10.200.100.1' | cmd resolvconf -a "$INTERFACE" -m 0 + } + post_del() { + cmd resolvconf -d "$INTERFACE" + } + +Run to flip on the VPN: +# wg-config add wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env +The config file is not overwritten on shutdown, due to the conditional in the env file: +# wg-config del wgvpn0 --env-file=/etc/wireguard/wg-vpn-gateway.env diff --git a/contrib/wg-config/tungate b/contrib/wg-config/tungate deleted file mode 100755 index 034e8b8..0000000 --- a/contrib/wg-config/tungate +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -unwind() { - ip route del "$1/32" 2>/dev/null - exit -} - -short_route() { - ip route | sed -n "s/$1 \\(.* dev [^ ]\\+\\).*/\\1/p" | head -n 1 -} - -resolve_ip() { - local filter='/^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$/{p;q;}' - [[ $(sed -n "$filter" <<<"$1") == "$1" ]] && echo "$1" || - host -t a "$1" | cut -d ' ' -f 4 | sed -n "$filter" -} - -set_route() { - local default_route="$(short_route default)" - [[ -n $default_route ]] || { echo "[-] Could not determine default route"; return; } - echo "[+] Adding route for $1 to be $default_route" - ip route del "$1/32" 2>/dev/null - ip route add "$1/32" $default_route -} - -check_loop() { - local ip="$(resolve_ip "$1")" - [[ -n $ip ]] || { echo "[-] Could not determine IP of '$1'" && return 1; } - echo "[+] Making sure $ip goes over the default (non-0/1,128/1) route" - - set_route "$ip" - trap unwind INT TERM EXIT - - while read -r; do - [[ $(short_route "$ip") != "$(short_route default)" ]] && set_route "$ip" - done < <(exec ip monitor route) -} - -[[ $# -ne 1 ]] && { echo "Usage: $0 IP|HOST" >&2; exit 1; } -[[ $UID -ne 0 ]] && exec sudo "$(readlink -f "$0")" "$@" - -check_loop "$1" -exit $? diff --git a/contrib/wg-config/wg-config b/contrib/wg-config/wg-config index d6447eb..8d8d4e7 100755 --- a/contrib/wg-config/wg-config +++ b/contrib/wg-config/wg-config @@ -15,7 +15,7 @@ auto_su() { unwind() { set +e - [[ -n $INTERFACE && -n $(ip link show dev "$INTERFACE" type wireguard 2>/dev/null) ]] && cmd ip link delete dev "$INTERFACE" + [[ -n $INTERFACE && -n $(ip link show dev "$INTERFACE" type wireguard 2>/dev/null) ]] && del_if exit } @@ -26,6 +26,9 @@ add_if() { del_if() { [[ -n $(ip link show dev "$INTERFACE" type wireguard 2>/dev/null) ]] || { echo "$PROGRAM: \`$INTERFACE' is not a WireGuard interface" >&2; exit 1; } + if [[ $(ip route show table all) =~ .*\ dev\ $INTERFACE\ table\ ([0-9]+)\ .* ]]; then + cmd ip rule delete table ${BASH_REMATCH[1]} + fi cmd ip link delete dev "$INTERFACE" } @@ -38,23 +41,20 @@ add_addr() { } add_route() { - cmd ip route add "$1" dev "$INTERFACE" + if [[ $1 == 0.0.0.0/0 || $1 == ::/0 ]]; then + add_default "$1" + else + cmd ip route add "$1" dev "$INTERFACE" + fi } add_default() { - if [[ $1 == ::/0 ]]; then - echo "tungate: does not yet support IPv6, skipping ::/0" >&2 - return 0 - elif [[ $1 == 0.0.0.0/0 ]]; then - local endpoint="$(join <(wg show "$INTERFACE" allowed-ips) <(wg show "$INTERFACE" endpoints) | sed -n 's/.* 0\.0\.0\.0\/0.* \([0-9.:\/a-z]\+\):[0-9]\+$/\1/p')" - add_route 0/1 - add_route 128/1 - killall tungate 2>/dev/null || true - echo "[&] Forking \`tungate' for $endpoint to background" >&2 - tungate "$endpoint" >/dev/null 2>&1 & disown - return 0 - fi - return 1 + [[ $(join <(wg show "$INTERFACE" allowed-ips) <(wg show "$INTERFACE" endpoints)) =~ .*\ ${1//./\\.}\ ([0-9.:a-f]+):[0-9]+$ ]] && local endpoint="${BASH_REMATCH[1]}" + [[ -n $endpoint ]] || return 0 + local table=51820 + while [[ -n $(ip route show table $table) ]]; do ((table++)); done + cmd ip route add "$1" dev "$INTERFACE" table $table + cmd ip rule add not to "$endpoint" table $table } set_config() { @@ -130,16 +130,12 @@ cmd_add() { done up_if if [[ $AUTO_ROUTE -eq 1 ]]; then - for i in $(wg show "$INTERFACE" allowed-ips | grep -Po '(?<=[\t ])[0-9.:/a-z]+' | sort -nr -k 2 -t /); do - if ! add_default "$i" && [[ $(ip route get "$i") != *dev\ $INTERFACE\ * ]]; then - add_route "$i" - fi + for i in $(wg show "$INTERFACE" allowed-ips | grep -Po '(?<=[\t ])[0-9.:/a-f]+' | sort -nr -k 2 -t /); do + [[ $(ip route get "$i" 2>/dev/null) == *dev\ $INTERFACE\ * ]] || add_route "$i" done fi for i in "${ADDITIONAL_ROUTES[@]}"; do - if ! add_default "$i"; then - add_route "$i" - fi + add_route "$i" done [[ $(type -t post_add) != function ]] || post_add trap - INT TERM EXIT @@ -148,7 +144,6 @@ cmd_add() { cmd_del() { auto_su [[ $(type -t pre_del) != function ]] || pre_del - killall tungate 2>/dev/null || true [[ -n $CONFIG_FILE ]] && save_config del_if [[ $(type -t post_del) != function ]] || post_del