WireGuard split tunnel with systemd-networkd
On most laptops I use wg-quick
to setup my WireGuard tunnels, but recently I got a bit curious about using systemd-networkd
to the the same.
In particular I want the same split-tunnel setup that I’ve used before to work also with systemd-networkd.
Worth noticing is that the setup I describe here will automatically start the tunnel when launching the computer. I haven’t really investigated if it is possible to do it on demand. Edit 2024-04-19: It is possible, thanks for some great feedback from axel
You need to create two different files to get this to work: /etc/systemd/network/99-wg0.netdev
and /etc/systemd/network/99-wg0.network
.
/etc/systemd/network/99-wg0.netdev
⌗
[NetDev]
Name=wg0
Kind=wireguard
Description=Wireguard tunnel wg0
[WireGuard]
PrivateKey=<PRIVATE KEY>
[WireGuardPeer]
PublicKey=<PUBLIC KEY OF REMOTE ENDPOINT>
PresharedKey=<PRESHARED KEY>
AllowedIPs=10.0.0.0/20
Endpoint=<IP ADDRESS:PORT OF REMOTE ENDPOINT>
Note that the captalization of WireGuard
is important! (Spent quite some time on this…)
Since I’m setting up a split tunnel, I set AllowedIPs to the IP-ranges I want to reach through the tunnel, in CIDR-notation. In this case 10.0.0.0/20
which translates to 10.0.0.0 – 10.0.15.255, which covers the relevant parts of my local network.
/etc/systemd/network/99-wg0.network
⌗
[Match]
Name=wg0
[Network]
Address=10.0.7.2/32
# ~zozs.se causes dns lookups for domains ending in .zozs.se to be routed
# to the DNS servers of this link, but doesn't affect other domains.
Domains=~zozs.se
DNS=10.0.7.254
[Route]
Destination=10.0.0.0/20
Scope=link
In this file, routes and DNS is setup. This is only relevant if you also use systemd-resolved
for DNS. In this example, it will cause all DNS requests for zozs.se
and subdomains to use a DNS server on the WireGuard tunnel, instead of the system’s regular DNS. This ensures my split-tunnel DNS works correctly, but doesn’t affect any other DNS requests.
Final notes⌗
Remember that you need to reload the configuration. I do this by using systemctl restart systemd-networkd.service
.
After this, you can check the status with networkctl
. It should show an output similar to this:
❯ networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp1s0f0 ether no-carrier configuring
3 wg0 wireguard routable configured
5 wlan0 wlan routable configured
4 links listed.