WireGuard configuration for FreeBSD 13.2+

FreeBSD 13.2 imported WireGuard into the base system, but so far the official documentation on it is limited only the man pages wg(4) and wg(8). The invasive wg-quick(8) script used in most examples wasn't imported breaking those. Despite this FreeBSD 13.2 has everything needed to comfortably use WireGuard except for the documentation needed to make it accessible to new users. This article is an attempt to to fix that.

How the parts fit together

Most existing examples configure everything about a WireGuard tunnel using a single WireGuard configuration file per tunnel interface processed by the wg-quick(8) script. Instead the setup described in this article uses the WireGuard configuration only for those parameters directly understood by wg setconf. The remaining network interface configuration of the WireGuard tunnel interfaces is left to the existing FreeBSD rc.d scripts. WireGuard tunnel interfaces have to be explicitly created as they do not correspond to any physical network interface that can be discovered by enumerating the installed physical network interfaces. The recommended way to have the rc.d scripts create tunnel interfaces is to add them to (space separated) cloned_interfaces list in /etc/rc.conf. Variables in /etc/rc.conf are used to have the netif and routing rc.d scripts configure the interface IP addresses, MTU, and static routes as required. Which variables are recognised by the base system rc.d scripts and a short description of their semantics can be looked up in the rc.conf(5) man page.

The /etc/rc.conf configuration is a shell script sourced by the various rc.d scripts to obtain their configuration. As long as /etc/rc.conf contains only variable assignments it can be queried and updated like a key-value store using sysrc(8). Getting too clever here will cause (a lot) more pain than gain over time. Tested for you sigh.

As part of the boot process FreeBSD runs its rc.d service scripts one after the other. For this article it's enough to know that devd is started before netif configures network interfaces allowing us to rely on devd(8) to load the rest of the WireGuard tunnel configuration on demand.

Prepare the system to load WireGuard configurations on demand.

Create your first WireGuard interface.

Inspect the result.

Mastodon: https://bsd.network/web/@crest