New year, new network. WireGuard promises to be a simpler more secure alternative to IPsec, and there’s a beta iOS client, so I thought I’d try my hand at setting up a server endpoint.

The caveats are that the documentation is sparse at times, and it’s mostly for Linux. The good news is it does deliver on the promise of simplicity. I was able to muddle along without too many missteps.

A more recent article is probably better to read.



wireguard

WireGuard encapsulates and encrypts traffic, tunneling over UDP. The primary implementation is a Linux kernel module. For everyone else, there’s a userland implementation in go, appropriately called wireguard-go. They are configured and controlled with the same wg utility, which is convenient.

WireGuard itself is mostly just concerned with connecting two peers. Which is the server and which is the client is more a matter of local network config, local routes, NAT, etc.



build

There’s a nascent port for OpenBSD, and also a curl it to sh script, but the build isn’t hard. We’re going to need git, gmake and bash to build. There’s two repositories to fetch.

git clone https://git.zx2c4.com/wireguard-go git clone https://git.zx2c4.com/WireGuard

Then build with gmake.

cd wireguard-go gmake Stuff happens...

cd WireGuard/src/tools gmake Stuff happens...

ifconfig

Before running wireguard, we need to make some interface changes on our server. Figuring this out was the hard part, since all the examples I could find online were for Linux and my browser crashes trying to display complicated iptables rules. In the end, it’s actually quite simple. Just a tunnel interface onto which traffic appears.

I decided to use the tun4 interface, which happens to not exist by default, so we need to make that first.

cd /dev sh MAKEDEV tun4 ifconfig tun4 create ifconfig tun4 up 10.99.0.1 10.99.0.2 netmask 255.255.255.0

In this example, 10.99.0.1 will be the server’s endpoint, and 10.99.0.2 will be the client.

If we don’t already have inet forwarding enabled, we need that. sysctl net.inet.ip.forwarding=1

We may also want to NAT traffic. pass out on egress inet from (tun4:network) nat-to (egress:0)



config

We can invoke the wg utility directly, or use it with ini style config files. There is also a wg-quick script, however that seems more targeted at client use. I’m not sure what it does, so we’ll ignore it.

We need keys for both ends. The official recipe looks a bit like this.

./wg genkey | tee server-private.key | ./wg pubkey > server-public.key ./wg genkey | tee client-private.key | ./wg pubkey > client-public.key

I guess it’s awesome to compose tools, though I might have preferred an option for just creating the files. As we’ll see though, the files don’t really matter.

The server.conf includes our private key and listening port, and their public key and address. I’m using a 32 bit netmask because I was only planning on one client. I’m not certain how it works with something like a 24.

[Interface] PrivateKey = QAdtiqb/qcdCVtkBzwBO1S+H0qiHRuhlXjjym6Zyu2Y= ListenPort = 9812 [Peer] PublicKey = BR8K1cLdY/aamBOf2p5mE8i0Iwjkf/o3azMh63fEXCg= AllowedIPs = 10.99.0.2/32

The client.conf is very similar, but reversed.

[Interface] Address = 10.99.0.2/32 PrivateKey = 4P3vw65rp6T7axvzcfkq1bhEhVL8GKGT9duHXSm4gFE= DNS = 10.99.0.1 [Peer] PublicKey = Mo25NWMiT781wv8cv+ubIEAZZ04z9ZqaG2fbNs/Fkh0= Endpoint = W.X.Y.Z:9812 AllowedIPs = 0.0.0.0/0

Note that the keys are not the filenames, but the actual contents, the key itself. If you have two terminals and are handy with copy and paste, there’s no need to actually create the files.

Getting the client config onto an iPhone is easiest via QR code. In the libqrencode package is a qrencode utility.

