Ramblings of an aging IT geek
← Ramblings of an aging IT geek
networking

i threw out my openvpn config and i feel lighter for it

Moving the homelab from a sprawling OpenVPN setup to WireGuard, why the smaller config wins, and the honest caveats of running pre-1.0 kernel code.

Network cables and a patch panel

My OpenVPN setup worked. That's the first thing I should say, because I'm about to be rude about it and it doesn't deserve all of it. It connected my laptop to home, it bridged a couple of remote boxes back to the lab, and it had done so reliably for years.

It was also a mess. Certificates I'd half-forgotten how to regenerate, a server.conf with a comment block longer than some of my programs, an easy-rsa directory I was scared to touch, and TLS negotiation overhead that made the link feel sluggish on a phone with a flaky signal. Every time I added a peer it was a small ceremony. So when WireGuard started looking genuinely usable, I gave myself a weekend to switch.

I did not need the whole weekend.

the config that fits on a postcard

Here is the entire server side. Not an excerpt. The whole thing.

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>

[Peer]
# laptop
PublicKey = <laptop-public-key>
AllowedIPs = 10.10.0.2/32

[Peer]
# remote box
PublicKey = <remote-public-key>
AllowedIPs = 10.10.0.3/32

That's it. No certificate authority. No cipher suite to argue about. Each peer is just a public key and the IPs it's allowed to use, which doubles as both authentication and routing. Generating a key pair is two commands:

wg genkey | tee privatekey | wg pubkey > publickey

Adding a new peer is: generate a key pair on the device, paste its public key into a [Peer] block, paste the server's public key into the device, done. The thing I'd built up as a chore on OpenVPN is now thirty seconds and no openssl incantations I have to look up every single time.

Server hardware in a rack

why it feels different

A few reasons, beyond the config being short enough to read in one breath.

It runs in the kernel. OpenVPN is a userspace process shuffling every packet up and back down the stack. WireGuard is a kernel module, so the data path is a great deal tighter. On the link from my phone the difference is obvious: lower latency, and it survives switching from wifi to mobile data without me noticing. That last point is the one I didn't expect to love. There's no "session" to renegotiate. The endpoint just updates and traffic carries on.

The cryptography isn't negotiable, and that's a feature. OpenVPN's flexibility means it has a TLS handshake and a hundred ways to configure yourself into something weak. WireGuard picks Curve25519, ChaCha20, Poly1305, BLAKE2s, and that's the menu. There's no cipher downgrade to worry about because there's nothing to downgrade to. Fewer choices, fewer ways to be wrong at 11pm.

And it's quiet on the wire when idle. WireGuard doesn't chatter; an unused tunnel sends nothing, which makes it pleasantly invisible to anyone port-scanning. If a packet doesn't authenticate, it's dropped with no reply, so the port doesn't even announce itself.

the honest caveats

I'd be doing you a disservice if I pretended this was all upside in mid-2017.

It is not in the mainline kernel yet. You're installing a DKMS module or running a kernel with it patched in, and that means a kernel update can occasionally leave you rebuilding the module before your tunnel comes back. On my Debian boxes the DKMS route has been smooth, but I keep a console available the first time I update a kernel on anything important, because finding out your remote-access VPN is down via the very VPN that's down is a special kind of foolish.

It is explicitly pre-1.0. The author says, repeatedly and clearly, that it has not been fully audited and you should not bet your life on it yet. For a homelab and a personal laptop that's a risk I'm comfortable taking. For a client's production estate I'd wait, and I'd say so.

There's no built-in IP assignment. OpenVPN can hand out addresses; WireGuard expects you to know which IP each peer gets and put it in AllowedIPs by hand. For a handful of peers that's a non-issue. For hundreds you'd want tooling around it.

And the mental model is different. AllowedIPs is doing double duty as a routing table and an access-control list, and if you get it wrong the symptom is "traffic mysteriously goes nowhere" rather than a clear error. Once it clicked I preferred it, but it tripped me up for a good twenty minutes the first time I tried to route a whole subnet rather than a single host.

A rack of networking equipment

was it worth the swap

Yes, comfortably. The OpenVPN config is gone, the easy-rsa directory is in a backup I'll never open again, and the new setup is small enough that I actually understand all of it, which I could not honestly say of the old one.

The real win isn't speed, though the speed is nice. It's that the whole thing now fits in my head. When something does eventually go wrong, and it will, I'll be debugging four lines per peer instead of a config file I'd grown afraid of. That's the property I want from my own infrastructure: not clever, just legible.

I'll keep an eye on the audit and the mainline merge. The day it lands in a stock kernel, this stops being a homelab toy and starts being the obvious default. It already feels like one here.