OpenBSD 6.8 includes WireGuard . WireGuard allows one to build VPNs. For a long time, OpenBSD has had excellent IPsec support. Unfortunately the same cannot be said of IPSec support on other platforms, and inevitably a VPN relies upon good software for all parties to VPN. WireGuard is pretty good on all platforms, making it very attractive. By pretty good, I mean: straightforward to use and well-engineered (fast, secure, code quality, crypto design, etc). Naturally though, just how well-engineered WireGuard is will be seen over the coming decades, so this is the hardest attribute to assess correctly.

Here I will describe my setup under OpenBSD: it is really just a summary of information already available in wg(4) , ifconfig(8) , hostname.if(5) , as well as the documentation for the wireguard-tools package.

We will use 10.1.1.0/16 and 2001:0db8:85a3:1::/80 as the VPN address ranges and the VPN server has a DNS name of vpn.ioctl.uk and will run on port 51820; replaces these appropriately.

First up, let’s create the wg(4) interface wg0. Generate a fresh private key:

$ openssl rand -base64 32

Then create the hostname.if(5) file:

$ doas tee /etc/hostname.wg0 <<EOF
destroy
create
wgport 51820 wgkey INSERT_HERE
inet 10.1.1.1 255.255.255.0
inet6 2001:0db8:84a3:1::1 80
EOF

Save the public key:

$ doas cat /etc/hostname.wg0 | awk '$3 ~ /wgkey/ {print $4}' | \
     wg pubkey | doas tee /etc/wireguard/vpn.pub

The wg command comes from the wireguard-tools package, available from ports: pkg_add wireguard-tools if you do not have it already.

I like to make it easy to add another host, so I add the following script in /etc/wireguard/add:

#!/bin/sh

umask 077
host=$1
id=$2
if [ -z "$host" -o -z "$id" ]; then
    echo usage: $0 host id
    exit 1
fi
if [ "$id" = 1 ]; then
    echo bad id
    exit 1
fi

key=/etc/wireguard/$host.key
pub=/etc/wireguard/$host.pub
psk=/etc/wireguard/$host.psk
ip=10.1.1.$id
ip6=2001:0db8:84a3:1::$id
if [ -e $key ]; then
    echo $key already exists
    exit 1
fi
wg genkey | tee $key | wg pubkey >$pub
wg genkey >$psk
chmod 400 $key $pub $psk
cat >>/etc/hostname.wg0 <<EOF
# $host
wgpeer $(cat $pub) wgpsk $(cat $psk) wgaip $ip/32 wgaip $ip6/128
EOF
cat >/etc/wireguard/$host.conf <<EOF
[Interface]
Address = $ip/32, $ip6/128
PrivateKey = $(cat $key)
DNS = 10.1.1.1

[Peer]
PublicKey = $(cat /etc/wireguard/vpn.pub)
PresharedKey = $(cat $psk)
AllowedIPs = 0.0.0.0/0, ::0/0
Endpoint = vpn.ioctl.uk:51820
PersistentKeepAlive = 15
EOF

And finally, another script for generating QR codes on the command line of the generated configurations. I put this in /etc/wireguard/qr:

#!/bin/sh
host=$1
if [ -z "$host" ]; then
    echo usage: $0 host
    exit 1
fi
qrencode -t ansiutf8 </etc/wireguard/$host.conf

Make the scripts executable:

$ chmod +x /etc/wireguard/{qr,add}

Now enrolling a new host is very straightforward. Pick an id for the host between 2 and 255. Suppose we wish to add a new host called alice as id 2 and another called bob as id 3:

$ doas /etc/wireguard/add alice 2
$ doas /etc/wireguard/add bob 3
$ doas sh /etc/netstart wg0

Client configuration is very simple.

  • Under Linux, for example, copy /etc/wireguard/alice.conf to /etc/wireguard/wg0.conf, then run on the Linux machine:
$ sudo wg-quick up wg0
  • On devices with a camera, use the QR code. On the VPN server run and scan the output:
$ doas /etc/wireguard/qr alice

Note, once a host is set up you can remove the corresponding .key and .conf files in /etc/wireguard on the VPN server. If you run into problems, on the VPN server run:

$ doas ifconfig wg0 debug

then check the output of dmesg(8) to see messages. The end of wg(4) has list of good diagnostics. To switch off debugging:

$ doas ifconfig wg0 -debug

Thanks

Nate Houghton for spotting a typo in the add script and suggesting variable usage.