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 Have you tried with `ip route get <IP address>` to see what’s the route used to access said IP address ?

On the client side, when I need to use the VPN for all outgoing traffic, I have no '[Route]` section.

@slubman When I did that, everything just went through the actual interface, not WireGuard. When I enable that [Route] section, it just spins and spins without actually loading anything.
@chiraag What did you put in the `AllowedIPs` for your `[WireguardPeer]` ?
@slubman AllowedIPs = 0.0.0.0/0
@chiraag I didn’t know of the ActivationPolicy option, but with it set to manual, did you bring the interface up ?
@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
this might be more of a Proton issue than a wireguard per se. is proton approving your tunnel? is the tunnel connected?
@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`)?
@dlakelan Ah. Is that happening through nft rules? There's a wg-quick-wgusca10 table with preraw, premangle, and postmangle chains.

@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.

@chiraag That’s my setup on the server and on some clients.

@chiraag

Yes, they have worked for me. Not currently how I'm doing it, but I did that for like 5 years with my last router setup.