Has anyone gotten a WireGuard VPN setup to work using systemd's netdev and network files (rather than wg-quick@ template units)?

#AskFedi #Linux #Systemd #Debian #WireGuard #VPN

I mainly need the client side config b/c I'm using a commercial VPN (Proton).

In the netdev, I have the [NetDev] section (Name and Kind), [WireGuard] section (PrivateKey), and [WireGuardPeer] section (PublicKey, AllowedIPs, and Endpoint). In the network, I have the [Match] section (Name), [Network] section (Address, DNS, and Domains=~.), and [Route] section (Gateway, manually added when debugging). Also ActivationPolicy=manual for now.

DNS resolution goes through the VPN, but I think the routing is off (as verified by looking at the routing tables with `ip route show table all` with wg-quick@ and with networkd). Just not sure how to fix it!
@chiraag
in my config, I was using the VPN as a point-to-point connection between households and I gave [Route] configs in the .network file. I think wgquick by default routes all allowed IPs through the tunnel. Whereas networkd doesn't do any route twiddling unless you explicitly tell it to.
@dlakelan Yeah, exactly. So I need to figure out how to convert the routing changes wg-quick does into directives in the .network file... :/

@chiraag
assuming you want to route everything through the tunnel it should be pretty easy, something like

[Route]
Gateway=...
Metric=1 #lower is preferred!

@dlakelan I tried adding `DefaultRouteOnDevice = true` which makes the routing table look more like what I see from wg-quick, but...then I can't connect to anything? It's so odd...
@chiraag
Oh you know what? maybe its trying to route the wireguard packets over the wireguard tunnel itself? Set up a route to the proton server on the Ethernet device so you are able to actually send the container packets.
@dlakelan Hmmm...that's probably what's happening. How would that look in the routing table (e.g. `ip route show table all`)?

@chiraag

nft isn't part of it, unless they're marking the server packets and routing based on rules related to firewall marks or something...

But you should be able to just put something like:

[Route]
Destination=_proton_server_ip/32
Gateway=_your_isp_gateway_

in your eth0.network or whatever the underlying transport is.

If it's on a laptop you might need to do something in NetworkManager somewhere I don't know.

@dlakelan Yeah, I think it's doing the routing using firewall marks. Let me see if I can at least get it working using your solution though.

@chiraag

You can test it out with just a command line probably, something like:

```
ip route add PROTON_IP/32 via ISP_GATEWAY dev ISP_DEV metric 1

@dlakelan Yes, this works! Now...my question is how can I do this such that I can change server IPs dynamically? There must be a way!
@dlakelan I'm writing a script to convert wireguard config to systemd stuff, and it's already structred data in there, so I can probably ask for the base .network file and modify it in this way.

@chiraag

WOOT! if you know the servers, maybe you can do the nft marking method, or you can add a bunch of /32 routes one for each server you want to use.

@dlakelan Yup, I'm taking the latter approach. It'll still be manual, but I don't really change the servers I want to connect to all that much (though I sometimes rotate between them, the _list_ of servers is relatively static).
@dlakelan Well this is fun. Somehow I now broke DNS resolution even with that trick... `ip route get <IP address>` works now (through the link), but DNS resolution isn't working (once I added `DefaultRouteOnDevice = true`).
@chiraag
what DNS servers are you using? if youre using the ones from proton it should work. if youre using your ISP they may block the proton VPN from connecting.
@dlakelan I'm using the Proton DNS servers, so it _should_ work (and the same VPN config works through wg-quick, so clearly the issue is in the config side, not the VPN side).

@dlakelan I think I'll give up on this particular project for a bit haha :D wg-quick@ works well enough (and is honestly more flexible) - this was more a curiosity to see if it's possible (clearly it is!). I think my network-related knowledge is pretty poor (especially routing tables and such), so debugging this is harder for me than it should be.

Thanks for the help! I'm definitely keeping the script around in case I pick it up again at some point.