Setting up a WireGuard client with NetworkManager (using nmcli)

July 16, 2021

For reasons beyond the scope of this entry, I've been building a VPN server that will support WireGuard (along with OpenVPN and L2TP). A server needs a client, so I spent part of today setting up my work laptop as a WireGuard client in a 'VPN' configuration, under NetworkManager because that's what my laptop uses. I was hoping to do this through the Cinnamon GUIs for NetworkManager, but unfortunately while NetworkManager itself has supported WireGuard for some time, this support hasn't propagated into GUIs such as the GNOME Control Center (cf) or the NetworkManager applet that Cinnamon uses.

I'm already quite familiar with WireGuard in general, so I found that the easiest way to start was to set up a basic WireGuard configuration file for the connection in /etc/wireguard/wg0.conf, including both the main configuration (with the laptop's key and my local port) and a [Peer] section for the server. Since I'm using WireGuard here in a VPN configuration, instead of to reach just some internal IPs, I set AllowedIPs to 0.0.0.0/0. After writing wg0.conf, I then imported it into NetworkManager:

nmcli connection import type wireguard file /etc/wireguard/wg0.conf

(For what can go in the configuration file, start with wg(8) and wg-quick(8). I suspect that NetworkManager doesn't support some of the more advanced keys. I stuck to the basics. The import process definitely ignores the various script settings supported by wg-quick(8). Currently, see nm_vpn_wireguard_import() in nm-vpn-helpers.c.)

Imported connections are apparently set to auto-connect, which isn't what I wanted, plus there were some other things to adjust (following the guide of Thomas Haller's WireGuard in NetworkManager):

nmcli con modify wg0 \
   autoconnect no \
   ipv4.method manual \
   ipv4.address 172.29.50.10/24 \
   ipv4.dns <...>

At this point you might be tempted to set ipv4.gateway, and indeed that's what I did the first time around. It turns out that this is a mistake, because these days NetworkManager will do the right thing based on the 'accept everything' AllowedIPs I set, right down to setting up policy based routing with a fwmark so that encrypted traffic to the WireGuard VPN server doesn't try to go over WireGuard. If you set ipv4.gateway as well, you wind up with two default routes and then your encrypted WireGuard traffic may try to go over your WireGuard connection again, which doesn't work.

(See the description of 'ip4-auto-default-route in the WireGuard configuration properties. The full index of available NetworkManager settings in various sections is currently here; the ones most useful to me are probably connection.* and ipv4.*.)

Getting DNS to work correctly requires a little extra step, or at least did for me. While the wg0 connection is active, I want all of my DNS queries to go to our internal resolving DNS server and also to have a search path of our university subdomain. This apparently requires explicitly including '~' in the NetworkManager DNS search path:

nmcli con modify wg0 \
  ipv4.dns-search "cs.toronto.edu,~"

This comes from Fedora bug #1895518, which also has some useful resolvectl options.

You (I) can see a lot of settings for the WireGuard setup with 'nmcli connection show wg0', including active ones, but this seems to omit NetworkManager's view of the WireGuard peers. To see that, I needed to look directly at the configuration file that NetworkManager wrote, in /etc/NetworkManager/system-connections/wg0.nmconnection. I'm someday going to need to edit this directly to modify the WireGuard VPN server's endpoint from my test machine to the production machine.

(The NetworkManager RFE for configuring WireGuard peers in nmcli is issue #358.)

With no GUI support for WireGuard connections, I have to bring this WireGuard VPN up and down with 'nmcli con up wg0' and 'nmcli con down wg0'. Once I have the new VPN server in production, I'll be writing little scripts to do this for me. Hopefully this will be improved some day, so that the NetworkManager applet allows you to activate and deactivate WireGuard connections and shows you that one is active.

If I wanted a limited VPN that only sent traffic to our internal networks over my WireGuard link, I would configure the server's AllowedIPs to the list of networks and then I believe that NetworkManager would automatically set up routes for them. However, I don't know how to make this work (in NetworkManager) if the WireGuard VPN server itself was on one of the subnets I wanted to reach over WireGuard. For my laptop, routing all traffic over WireGuard to work is no worse than using our OpenVPN or L2TP VPN servers, which also do the same thing by default.

(On my home desktop, I use hand built fwmark-based policy rules to deal with my WireGuard endpoint being on a subnet I want to normally reach over WireGuard. NetworkManager will build the equivalents for me when I'm routing 0.0.0.0/0 over the WireGuard link, but I believe not in other situations.)

(For information, I primarily relied on Thomas Haller's WireGuard in NetworkManager, supplemented with a Fedora Magazine article and this article.)


Comments on this page:

By James at 2021-07-17 09:06:38:

nm-applet in Debian unstable does provide a GUI to wg, maybe you're running an older version?

By cks at 2021-07-17 18:50:00:

The Fedora 34 version of nm-applet appears to be 1.22.0 (and it seems to come from NetworkManager). When I call it up in Cinnamon, the only connections it offers for me to activate are Wired, Wireless, and VPNs, which don't include the WireGuard connection. The WireGuard connection does show in 'nmcli connection', as type 'wireguard'. However, it appears that this should work, based on eg Debian bug #983641, as the support for this was apparently added in 1.20.

What appears to be going on in my Cinnamon desktop is that although nm-applet is running, it's not what Cinnamon is using for its network applet menu. Instead that is provided by some internal component that doesn't seem to support WireGuard yet (and I don't think there's an open bug for that in Cinnamon, at least not that I could find). It may be possible to replace this internal applet with nm-applet to solve my problem.

Written on 16 July 2021.
« Making two Unix permissions mistakes in one
The WireGuard VPN challenge of provisioning clients »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Jul 16 01:00:49 2021
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.