Skip to main content
  1. Index/

WireGuard

WireGuard is a VPN protocol and implementation designed by Jason Donenfeld, merged into the Linux kernel in 5.6 (2020) and subsequently ported to Windows, macOS, iOS, Android, and BSD. Its defining characteristic is radical simplicity: the reference Linux kernel implementation is approximately 4,000 lines of code, compared to tens of thousands for IPsec’s XFRM subsystem and hundreds of thousands for OpenVPN. This simplicity is a deliberate security property — a smaller codebase has a smaller attack surface, is easier to audit, and is less likely to contain implementation vulnerabilities. WireGuard achieves this by making every design decision that allows optionality to be eliminated: there is no algorithm negotiation, no handshake negotiation, no cipher suite selection. The cryptographic suite is fixed: X25519 for key exchange, ChaCha20-Poly1305 for authenticated encryption, BLAKE2s for hashing and key derivation (via a custom HKDF-like construction), and Curve25519 for the static key pairs that identify peers. Peers are identified exclusively by their 32-byte Curve25519 public key, making WireGuard a public-key routed VPN: there are no usernames, passwords, certificates, or CAs; access control is entirely a function of which public keys are listed in each peer’s configuration.

The protocol is stateless by design from the perspective of connection tracking. A WireGuard interface has a private key and a list of allowed IPs per peer — the IP ranges that the tunnel will accept from and route toward each peer’s public key. When a packet arrives on the WireGuard UDP port (51820 by default, fully configurable), the interface decrypts it using the session key derived from the initiating handshake and checks whether the decrypted source IP falls within the allowed IPs for the peer that sent it; if not, the packet is dropped. There is no persistent connection state beyond the session keys, which are renegotiated every 3 minutes (or after 180 seconds of inactivity) using a 1-RTT Noise protocol handshake (specifically, the Noise_IKpsk2 pattern from the Noise Protocol Framework). The handshake provides mutual authentication (both peers verify each other’s static public key against their configuration), forward secrecy (ephemeral X25519 key pairs are generated per session and discarded after use), and identity hiding (the initiator’s static public key is encrypted under the responder’s static public key before transmission, so a passive observer cannot determine who is connecting). An optional pre-shared symmetric key (PSK) can be added per peer pair as a post-quantum hedge — XOR’d into the key derivation — providing a symmetric layer of protection against a CRQC breaking the X25519 key exchange, though this is a manual, non-rotating secret rather than a full PQC solution.

WireGuard’s operational model is intentionally infrastructure-agnostic: a WireGuard interface is a standard Linux network interface (ip link add wg0 type wireguard), configurable via wg and wg-quick or directly via the kernel netlink API, and composable with standard Linux networking — nftables and iptables rules, routing tables, network namespaces, and eBPF programs all apply to WireGuard traffic exactly as to any other interface. This composability makes WireGuard the tunnelling layer for several higher-level systems: Tailscale and Headscale use WireGuard as the data plane for a mesh VPN with a control plane that distributes public keys and coordinates NAT traversal via DERP relay servers; Netbird takes a similar approach; Kubernetes CNI plugins including Kilo and Flannel (in WireGuard mode) use it for encrypted pod-to-pod cross-node traffic. The fixed cryptographic suite creates a PQC migration challenge: unlike TLS 1.3 where the key exchange algorithm is negotiable and X25519MLKEM768 can be deployed as a drop-in hybrid, WireGuard’s Noise_IKpsk2 handshake hardcodes X25519 and there is no standardised mechanism for substituting ML-KEM. The PSK option provides a partial mitigation (a pre-shared 256-bit key added to the derivation provides symmetric post-quantum security for the session confidentiality if the PSK itself is securely pre-distributed and rotated), but a full PQC WireGuard would require a protocol revision. The WireGuard project and several research groups are actively exploring Noise_IKpsk2 variants with ML-KEM, but no standardised, widely-deployed solution exists as of 2025.

Related

IPsec (Internet Protocol Security)

IPsec (Internet Protocol Security) is a suite of IETF standards (core specification RFC 4301) that adds cryptographic security to IP packets at the network layer, transparently to applications running above it. Where TLS secures a specific connection between two application endpoints, IPsec secures all IP traffic between two hosts or networks — including traffic from applications that have no TLS support, protocols that predate encryption (routing protocols, SNMP, ICMP), and layer-3 metadata that TLS cannot protect. IPsec provides two protocol headers: AH (Authentication Header, IP protocol 51) signs the IP packet including immutable header fields, providing integrity and source authentication without confidentiality — rarely used in modern deployments because NAT rewrites fields that AH covers. ESP (Encapsulating Security Payload, IP protocol 50) encrypts the payload and provides authenticated encryption with AES-GCM or ChaCha20-Poly1305, optionally protecting the inner IP header as well; ESP is the universally deployed choice. Both operate in two modes: transport mode protects only the payload of an existing IP packet (used for host-to-host encryption between endpoints that share routing), and tunnel mode encapsulates the entire original IP packet inside a new one with new source and destination addresses — the basis of VPN gateways where traffic from one network is tunnelled to another through the public internet.

SSH (Secure Shell)

SSH (Secure Shell) is a cryptographic protocol, standardised in RFC 4251–4254, that provides a secure channel over an unsecured network for remote login, remote command execution, file transfer (via SFTP and SCP), and general TCP port forwarding. It replaced the plaintext protocols it was designed to obsolete — Telnet, rlogin, rsh, rcp — by providing mutual authentication and full session encryption. SSH is the universal administrative access mechanism for Linux servers, network devices, and embedded systems, and the transport layer for Git over SSH, Ansible, Fabric, and most configuration management tooling. The protocol stack has three layers: SSH-TRANS (the transport layer — handles the initial key exchange, server authentication, and establishes the encrypted channel), SSH-AUTH (the authentication protocol — authenticates the client to the server using one of several methods), and SSH-CONN (the connection protocol — multiplexes the encrypted channel into multiple logical channels for sessions, port forwards, and X11 forwarding).

eBPF (Extended Berkeley Packet Filter)

eBPF (Extended Berkeley Packet Filter) is a Linux kernel subsystem, its modern form dating to kernel 3.18 (2014), that allows user-authored programs to run inside the kernel with near-native performance, subject to safety guarantees enforced at load time by a verifier. The name is historical: the original BPF (Berkeley Packet Filter, 1992) was a narrow packet filtering mechanism for tools like tcpdump. eBPF extended the instruction set, registers, and capabilities far beyond packet filtering into a general-purpose in-kernel programmability platform. The central design constraint is that eBPF programs must be provably safe: they cannot crash the kernel, loop infinitely, or access memory out of bounds. The verifier statically analyses every program at load time, checking that all memory accesses are bounds-checked, all loops are bounded or unrolled, and all pointer dereferences are preceded by null checks. Only programs that pass verification are accepted; once accepted, the kernel JIT-compiles the eBPF bytecode to native machine code for the host architecture — x86-64, ARM64, RISC-V — so eBPF programs run at the same speed as compiled kernel code, not as an interpreter.