WireGuard: A Comprehensive Overview¶
1. What WireGuard Is¶
WireGuard is a modern VPN protocol and implementation designed to be simple, fast, and cryptographically sound. It was created by Jason Donenfeld and merged into the mainline Linux kernel (5.6+) in 2020. Compared to IPsec and OpenVPN, its entire codebase is small — roughly 4,000 lines vs. tens/hundreds of thousands for the alternatives — which makes it dramatically easier to audit and reason about.
Core design goals:
- Minimal attack surface — small, auditable codebase.
- High performance — kernel-space implementation (on Linux), tight crypto primitives, no negotiation overhead per-packet.
- Simplicity — no cipher negotiation, no complex state machine. One cryptographic suite, versioned as a whole; if it's ever broken, you upgrade the whole protocol rather than patch individual algorithm choices.
- UDP-based, connectionless — behaves like a stateless tunnel that "just works" across NAT and roaming networks (mobile device switching from WiFi to LTE keeps the tunnel alive).
2. Cryptographic Foundations¶
WireGuard uses a fixed, opinionated set of modern primitives (Noise Protocol Framework):
| Purpose | Algorithm |
|---|---|
| Key exchange | Curve25519 (ECDH) |
| Symmetric encryption | ChaCha20 |
| Authentication (AEAD) | Poly1305 |
| Hashing | BLAKE2s |
| Handshake | Noise_IK (Noise Protocol Framework) |
| Key derivation | HKDF |
There's no algorithm agility — you don't choose ciphers like in OpenVPN/IPsec. This eliminates an entire class of misconfiguration and downgrade-attack risk.
Handshake (Noise_IK):
1. Each peer has a static Curve25519 keypair (private/public).
2. On first packet, an ephemeral key exchange occurs, authenticated by the peers' known static public keys.
3. Produces a new symmetric session key roughly every 2 minutes (or after ~2^60 messages), giving forward secrecy — a compromised key doesn't retroactively expose old traffic.
4. Includes a "silent" mode: WireGuard doesn't respond to unauthenticated packets at all, so a port scanner sees nothing (no port appears "open" without the right key) — this is the same property that makes it resistant to certain DoS and fingerprinting attacks.
3. Identity Model: Keys Instead of Certificates¶
This is the biggest conceptual shift from OpenVPN/IPsec:
- No PKI, no certificate authority, no revocation lists.
- Each peer (client or server) has a Curve25519 private key (keep secret) and derived public key (share it).
- A peer's "identity" on the network is its public key.
- The interface config lists the peers it trusts by public key, plus which IP ranges each peer is allowed to send/receive traffic for (
AllowedIPs).
This means adding a device = generating a keypair and exchanging public keys — not issuing/signing/distributing certs. It also means revocation is manual: to remove a peer, you delete its entry from the config on the other side. There is no CRL/OCSP mechanism.
4. Core Concepts and Terminology¶
- Interface: a virtual network device (e.g.,
wg0) that WireGuard creates. It has its own private key and an IP address in the tunnel's private subnet. - Peer: a remote endpoint you communicate with. Each peer entry has:
PublicKey— identifies the peer.AllowedIPs— a whitelist of source/destination CIDR ranges for that peer. This does double duty as both a routing table and a cryptographic ACL — packets from a peer are only accepted if their source IP falls within that peer'sAllowedIPs.Endpoint(optional) — the peer's real IP:port, if it has one (not needed for peers behind NAT that only initiate).PersistentKeepalive(optional) — sends a keepalive packet every N seconds to hold NAT mappings open (important for peers behind NAT/firewalls, e.g. road-warrior clients or IoT/homelab boxes).- Endpoint: the actual UDP IP:port a peer is reachable at.
- ListenPort: UDP port the local interface listens on (default convention: 51820, but arbitrary).
- Handshake: the key-exchange event; happens roughly every 2 minutes to rotate session keys.
5. AllowedIPs — the Part Everyone Gets Wrong¶
AllowedIPs is used differently depending on which side of the config you're looking at, and this trips up almost everyone the first time:
- On the receiving side, it's a packet filter: only accept a packet from this peer if its source IP is in this range.
- When building the routing table, it's used to decide which peer a destination IP should be routed through.
Examples:
- A client connecting to a single-server VPN with a full tunnel (route everything through the VPN) sets AllowedIPs = 0.0.0.0/0, ::/0 for the server peer.
- A client that only wants to reach the VPN server's LAN (split tunnel) sets AllowedIPs = 10.10.0.0/24 (the LAN CIDR) instead.
- On the server, each client peer typically gets AllowedIPs = <client's tunnel IP>/32 — i.e., "only this exact tunnel address may claim to be this peer."
Overlapping AllowedIPs across peers is not allowed on the same interface — WireGuard needs an unambiguous way to route/authenticate each packet.
6. Network Topologies¶
WireGuard doesn't inherently have a "client/server" model — every peer is symmetric. Common topologies:
- Road warrior (remote access): One "hub" (e.g., your home router) with a public endpoint; multiple client peers roam and connect in. Hub has each client's
/32inAllowedIPs; clients have the hub's LAN CIDR (or0.0.0.0/0) in theirs. - Site-to-site: Two networks (e.g., two homes, or home + cloud VPS) each have a gateway peer. Each side's
AllowedIPsfor the other lists the remote LAN CIDR, enabling routing between full subnets. - Mesh: Every peer has a direct peer entry for every other peer. No central hub, but N peers requires managing N(N-1)/2 relationships — usually orchestrated by a tool (e.g., Tailscale, Netmaker,
innernet) rather than by hand. - Hub-and-spoke with LAN routing: A hub relays not just to itself but forwards to its whole LAN and possibly between spokes (requires explicit IP forwarding + firewall rules on the hub — this is the "route the whole network through WireGuard" pattern, covered in the companion OPNsense doc).
7. Performance Characteristics¶
- Linux kernel module implementation avoids userspace/kernel context-switch overhead that plagues OpenVPN (which runs in userspace via TUN).
- ChaCha20 is fast even without AES-NI hardware acceleration (relevant on ARM devices, low-power routers, phones), whereas AES-based ciphers benefit heavily from hardware acceleration and can lag on hardware without it.
- Typically achieves throughput close to line-rate on modern hardware, and consistently outperforms OpenVPN and often IPsec in real-world benchmarks, especially on constrained CPUs (e.g., consumer router SoCs, small VPS instances, ARM SBCs).
- Lower per-packet overhead (fixed 60-byte header vs. OpenVPN's larger, variable overhead) — better MTU efficiency.
8. Comparison to Other VPN Technologies¶
| WireGuard | OpenVPN | IPsec/IKEv2 | |
|---|---|---|---|
| Codebase size | ~4K LOC | ~100K+ LOC | Very large (multiple RFCs, vendor stacks) |
| Transport | UDP only | UDP or TCP | UDP (ESP/IKE), sometimes TCP encapsulated |
| Identity | Static keypairs | X.509 certificates (typically) | Certificates or PSK |
| Cipher agility | None (fixed suite) | Configurable | Configurable |
| Kernel support | Mainline Linux since 5.6 | Userspace (TUN/TAP) | Kernel (XFRM) on Linux, native on most OSes |
| Roaming / mobile friendliness | Excellent (no renegotiation needed on IP change) | Poor to moderate | Moderate (IKEv2 MOBIKE helps) |
| Config complexity | Low | Moderate–high | High |
| NAT traversal | Simple (UDP + keepalive) | Simple | Can be finicky (NAT-T) |
| Built-in dead-peer detection | No (relies on handshake timers/keepalive) | Yes | Yes |
| DPI resistance | Fair, no ability to disguise as e.g. TLS/443 | Good (can run over TCP/443) | Fair |
Practical takeaway: WireGuard is generally the better choice for point-to-point tunnels, road-warrior remote access, and site-to-site links where you control both ends. OpenVPN-over-TCP-443 is still relevant when you need to blend in with HTTPS traffic to get through restrictive firewalls/DPI. IPsec/IKEv2 remains common in enterprise/vendor-interop scenarios (native OS clients, older network gear) and where you don't control both ends.
9. Security Considerations and Caveats¶
- No built-in user authentication layer. WireGuard authenticates devices (keys), not users. If you need per-user auth (e.g., 2FA, SSO), you build that on top (e.g., a portal that provisions keys, or pairing with something like a RADIUS-gated admin process) — WireGuard itself doesn't do it.
- No revocation infrastructure. Losing a device means you must manually remove its peer entry everywhere it was trusted. Rotate keys and treat leaked private keys as you would a leaked SSH key.
- Private key storage matters. Anyone with a peer's private key can impersonate it. On OPNsense/Linux, key files should have restrictive permissions; avoid pasting private keys into shared configs/tickets/chat (a good
pass-style habit here). - Metadata isn't hidden. WireGuard doesn't provide traffic obfuscation — a firewall doing deep packet inspection can identify WireGuard traffic by its handshake pattern, even without decrypting it. If protocol obfuscation is a requirement, this isn't the tool (consider
udp2raw,obfs4, or shadowsocks wrapping if that's genuinely needed). - DoS resistance is decent but not magic. The protocol's silent-drop behavior helps, but a flood of well-formed handshake-initiation packets can still cost CPU; WireGuard includes a cookie mechanism to mitigate this under load.
- PresharedKey (PSK) option. In addition to the asymmetric handshake, WireGuard supports an optional per-peer symmetric preshared key for post-quantum defense-in-depth — it doesn't replace Curve25519, but layers a symmetric secret onto the handshake so that a future break of Curve25519 alone wouldn't be sufficient to decrypt captured traffic. Worth enabling for anything you consider higher-value.
10. Key Management Best Practices¶
- Generate keys with
wg genkey/wg pubkey(or your platform's equivalent UI, which usually wraps the same call). - Never reuse a keypair across multiple peers/devices.
- Store private keys with
0600permissions, owned by the service user. - Prefer a config-management or secrets tool (you already use
pass— treating each peer's private key as apassentry works well) over ad-hoc plaintext files scattered across hosts. - Rotate keys periodically for anything long-lived and high-trust (e.g., site-to-site links), and immediately on suspected compromise or device loss.
- Use PresharedKeys for peers you consider high-value.
11. Operational Notes¶
- MTU: Default WireGuard overhead is 60 bytes (IPv4) — a common baseline is setting the tunnel MTU to 1420 (from a standard 1500 underlying MTU) to avoid fragmentation; tune down further if the underlying path has its own overhead (e.g., PPPoE, double NAT, another tunnel).
- Keepalives: Needed on any peer that sits behind NAT and doesn't itself receive unsolicited inbound handshakes (e.g., a phone, or a home box behind CGNAT) — typically
PersistentKeepalive = 25seconds. - DNS: WireGuard has no opinion on DNS. Full-tunnel clients (
AllowedIPs = 0.0.0.0/0) usually also want aDNS =line pointing at an internal resolver, or their normal DNS resolution will still work but potentially leak query metadata to whatever resolver they're using, and access to internal-only DNS names (e.g., your homelab domain) will fail — the client's OS/wg-quick script needs to explicitly override resolv.conf during the tunnel session. - Logging/observability:
wg showgives live peer state (last handshake, transfer stats). There's no built-in long-term logging — pair with your existing ELK/Prometheus stack if you want handshake/traffic history (e.g., scrapewg showoutput or firewall interface counters).
12. Where to Go Next¶
This document covers the protocol and concepts generally, independent of any specific platform. For a concrete, step-by-step implementation that routes an entire home/office network through WireGuard using OPNsense as the gateway — including firewall rules, NAT considerations, and both road-warrior and site-to-site patterns — see the companion document: wireguard-opnsense-whole-network-guide.md.