Making per-link DNS servers added by Wireguard to systemd-resolved survive NetworkManager connection changes

April 13, 2021 

Update: the problem described in this article seems to be resolved in Fedora 36 (NetworkManager 1.38.0-2.fc36). It is still present in Fedora 35 (NetworkManager 1.32.12-2.fc35).

The title of this blog post may seem familiar to some, as I solved this problem for OpenVPN earlier. I won't repeat myself here, so please check the OpenVPN article to understand why this is happening.

Wireguard servers - unlike OpenVPN servers - are not able to push any settings such as DNS servers to their clients. However, Wireguard client itself is able to run PostUp commands to configure per-link DNS. The same approach can be used with OpenVPN "up" scripts as well, if you prefer having full control at the client-side. Here's a Wireguard example:

PostUp = systemd-resolve -i wg0 --set-dns=10.9.54.1 --set-domain=mycompany.com

This configures systemd-resolved to resolve all *.mycompany.com DNS requests using 10.9.54.1. But as described in the OpenVPN article those settings will get nuked when NetworkManager changes connection. The solution is essentially the same as well: add a NetworkManager dispatcher script to restart Wireguard connections when the (physical) connection changes:

#!/bin/sh
#
# Restart running wireguard clients
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin

IFACE="$1"
ACTION="$2"

# Ensure that this connection is _not_ a Wireguard connection. Without this check
# Wireguard would get into a restart loop, because its interface is also a
# NetworkManager connection and would trigger its own "up" action.
if echo $IFACE|grep -qE '^wlp2s0$'; then
    if [ "$ACTION" = "up" ]; then
        ls /etc/wireguard/*.conf|while read CONFIG; do
            IFACE=`basename $CONFIG .conf`
            if ip addr show $IFACE > /dev/null 2>&1; then
                wg-quick down $IFACE
                wg-quick up $IFACE
            fi
        done
    fi
fi

Place the script to /etc/NetworkManager/dispatcher.d/20-restart-wireguard-clients.sh and restart NetworkManager and you should be good to go.

Note that the script assumes you do not have unit files for Wireguard, which is the case on Fedora. On Ubuntu you have the unit files so you can adjust the script accordingly.

Samuli Seppänen
Samuli Seppänen
Author archive
menucross-circle