toying with wireguard on openbsd
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.
Tagged: openbsd