From 6b27d0d0f03a5ad4b2b3fe620aa345325b94d353 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 26 Jul 2017 03:09:48 +0200 Subject: [PATCH] wg-quick: add explicit support for common DNS usage Signed-off-by: Jason A. Donenfeld --- src/wg-quick.8 | 30 ++++++++++++++++++------------ src/wg-quick.bash | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/wg-quick.8 b/src/wg-quick.8 index 04653a8..f27a270 100644 --- a/src/wg-quick.8 +++ b/src/wg-quick.8 @@ -62,9 +62,16 @@ sub-command, with the exception of the following additions to the \fIInterface\f which are handled by this tool: .IP \(bu -Address \(em a comma-separated list of ip (v4 or v6) addresses (optionally with CIDR masks) +Address \(em a comma-separated list of IP (v4 or v6) addresses (optionally with CIDR masks) to be assigned to the interface. May be specified multiple times. .IP \(bu +DNS \(em a comma-separated list of IP (v4 or v6) addresses to be set as the interface's +DNS servers. May be specified multiple times. Upon bringing the interface up, this runs +`resolvconf -a tun.\fIINTERFACE\fP -m 0 -x` and upon bringing it down, this runs +`resolvconf -d tun.\fIINTERFACE\fP`. If these particular invocations of +.BR resolvconf (8) +are undesirable, the PostUp and PostDown keys below may be used instead. +.IP \(bu MTU \(em if not specified, the MTU is automatically determined from the endpoint addresses or the system default route, which is usually a sane choice. However, to manually specify an MTU to override this automatic discovery, this value may be specified explicitly. @@ -72,7 +79,8 @@ an MTU to override this automatic discovery, this value may be specified explici PreUp, PostUp, PreDown, PostDown \(em script snippets which will be executed by .BR bash (1) before/after setting up/tearing down the interface, most commonly used -to configure DNS. The special string `%i' is expanded to \fIINTERFACE\fP. +to configure custom DNS options or firewall rules. The special string `%i' +is expanded to \fIINTERFACE\fP. .IP \(bu SaveConfig \(em if set to `true', the configuration is saved from the current state of the interface upon shutdown. @@ -98,9 +106,7 @@ traffic: .br \fBAddress = 10.200.100.8/24\fP .br - \fBPostUp = echo nameserver 10.200.100.1 | resolvconf -a tun.%i -m 0 -x\fP -.br - \fBPostDown = resolvconf -d tun.%i\fP + \fBDNS = 10.200.100.1\fP .br PrivateKey = oK56DE9Ue9zK76rAc8pBl6opph+1v36lm7cXXsQKrQM= .br @@ -117,12 +123,11 @@ traffic: Endpoint = demo.wireguard.com:51820 .br -Notice that the `PostUp` and `PostDown` commands are used here to configure DNS using -.BR resolvconf (8), -which is one of the many options for DNS configuration. The `Address` field is added -here in order to set up the address for the interface. The peer's allowed IPs entry -implies that this interface should be configured as the default gateway, which this -script does. +The `Address` field is added here in order to set up the address for the interface. The `DNS` field +indicates that a DNS server for the interface should be configured via +.BR resolvconf (8). +The peer's allowed IPs entry implies that this interface should be configured as the default gateway, +which this script does. Here is a more complicated example, fit for usage on a server: @@ -184,7 +189,8 @@ This will load the configuration file `/etc/wireguard/wgnet0.conf'. .BR ip-link (8), .BR ip-address (8), .BR ip-route (8), -.BR ip-rule (8). +.BR ip-rule (8), +.BR resolvconf (8). .SH AUTHOR .B wg-quick diff --git a/src/wg-quick.bash b/src/wg-quick.bash index d7e7d68..e5ae48f 100755 --- a/src/wg-quick.bash +++ b/src/wg-quick.bash @@ -14,6 +14,7 @@ WG_CONFIG="" INTERFACE="" ADDRESSES=( ) MTU="" +DNS=( ) PRE_UP="" POST_UP="" PRE_DOWN="" @@ -41,6 +42,7 @@ parse_options() { case "$key" in Address) ADDRESSES+=( ${value//,/ } ); continue ;; MTU) MTU="$value"; continue ;; + DNS) DNS+=( ${value//,/ } ); continue ;; PreUp) PRE_UP="$value"; continue ;; PreDown) PRE_DOWN="$value"; continue ;; PostUp) POST_UP="$value"; continue ;; @@ -128,6 +130,14 @@ set_mtu() { cmd ip link set mtu $(( mtu - 80 )) dev "$INTERFACE" } +set_dns() { + [[ ${#DNS[@]} -eq 0 ]] || printf 'nameserver %s\n' "${DNS[@]}" | cmd resolvconf -a "tun.$INTERFACE" -m 0 -x +} + +unset_dns() { + [[ ${#DNS[@]} -eq 0 ]] || cmd resolvconf -d "tun.$INTERFACE" +} + add_route() { if [[ $1 == 0.0.0.0/0 || $1 =~ ^[0:]+/0$ ]]; then add_default "$1" @@ -168,6 +178,9 @@ save_config() { for address in ${BASH_REMATCH[1]}; do new_config+="Address = $address"$'\n' done + while read -r address; do + [[ $address =~ ^nameserver\ ([a-zA-Z0-9_=+:%.-]+)$ ]] && new_config+="DNS = ${BASH_REMATCH[1]}"$'\n' + done < <(resolvconf -l "tun.$INTERFACE" 2>/dev/null) [[ -n $MTU && $(ip link show dev "$INTERFACE") =~ mtu\ ([0-9]+) ]] && new_config+="MTU = ${BASH_REMATCH[1]}"$'\n' [[ $SAVE_CONFIG -eq 0 ]] || new_config+=$'SaveConfig = true\n' [[ -z $PRE_UP ]] || new_config+="PreUp = $PRE_UP"$'\n' @@ -203,6 +216,7 @@ cmd_usage() { - Address: may be specified one or more times and contains one or more IP addresses (with an optional CIDR mask) to be set for the interface. + - DNS: an optional DNS server to use while the device is up. - MTU: an optional MTU for the interface; if unspecified, auto-calculated. - PreUp, PostUp, PreDown, PostDown: script snippets which will be executed by bash(1) at the corresponding phases of the link, most commonly used @@ -226,6 +240,7 @@ cmd_up() { done set_mtu up_if + set_dns for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do [[ $(ip route get "$i" 2>/dev/null) == *dev\ $INTERFACE\ * ]] || add_route "$i" done @@ -237,6 +252,7 @@ cmd_down() { [[ -n $(ip link show dev "$INTERFACE" type wireguard 2>/dev/null) ]] || die "\`$INTERFACE' is not a WireGuard interface" execute_hook "$PRE_DOWN" [[ $SAVE_CONFIG -eq 0 ]] || save_config + unset_dns del_if execute_hook "$POST_DOWN" }