From 13db708a0f68a1615ea58e8774bd2b46e3e950ab Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 24 Apr 2017 05:01:16 +0200 Subject: wg-quick: auto MTU discovery Signed-off-by: Jason A. Donenfeld --- src/wg-quick.8 | 6 +++++- src/wg-quick.bash | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/wg-quick.8 b/src/wg-quick.8 index 40c6650..e32971e 100644 --- a/src/wg-quick.8 +++ b/src/wg-quick.8 @@ -22,7 +22,7 @@ suitable for a few common use cases. Use \fIup\fP to add and set up an interface, and use \fIdown\fP to tear down and remove an interface. Running \fIup\fP adds a WireGuard interface, brings up the interface with the -supplied IP addresses, sets up routes, and optionally runs pre/post up scripts. Running \fIdown\fP +supplied IP addresses, sets up mtu and routes, and optionally runs pre/post up scripts. Running \fIdown\fP optionally saves the current configuration, removes the WireGuard interface, and optionally runs pre/post down scripts. @@ -65,6 +65,10 @@ which are handled by this tool: 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 +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. +.IP \(bu 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 diff --git a/src/wg-quick.bash b/src/wg-quick.bash index 257ea7d..8cb439a 100755 --- a/src/wg-quick.bash +++ b/src/wg-quick.bash @@ -13,6 +13,7 @@ export PATH="${SELF%/*}:$PATH" WG_CONFIG="" INTERFACE="" ADDRESSES=( ) +MTU="" PRE_UP="" POST_UP="" PRE_DOWN="" @@ -39,6 +40,7 @@ parse_options() { if [[ $interface_section -eq 1 ]]; then case "$key" in Address) ADDRESSES+=( ${value//,/ } ); continue ;; + MTU) MTU="$value"; continue ;; PreUp) PRE_UP="$value"; continue ;; PreDown) PRE_DOWN="$value"; continue ;; PostUp) POST_UP="$value"; continue ;; @@ -108,6 +110,25 @@ add_addr() { cmd ip address add "$1" dev "$INTERFACE" } +set_mtu() { + local mtu=0 endpoint output + if [[ -n $MTU ]]; then + cmd ip link set mtu "$MTU" dev "$INTERFACE" + return + fi + while read -r _ endpoint; do + [[ $endpoint =~ ^([a-z0-9:.]+):[0-9]+$ ]] || continue + output="$(ip route get "${BASH_REMATCH[1]}" || true)" + [[ ( $output =~ mtu\ ([0-9]+) || ( $output =~ dev\ ([^ ]+) && $(ip link show dev "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) ) ) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}" + done < <(wg show "$INTERFACE" endpoints) + if [[ $mtu -eq 0 ]]; then + read -r output < <(ip route show default || true) || true + [[ ( $output =~ mtu\ ([0-9]+) || ( $output =~ dev\ ([^ ]+) && $(ip link show dev "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) ) ) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}" + fi + [[ $mtu -gt 0 ]] || mtu=1500 + cmd ip link set mtu $(( mtu - 80 )) dev "$INTERFACE" +} + add_route() { if [[ $1 == 0.0.0.0/0 || $1 == ::/0 ]]; then add_default "$1" @@ -146,6 +167,7 @@ save_config() { for address in ${BASH_REMATCH[1]}; do new_config+="Address = $address"$'\n' done + [[ -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' [[ -z $POST_UP ]] || new_config+="PostUp = $POST_UP"$'\n' @@ -200,6 +222,7 @@ cmd_up() { for i in "${ADDRESSES[@]}"; do add_addr "$i" done + set_mtu up_if 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" -- cgit v1.2.3-59-g8ed1b