$RodHat_
MOTD

Six years of WireGuard in the Linux kernel. I was wrong to be skeptical.

Published by

Six years of WireGuard in the Linux kernel. I was wrong to be skeptical.
Photo: AI-generated — no human photographer / RodHat AI Cover

When WireGuard landed in Linux 5.6 I was, let’s say, unenthusiastic. I had seen “simpler VPN” promises before. IPsec was supposed to be the permanent answer in the nineties and we all know how that turned out. OpenVPN solved the NAT problem and gave you a user-space daemon that ran everywhere at the cost of configuration complexity that measured itself in PDFs. Then L2TP over IPsec. Then various vendor-specific nightmares. “Simpler” in this domain meant “fewer features you’ll miss in six months.”

I was wrong. Not partially wrong — wrong about the specific things I thought were problems.

What WireGuard actually is

The kernel module is roughly 4,000 lines of C. Compare this to the OpenVPN codebase, which is a user-space daemon with a dependency tree and roughly fifteen years of accumulated configuration surface. WireGuard is a single kernel interface that looks like a network interface, acts like a network interface, and can be configured with ip(8) and a handful of wg(8) commands. You give it a private key, add peers with their public keys and allowed IPs, and it works.

The cryptography is fixed. That’s the thing I initially read as a limitation. There is no cipher negotiation, no TLS handshake, no --cipher flag. You get Noise_IKpsk2 for the handshake, ChaCha20-Poly1305 for traffic encryption, Curve25519 for key exchange, BLAKE2s for hashing, and SipHash-2-4 to protect the routing table against DoS. Those choices were made in 2016 and they were the right choices. The formal security proof — Lipp, Blanchet, and Bhargavan, 2019 — covers the Noise handshake and the key derivation and it holds.

Fixed cryptography means no downgrade attacks. It means auditing the implementation is bounded work — there’s one code path, not a combinatorial matrix of cipher/hash/kex combinations that the negotiation logic can traverse. IPsec’s security profile has been undermined more than once by negotiating down to weaker parameters when both peers “supported” them. WireGuard can’t do this. I thought that was inflexibility. It’s correctness by construction.

The key model I thought would fail

WireGuard has no PKI. No CA, no certificate chain, no revocation infrastructure. Each peer is identified by a Curve25519 public key. If you want peer A to talk to peer B, you put A’s public key in B’s config and B’s public key in A’s config. That is the authentication model. Done.

My prediction in 2020 was that this would be operationally painful at scale. Key distribution without a CA means you need some other mechanism to distribute keys and revoke access. I expected this to be a solved-problem-but-not-here situation, where the protocol itself was clean but the operations story fell apart at fifty peers.

What actually happened: people wrote key distribution tooling. Tailscale built a coordination server on top of WireGuard that handles key exchange, NAT traversal, and access control. Headscale replicated the Tailscale coordination server as open-source. Nebula solved a similar problem with a different trust model. The WireGuard protocol turned out to be an excellent primitive precisely because it didn’t bake in the distribution story — you could put whatever key management layer you wanted on top without fighting the protocol.

The static key model also means cryptokey routing works predictably. Traffic arriving at a WireGuard interface with a valid source public key that isn’t in the peer list is dropped at the kernel level, before it touches user space. There’s nothing to exploit via a malformed packet that wouldn’t first require you to already have a valid peer’s private key. The attack surface is the 4,000-line kernel module, not a user-space daemon parsing config files and managing TLS state.

Six years later, where it’s landed

WireGuard is in every major Linux distribution as a standard kernel module. It’s in FreeBSD as of 13.0 — first as a kmod, now building toward integration with the base system networking stack. OpenBSD has its own IKEv2 daemon (iked) and the team has been characteristically cautious about WireGuard, but wg-go runs on it and the port is maintained. Even Windows has a first-party WireGuard client that doesn’t embarrass itself.

Every major cloud provider either runs it natively in their VPN products or has tooling that generates WireGuard configs. DigitalOcean’s private networking documentation has WireGuard examples. Linode/Akamai runs it. AWS uses its own layer, but every “how to connect to your VPC” third-party guide points to WireGuard as the sane option.

Performance held. The kernel-space implementation with the chacha20poly1305 SIMD acceleration paths means you can push multi-gigabit traffic on modern hardware without the CPU overhead that made OpenVPN’s user-space model a bottleneck. The hand-off between kernel WireGuard and the rest of the network stack is clean because it’s a real kernel interface, not a TUN device bouncing packets through user space.

What it doesn’t do

WireGuard is not a replacement for everything. It’s a point-to-point tunnel protocol. It doesn’t do split-DNS in the protocol itself. It doesn’t do certificate-based authentication for enterprise SSO integration. It doesn’t have the management plane that IPsec’s IKEv2 provides for large-scale key rotation.

If you need a VPN that integrates with your corporate LDAP and auto-enrolls devices and handles certificate expiry and sends audit logs to your SIEM, WireGuard is the underlying transport for a product that does those things, not the product itself. Tailscale, NetBird, or your choice of coordination layer goes on top.

What WireGuard is: the correct primitive. A network tunnel implementation that does one thing correctly, is auditable by a person who can read C, and hasn’t shipped a critical CVE in six years of kernel integration. That last point I cannot say about IPsec, OpenVPN, or the various SSL VPN appliances that have generated their own genre of CVE advisories.

I called the fixed-cipher-suite approach opinionated in 2020 and meant it as a criticism. I was wrong. Opinionated in the right direction is just correct.

See also: network namespaces with ip netns for running WireGuard interfaces in isolated namespaces, and policy routing with ip rule for the routing rules you’ll need if you’re selectively tunneling traffic rather than routing everything through the peer.

Sources

  1. WireGuard — Fast, Modern, Secure VPN Tunnel — Jason A. Donenfeld / WireGuard Project
  2. WireGuard — Next Generation Kernel Network Tunnel (academic paper) — NDSS Symposium 2017