WireGuard is a relatively new and exciting VPN protocol because it has significantly more performance than OpenVPN and IPSEC. Additionally, WireGuard is much leaner and simpler in terms of its code and configuration than its other competitors. Usually a leaner code base means it’s easier to audit for security issues. After reading posts on Ted Unangst’s flak and WireGuard on OpenBSD, I just had to give it a shot. Basically, my setup almost mirrors that of these two posts but I made some additions so it would launch at startup.
WireGuard has a relatively recent port in the OpenBSD ports tree, so rather than build it, I went ahead and used the port. However, WireGuard is easy enough to build and Ted Unangst provides instructions for building it. First off, I need an IP addressing scheme and I settled on 10.6.0.0/24. While I was in the evaluation phase, I ran OpenVPN and WireGuard side by side. OpenVPN’s example config file uses 10.8.0.0/24. My instructions will assume a brand new setup and start with the server setup.
Enable the all important IP Forwarding. If I don’t do this first, I end up forgetting and then spending several head-scratching hours trying to troubleshoot.
# sysctl net.inet.ip.forwarding=1 # echo net.inet.ip.forwarding=1 >> /etc/sysctl.conf
Create the tun0 interface and a corresponding hostname.if so we can get this setup persistent across reboots.
# ifconfig tun0 inet 10.6.0.1 10.6.0.2 netmask 255.255.255.255 # route add -host 10.6.0.1/32 127.0.0.1
## /etc/hostname.tun0 inet 10.6.0.1 255.255.255.255 NONE dest 10.6.0.2 !route add -host 10.6.0.1/32 127.0.0.1
Now that we have the interfaces defined and started, we can add the packaes and begin to build the configuration. WireGuard uses private/public key pairs for real simple authentication. Since the keys are stored in plain text, it is a good idea to set the configuration directory permissions to be only accessible to root.
# pkg_add -Dsnap wireguard-go wireguard-tools # mkdir /etc/wireguard # chmod 0700 /etc/wireguard # cd /etc/wireguard # wg genkey | tee server-private.key | wg pubkey > server-public.key # wg genkey | tee client-private.key | wg pubkey > client-public.key # chmod 0600 *.key
Below is the configuration file I used for the server. If you are going to be routing subnets behind the client, add them here in the allowed IPs. In my setup, I have a subnet of 10.0.0.0/24 behind my client that I might want to access. Since the peer is behind a NAT firewall, keepalives are necessary so that the tunnel does not go down.
[Interface] PrivateKey = <Server Private Key Goes Here> ListenPort = 8000 [Peer] PublicKey = <Client Public Key Goes Here> AllowedIPs = 10.6.0.2/32, 10.0.0.0/24 PersistentKeepalive = 20
Now you will need to add statements similar to the ones below for pf.conf for your server. I do not route all of my traffic from the client over the VPN but I will show you how it can be done. Make certain to replace the interfaces with yours.
# NAT if you want/need it match out on vio0 from 10.0.0.0/24 to any nat-to (vio0:0) pass in on vio0 inet proto udp from any to port 8000 pass in on tun0 from 10.0.0.0/24 to any pass in on tun0 from 10.6.0.0/24 to any
Now it’s time to enable and start WireGuard. We will also create an additional file for use during startup which will insert the interface and configuration file into WireGuard
# rcctl enable wireguard_go # rcctl start wireguard_go # wg setconf tun0 /etc/wireguard/server.conf
Now create /etc/rc.local
#!/bin/sh if [ -r /etc/wireguard/server.conf ]; then /usr/local/bin/wg setconf tun0 /etc/wireguard/server.conf fi
On the client side, you will want to be certain to enable IP Forwarding and make it persistent across reboots. You will also want to securely copy the server’s public and client’s private key to the client. Follow some of the same steps above for making wireguard start-up on boot. On my client side, I used the following configuration file. In the example, I have set the endpoint to 192.0.2.1. Again, change it to yours.
# ifconfig tun0 inet 10.6.0.2 10.6.0.1 netmask 255.255.255.255 # route add -host 10.6.0.2/32 127.0.0.1
## hostname.tun0 inet 10.6.0.2 255.255.255.255 NONE !route add -host 10.6.0.2/32 127.0.0.1
Below is the client configuration file. I placed it in /etc/wireguard and called it client.conf
[Interface] PrivateKey = <Client Private Key Goes Here> [Peer] PublicKey = <Server Public Key Goes Here> AllowedIPs = 0.0.0.0/0 Endpoint = 192.0.2.1:8000 PersistentKeepalive = 20
If you want to route everything over the VPN, here is the magic that will make it happen. There are two things that you have to do. First, you have to create a host route from the client’s default gateway to the server. Then, you can set the default route to the local VPN tunnel endpoint. My default gateway just happens to be 192.168.1.1.
route add -priority 2 -host 192.0.2.1 192.168.1.1 route add -priority 7 default 10.6.0.2
Now enable and start WireGuard on the client. Try pinging the server’s VPN tunnel endpoint. If all goes well, you’ll have really cool VPN going.