cat client.conf | qrencode -t ansiutf8 █████████████████████████████████████████████████████████████ █████████████████████████████████████████████████████████████ ████ ▄▄▄▄▄ █ ▀▄ ▄▄▄ ▀▄ ▀▀▄▄▀█▄▀▄▀█▀██▄▄▄▄▀█ ▀██ ▄▄▄▄▄ ████ ████ █ █ █ █▄▀█▄▀▀█ ▄ ▄ ▀██▀▄▄█▄ ▄ ▄ █ ▀▄▀█ █ █ ████ ████ █▄▄▄█ █▀ ▄ ▀▀█▄▄ █ █ ▄▄▄ ▀█ ▄▀▀▄ ▄██▀ ███ █▄▄▄█ ████ ████▄▄▄▄▄▄▄█▄▀▄▀ ▀▄█ █ █▄█▄▀ █▄█ █ ▀ ▀▄▀ ▀▄█▄█▄▀ █▄▄▄▄▄▄▄████ ████ ▀█ ▄█▀▄▀▄▄▄ ▄██▀ ▄ ▄▀ ▄ ▄▄▄ ▄▀█▄ ▄██▄ █ ▀█▄▀▄ ▄ ████ ████▀▀▄█▄█▄█ █▀█▄█▄▀ █▄ ▄▀▀██▄▄▄█▄ ▀█▄ █ ▀▀ ▄▀█▀█▄▀ ████ █████▀█ █▄▄█▄▀▄█ ▄▄██▀ ▀▄▀ ▄█▀ ▄ █▄ ▄▄▀▀▄▀ █ █▄▀▄▄ ███▀ ▀████ ████▀▀ ███▄█ █ ▀ ▄ █ ▀▄▄▀█▀ █ ▀▄▀▀▀▄▄█▄▀ ▄█▄▄ █ ▀▀ █▄ ████ ████▄▀▀▄▀█▄ ▄ ██▀▀▀▀█ ▄████ ▀▄▄ ▀▄▄█ ▀▀▀█ ▄▀▀█ █▀▀▀████ ████ ▄▀▀█▄▄█ ▄▀▀ █▀▄█ ▄▀▀▀▄████ █▄▀▀█▀▄▀▄ ▀▄ ▀██▀█ ▀█▀▀▄████ ██████ ██▄▄ █ █▀█▄██▀▀▀ ▀▀▄█ ▄█▀ ▄▀▄▄▄ ▀ █▄▄█▀ ▄██ ▀▀ ████ █████▄▄█ ▀▄ ▄██ ▄▀█ ▄▄ ▄▄▀▀▄█▄ █▀▄ ▀ █▄▄▄█▀ █▄█ ▀ █▀▄ █████ ████ █▀ ▄▄▄ ▀▄ █▄ ▄██▀ █▀ ▄▄▄ ▄▀▄█▄ ██ ▄▀▀▀▀▄ ▄▄▄ ▀█ ████ ████ ▄▀▄ █▄█ █▀▄▀█▀▀ ▄█▀ █ █▄█ ▀ ▀ ▀ █▄▄ █▀ █ █▄█ ▄▀█ ████ █████▀▄▄ ▄ ████▄█▄█▀ ▀▀▀▄ ▄▄▄█▀ █▄▄▀█ ▀▀█▄▀▀▄▄ ▄▀▀ ████ ████ ▄▄▄▀ █ ▄ █▀▀▄█▄▄▀██▀▀█▀██▀█▀█▄█▄ ▀▀ █▀▄ ▀▄ ████ ████▀▀ ▀▄▀▄█ ▄ ▀▀▀▀█ ▄ ▀█▀▀ ██ ▄▄ ▄▄▄█ ▀▄▀▄█▀▄█ ▄▄▄▀█▄████ ████ █▄▀ ▄█▄██▀█▀▄▄██▀ ▄▄▀▀▀▄ ▀▀▄█ █ ▀ ▄▄█ ▀▄ █▄ ▄▀█▄████ ████ █ █▄▄▄▀ █▀▀ ▄▄█▀ ▀█ ▄ ▀▄▀██ ▄ ▄▀█▀▀ █ █ ██ ▀▀█ ████ ████ ██▄█ ▄█▄█ ▀▄▀█ ▄▄ █ ▄▄▀ █▀▀▀▀▄▀▀█▄█▄█▄▀▀▄▀▄█▄█▀ █▄ ████ █████▀▄█▄█▄ █▀▀▄▄ ██▄▀ ██▀ █ ▄█▄▄▄█ █▀ ███ █▄ ▀▄ ▀ █████ ████▄ ▀▄▄▄▄ █ ▄██▄ ▀▄█▀▄▄▄█▀▄▀▀█▀█▄█▀█ ▀ █▄▀▄▀█ ▄ ██ █ ████ ███████▄██▄▄ ▄▄▄▀▀█▄█▀▀ ▄█▀▄ ▄▄▄ ██ ████▀ ▄▀▄▄▄▄ ▄▄▄ ▀▀▄█████ ████ ▄▄▄▄▄ █▀██▀▀▄▀█▀▀▄▀ ▀ █▄█ ▀▀ ▄▀▄▄ ▀▄▀▄█▄▄ █▄█ ▄ █████ ████ █ █ █▄▀ ██▀██▀█ ▄▄▀█▀ ▄█▄ ▄███▀▄▀▀▀▀ ▄▄▄ ▄█ ▄████ ████ █▄▄▄█ █▀ ▄ ▄█▀ ▀▀▄▀▀ ▄ ██▄▄▀▄▀▄▀█▄▀ █▀ ▀▀ █▀███▀ ████ ████▄▄▄▄▄▄▄█▄████▄▄▄████▄█▄███████▄▄▄███▄█▄██▄█▄█▄▄▄▄█▄▄█████ █████████████████████████████████████████████████████████████ █████████████████████████████████████████████████████████████

running

Finally, we have all the pieces in place.

Run wireguard-go.

./wireguard-go -f tun4 WARNING WARNING WARNING WARNING WARNING WARNING WARNING W G W This is alpha software. It will very likely not G W do what it is supposed to do, and things may go G W horribly wrong. You have been warned. Proceed G W at your own risk. G W G WARNING WARNING WARNING WARNING WARNING WARNING WARNING

Run wg to configure.

./wg setconf tun4 server.conf

Turn on your phone and see if it’s working.



conclusion

Seems to work pretty well for beta software that tells you not to use it.

The one feature I really wanted to set, http proxy, isn’t available at this time in the iOS client. Oh, well, maybe later.

The other option to consider is probably IPsec with iked. A simple iked.conf isn’t many lines at all, but IPsec being IPsec, there are a great many knobs and buttons to push and I always get confused wondering if I’ve forgotten something.