Virtual Private Networks (VPNs) allow a device to connect to a private network from afar. For example, one could travel to a remote location yet still be able to act as if connected to the home LAN. As a secondary benefit, internet traffic can be tunnelled through the VPN to hide it from untrusted networks such as public WiFi.
IPSec and OpenVPN are the most well-known VPN protocols, but are difficult to understand and complex to configure. OpenSSH can provide some of the necessary features at the cost of convenience and performance.
WireGuard is a new work-in-progress VPN protocol and software intended to be simple, secure and performant. It has a small code-base, uses only strong cryptographic algorithms, and provides perfect forward secrecy.
This guide will demonstrate how to run WireGuard on an already functioning OpenBSD home router to let clients access the home network remotely.
Each device in the network is assigned a key pair (a public and private key) and an internal IP address
Outbound traffic is encrypted with the target host’s public key and encapsulated in UDP before being transmitted
Inbound encrypted traffic is decrypted with the receiving host’s private key
Each host is configured with information about its peers: the public keys and the IP address ranges that they can route
For for tunnelling all internet traffic through one host (the VPN “server”), allow that device to route all addresses
VPN clients need to know the public IP address of the server to initiate a connection
In this example, the
10.0.0.0/24 subnet is used for the VPN. The home router will be assigned
10.0.0.1 and will be the server through which traffic is tunnelled.
On the router, create a tunnel interface with the chosen private IP address. Since
tun(4) is used as a point‑to‑point interface, a static route is needed to support multiple clients.
WireGuard authenticates packets on the tunnel network interface so it doesn’t need any filtering—add it to the PF
Open the port that WireGuard will listen on so that clients can connect to this server over the internet.
Traffic going out to the internet from the VPN will need NAT, but if you have a
match rule performing NAT on
!(egress:network), then this is already done.
For clients to be able to access the local
unbound DNS resolver, add an
access-control directive with the subnet of the VPN.
Install and enable the WireGuard userspace daemon on the OpenBSD (6.6+) router to run on your chosen tunnel interface.
Each device in the VPN needs a key pair.
Once the keys are generated, use
wg(8) to configure the wireguard-go daemon. This must be done each time it is restarted.
Instead of setting parameters through command-line arguments, you could also create and load the configuration through an ini file.
The config must be reloaded whenever the daemon is restarted.
Refer to the
wg(8) manual for details.
Instead of creating the tunnel interface and routes manually as above, you can use the included
wg-quick script. This creates a tunnel interface, sets the IP address, adds routes, and configures and runs the WireGuard daemon. Simply add an
Address parameter to the WireGuard configuration file then run the script.
See the wg-quick(8) manual for details.
Mobile (Android & iOS)
WireGuard applications for mobile operating systems handle setting up the tunnel interface and routes. Simply set a private key and internal IP address, and provide details of the public key and public IP address (or domain name) of the server so the client can connect.
The allowed IPs of the server will be all addresses (
0.0.0.0/0, ::/0) so that all traffic is tunnelled. If you only wish to access particular subnets in your home LAN, add the relevant addresses instead.
DNS parameter to the internal IP address of your router tells the mobile client to use the resolver that you presumably have running—useful if you perform DNS-based ad blocking. You may of course use a different resolver if you desire or if you don’t run a resolver.
If you create the configuration file on an OpenBSD system, an easy way to transfer it to the mobile applications is by generating then scanning a QR code
Follow the same process of adding an interface and installing WireGuard as for the server, and let the server route all addresses.
Set up routes for the traffic you want to tunnel through the VPN.
To tunnel all traffic, add a high priority (priority < 8) default route through the VPN server. You will need an even higher priority (smaller priority number) route for the server itself through the normal external interface (so that the WireGuard traffic doesn’t get routed back to the WireGuard interface).
OpenBSD with wg-quick
As above, but the
wg-quick script configures the interface and routing.
Connect to the VPN. Check that you can ping the router on its VPN internal address, access other hosts on the LAN, and that your external IP appears as that of your home network.