I configured a WireGuard VPN on my OpenBSD laptop shortly after it was committed to -current in June of 2020. It was a relatively easy implementation, and at the time, I set up my routing table with priorities to be able to turn the VPN on and off easily by just setting the WireGuard NIC wg0 "down" to disable the VPN, then "up" to enable it:
- I set my route to the remote VPN tunnel endpoint with the highest routing priority, through my physical egress NIC.
- I set up two default routes: a high priority route through the VPN via the wg0 pseudo-NIC, and a lower priority route through the egress NIC.
While this worked well, over time I determined two reasons to switch to a different routing schema.
- I needed to switch now and then between wired and wireless, and that changed my true egress NIC. And my wired NIC would sometimes need to manage multiple VLANs, and sometimes not, so using trunk(4) was not a provisioning option.
- I wanted more fine grain control -- by process -- of which applications were or were not transiting the VPN. My original provisioning turned the VPN on or off for everything on the laptop globally.
Several "how to" guides have been published that recommended using routing domains with WireGuard -- including
solene@'s guide, so armed with her guide and the rtable(4)/rdomain(4) man page, I switched from routing by priority to using routing domains. I even set up a `novpn` shell alias for `route exec -T 1` to make it easy and simple to start something I didn't want using the VPN.
There was one service lacking though -- I'm an unwind(8) user for its DNS over TLS (DoT) features, and I needed to have two instances of unwind(8) available in order to resolve DNS entries through either of my two domains.
----
Here is how I have unwind(8) provisioned to run two instances in support of both rdomain 0, the default domain through my WireGuard VPN, and rdomain 1, my "real" network connection:
- Provision unwind's IPv4 loopback address on lo1:
# echo rdomain 1 > /etc/hostname.lo1
# echo inet 127.0.0.1/8 >> /etc/hostname.lo1
# sh /etc/netstart lo1
- Duplicate the unwind rc.d(8) script:
# ln -s /etc/rc.d/unwind /etc/rc.d/unwind1
- Enable the second instance with a unique control socket and starting with rtable 1:
# rcctl enable unwind1
# rcctl set unwind1 flags -s /dev/unwind1.sock
# rcctl set unwind1 rtable 1
- Start the new instance, and ensure it is running:
# rcctl start unwind1
$ rcctl ls on | grep unwind
Now I have fine-grain control. I can start an application with
$ novpn program
which will run any of its network connections outside the VPN, while all other applications continue to use the VPN.