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. These instructions have been tested on all versions of OpenBSD from 6.8 to 7.1. They will probably work on future versions–but perhaps stuff will change.

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

set -e

umask 077
host=$1
id=$2
if [ -z "$host" ] || [ -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
set -e
host=$1
if [ -z "$host" ]; then
    echo usage: $0 host
    exit 1
fi
qrencode -t ansiutf8 </etc/wireguard/$host.conf

This script makes use of the qrencode binary from the OpenBSD package named libqrencode (install with pkg_add libqrencode).

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.