OpenBSD + Wireguard

I'm reminded of the excellent cartoon from XKCD.  Is Wireguard just another way to secure communications? Maybe... but let's take a look.

Before we start there are a few things to know that were not obvious to me when I first looked at this.  Wireguard utilizes public and private keys for each system PLUS a shared key.  When I think about IPSec and IKE, this makes some sense but I missed when I initially read the docs.

Server

First step is to create the private key for the server (and the directory to store it).

# install -d /etc/wireguard -o root -g wheel -mode 0700
/etc/wireguard
openssl rand -base64 32 > /etc/wireguard/$(hostname).key
private key

Now let's create the hostname.wgX file to create the interface on reboot

# Load the private key
wgkey `cat /etc/wireguard/$(hostname).key`
# Tell the server what port to listen on... can be anything
wgport 54321
# Add peers to the interface
!/etc/wireguard/wgadd_peers.sh $if
# now finally add an IP to the interface
inet 192.0.2.1 255.255.255.0
/etc/hostname.wg0

The wgadd_peers.sh script can be found here.

Be sure to enable forwarding.

# sysctl net.inet.ip.forwarding=1
net.inet.ip.forwarding: 0 -> 1
sysctl

Now we need to load up the interface to get the public key.

/bin/sh /etc/netstart wg0
# ifconfig wg0
wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
        index 6 priority 0 llprio 3
        wgport 54321
        wgpubkey o64ZWNcnsuvzju0vMvhsmf1krPgTiwTpfkgk5I4HsFE=
        wgpeer ExhyEDsPO7Cy2VJNqUBz209hPJDDKeXKS7s0kttRghY=
                wgpsk (present)
                tx: 0, rx: 0
                wgaip 192.0.2.10/32
        groups: wg
        inet 192.0.2.1 netmask 0xffffff00 broadcast 192.0.2.255

Now we have the public key for the server we can goto the client.

Client

The client configuration is very similar to the server. Create the wireguard directory and the private key.

# install -d /etc/wireguard -o root -g wheel -m 0700
openssl rand -base64 32 > /etc/wireguard/$(hostname).key
private key

Now let's create the hostname.wgX file to create the interface on reboot.  There are minor tweaks to the hostname file.

# Load the private key
wgkey `cat /etc/wireguard/$(hostname).key`
# Add peers to the interface
!/etc/wireguard/wgadd_peers.sh $if
# now finally add an IP to the interface
inet 192.0.2.10 255.255.255.0
/etc/hostname.wg0

Now we create a peers file on the client.  In the peers file we will add the public key from the server.

# hostname pubkey psk address/mask port
server o64ZWNcnsuvzju0vMvhsmf1krPgTiwTpfkgk5I4HsFE= SuJGiJ6IusilMT9kV0u4cL1u8d1uw7UOm5KDjkdepUE= 0.0.0.0/0 54321
/etc/wireguard/peers

We will also create a pre-shared key for our client.

# openssl rand -base64 32
SuJGiJ6IusilMT9kV0u4cL1u8d1uw7UOm5KDjkdepUE=
pre-shared key
# ifconfig wg0
wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
        index 7 priority 0 llprio 3
        wgport 38566
        wgpubkey ExhyEDsPO7Cy2VJNqUBz209hPJDDKeXKS7s0kttRghY=
        wgpeer o64ZWNcnsuvzju0vMvhsmf1krPgTiwTpfkgk5I4HsFE=
                wgpsk (present)
                wgendpoint 198.51.100.99 54321
                tx: 0, rx: 0
                wgaip 0.0.0.0/0
        groups: wg
        inet 192.0.2.10 netmask 0xffffff00 broadcast 192.0.2.255

Server (again)

Back to the server to create the peers file on the server.  Take the public key from the clients wg0 output.

# hostname pubkey  psk  address/mask port
client1 ExhyEDsPO7Cy2VJNqUBz209hPJDDKeXKS7s0kttRghY= SuJGiJ6IusilMT9kV0u4cL1u8d1uw7UOm5KDjkdepUE= 192.0.2.10/32
/etc/wireguard/peers

Now rerun the netstart command to update the peers on the wg0 interface

Client (again)

Let's test from the command line

# ping -c 5 192.0.2.1
PING 192.0.2.1 (192.0.2.1): 56 data bytes
64 bytes from 192.0.2.1: icmp_seq=0 ttl=255 time=42.461 ms
64 bytes from 192.0.2.1: icmp_seq=1 ttl=255 time=41.570 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=255 time=46.346 ms
64 bytes from 192.0.2.1: icmp_seq=3 ttl=255 time=46.382 ms
64 bytes from 192.0.2.1: icmp_seq=4 ttl=255 time=46.034 ms

--- 192.0.2.1 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 41.570/44.559/46.382/2.099 ms

Other Notes

  • ping: sendmsg: Permission denied
    Don't forget to update pf.conf to allow traffic from/to the wg0 interface
  • ping: timeout
    make sure the that the sever pf.conf is allowing udp traffic on the 54321 port.

Conclusion

Wireguard is defiantly interesting.  I wouldn't say that it can replace IKE+IPSec.  At this time I think it suffers from the same issues that cause IKE+IPSec to be difficult.  There is a lot of configuration involved that has to be individualized for each node/client.  And distributing the keys will require a separate solution/process.