L3 · security · reviewed
WireGuard
WireGuard
A small cryptographic VPN with static public keys, cryptokey routing, and one UDP-carried tunnel interface per peer list.
Why it exists
IPsec’s SAD/SPD and IKEv2 are a lot of moving parts for a host tunnel. WireGuard aims for a small, auditable kernel interface: one private key, a UDP port, and a list of peers. WireGuard Protocol §1 Introduction & Motivation
WireGuard is a protocol and an interface, not a managed VPN service. Key distribution, addressing, and policy remain the operator’s problem. WireGuard Protocol §1 Introduction & Motivation
One interface, one peer, one handshake
A wg0 interface holds a private key and a UDP listen port. A peer is a public key, an endpoint, and allowed IPs. The handshake is one round trip over UDP; unauthenticated packets get silence.
Each side brings up a WireGuard interface with its own private key and a UDP listen port. Peers are identified by static Curve25519 public keys — not by certificates or an IKE identity store. Host A · wg0: Listen UDP :51820. UDP underlay. Host B · wg0: Listen UDP :51820.
- Link
- Blocking
- Packet in flight
- Discarded
- Emphasis
Text equivalent of this diagram
| Element | Kind | State |
|---|---|---|
| Host A · wg0 | host | Listen: UDP :51820 |
| UDP underlay | cloud | — |
| Host B · wg0 | host | Listen: UDP :51820 |
| Host A · wg0 — UDP underlay | link | up |
| UDP underlay — Host B · wg0 | link | up |
Each side brings up a WireGuard interface with its own private key and a UDP listen port. Peers are identified by static Curve25519 public keys — not by certificates or an IKE identity store.
What changed
- Host A · wg0: Listen → UDP :51820
- Host B · wg0: Listen → UDP :51820
- Emphasis on Host A · wg0
How it works
Cryptokey routing associates each peer’s public key with the tunnel IP prefixes that peer may source and that should be routed toward it. WireGuard Protocol §2 Cryptokey Routing
Session keys come from a one-round-trip Noise_IK handshake using Curve25519. Transport packets use ChaCha20-Poly1305 over UDP. WireGuard Protocol §Key Exchange and Data Packets
There is no cipher negotiation. One set of primitives is built in; changing them means a new protocol version — removing a large class of downgrade attacks. WireGuard Protocol §Primitives
Authenticated packets from a new source address update the peer’s endpoint (roaming). Unauthenticated packets allocate no state and receive no reply. WireGuard Protocol §DoS Mitigation
On the wire
Constructed examples, encoded from the field table below them — not captured traffic.
- IPv4 or IPv6
- Protocol number 17. The addresses are borrowed back for the checksum pseudo-header. RFC 768
- UDP header
- Source port, destination port, length, checksum. RFC 768
- Payload
- DNS, DHCP, a VXLAN-encapsulated frame, a QUIC packet — whatever the destination port implies. RFC 768
Configure it
[Interface] PrivateKey = <host-a-private> Address = 10.0.0.1/32 ListenPort = 51820The interface owns a static private key and a UDP listen port. Address is the tunnel IP this host sources.
WireGuard Protocol §Command-line Interface
[Peer] PublicKey = <host-b-public> Endpoint = 203.0.113.2:51820 AllowedIPs = 10.0.0.2/32 PersistentKeepalive = 25AllowedIPs is cryptokey routing: outbound path and inbound source filter. Keepalive refreshes NAT mappings when this side is behind NAT.
Common mistake: Omitting PersistentKeepalive on the NAT side and blaming cryptography when the mapping expires.
WireGuard Protocol §2 Cryptokey Routing
Verify
wg show- Peer public key, endpoint, and latest handshake.
ip route show- Routes installed from AllowedIPs.
Caveats
- Keys are secrets — this corpus never stores real key material.
- Overlapping AllowedIPs across peers makes outbound routing nondeterministic.
When it breaks
Symptom first, because that is what you have when it happens.
A peer will not connect and there is nothing in the log to explain it.
Narrow it down
- Check whether each side has the other’s public key exactly.
- Confirm the endpoint address and port on the initiating side.
- Check the allowed IPs on both, which is where most misconfiguration lives.
Cause
WireGuard does not respond to a packet it cannot authenticate. An unknown key produces silence rather than an error, which is deliberate — the interface is unresponsive to anything that cannot prove it belongs.
Fix
Verify the keys and the allowed IPs. The silence is the design; expecting a rejection message wastes the first hour.
WireGuard Protocol §DoS MitigationTraffic to some destinations goes through the tunnel and others do not, with no routing configured to that effect.
Narrow it down
- Read the allowed IPs for each peer.
- Check the routing table entries WireGuard installed from them.
- Look for two peers with overlapping allowed IPs.
Cause
Allowed IPs is two things at once: a routing table for outbound traffic and an access filter for inbound. A prefix listed against a peer routes there, and a packet arriving from that peer with a source outside the list is dropped.
Fix
Treat it as both. Overlapping ranges across peers make the last one configured win for routing, which is rarely what was intended.
WireGuard Protocol §2 Cryptokey RoutingThe tunnel works and then goes quiet after a few minutes of idleness, until traffic is sent from one particular side.
Narrow it down
- Check which side is behind NAT.
- Look at whether persistent keepalive is configured on that side.
- Compare the NAT mapping timeout against the idle period.
Cause
WireGuard sends nothing when there is no traffic, so a NAT mapping expires and the peer behind it becomes unreachable from outside until it sends again.
Fix
Set persistent keepalive on the side behind NAT — twenty-five seconds is the usual value. The peer with a public address does not need it.
WireGuard Protocol §NAT and Firewall Traversal PersistenceHandshake never completes through a middlebox that allows TCP VPN traffic.
Narrow it down
- Confirm the UDP destination port is permitted both ways.
- Check whether the initiator’s source port is being rewritten unexpectedly.
- Capture on the responder to see whether handshake datagrams arrive at all.
Cause
WireGuard is UDP-only. Filters that allow TCP 443 or ESP but drop arbitrary UDP block the handshake before cryptography matters.
Fix
Permit the configured UDP port end to end, or move the listen port to one the path already allows — without inventing a TCP mode that does not exist.
WireGuard Protocol §Key Exchange and Data PacketsA peer moved networks and never reconnects until the other side restarts.
Narrow it down
- Check which side still has the old endpoint cached.
- Confirm whether the moved peer can initiate (it must send an authenticatable packet).
- Look for a sticky NAT or firewall session to the old address.
Cause
Endpoints update from authenticated packets. If the peer that moved cannot initiate — for example it is behind NAT without keepalive and the other side still targets the old mapping — the session stays stuck.
Fix
Ensure the roaming peer can initiate (keepalive if behind NAT) so the new source address is learned from authenticated traffic.
WireGuard Protocol §2.1 Endpoints & Roaming
Design notes
Allowed IPs is both routing and inbound filtering. Overlaps across peers are configuration bugs, not load-balancing.
Silence on a wrong key is deliberate. Expecting an authentication-failure log wastes the first hour of troubleshooting.
Contrast with IPsec: no SPD in the IKE sense, no IKEv2 identities, static keys like OpenSSH authorized_keys. Mixing vocabularies is how configs get copied wrong. Security AssociationsRFC 4301 · PROPOSED STANDARD · December 2005
Misconceptions
- “WireGuard is a VPN service.”
- It is a protocol and a kernel interface. Everything else — user management, address assignment, key distribution, routing policy — is the operator’s problem or a separate product’s. That minimalism is why it is small enough to audit.
- “Allowed IPs is a firewall rule.”
- It is a routing table and an inbound filter simultaneously. Adding a prefix to route traffic to a peer also permits that peer to source traffic from it, and the two cannot be separated. WireGuard Protocol §2 Cryptokey Routing
- “WireGuard negotiates ciphers.”
- It does not. One set of primitives is built in, and changing them means a new version of the protocol. Removing negotiation removes downgrade attacks and a large share of the complexity that TLS and IKE carry. WireGuard Protocol §Primitives
More walkthroughs
Allowed IPs is routing and filterdesign-choice
Allowed IPs installs routes toward a peer and filters inbound sources from that peer. One setting, two jobs — overlapping ranges across peers make the last configured peer win for outbound routing.
The client lists 10.1.0.0/16 under Peer A and 10.2.0.0/16 under Peer B. Outbound packets to those prefixes route to the matching peer; inbound packets from a peer must source from its list or they are dropped. Client · wg0. Peer A · 10.1.0.0/16: Allowed 10.1.0.0/16. Peer B · 10.2.0.0/16: Allowed 10.2.0.0/16. Overlap trap · 10.0.0.0/8.
- Link
- Blocking
- Packet in flight
- Discarded
- Emphasis
Text equivalent of this diagram
| Element | Kind | State |
|---|---|---|
| Client · wg0 | host | — |
| Peer A · 10.1.0.0/16 | router | Allowed: 10.1.0.0/16 |
| Peer B · 10.2.0.0/16 | router | Allowed: 10.2.0.0/16 |
| Overlap trap · 10.0.0.0/8 | zone | — |
| Client · wg0 — Peer A · 10.1.0.0/16 | link | up |
| Client · wg0 — Peer B · 10.2.0.0/16 | link | up |
The client lists 10.1.0.0/16 under Peer A and 10.2.0.0/16 under Peer B. Outbound packets to those prefixes route to the matching peer; inbound packets from a peer must source from its list or they are dropped.
What changed
- Peer A · 10.1.0.0/16: Allowed → 10.1.0.0/16
- Peer B · 10.2.0.0/16: Allowed → 10.2.0.0/16
- Emphasis on Client · wg0 ↔ Peer A · 10.1.0.0/16
- Emphasis on Client · wg0 ↔ Peer B · 10.2.0.0/16
Idle tunnel dies behind NATfailure
WireGuard sends nothing when idle. A NAT mapping expires, and the peer behind NAT becomes unreachable from outside until it sends again — persistent keepalive exists for that case.
The laptop initiates and the handshake completes. Traffic flows. The NAT device holds a UDP mapping from the laptop’s ephemeral port to the server. Laptop · behind NAT. NAT · mapping expires: Mapping alive. Server · public.
- Link
- Blocking
- Packet in flight
- Discarded
- Emphasis
Text equivalent of this diagram
| Element | Kind | State |
|---|---|---|
| Laptop · behind NAT | host | — |
| NAT · mapping expires | firewall | Mapping: alive |
| Server · public | host | — |
| Laptop · behind NAT — NAT · mapping expires | link | up |
| NAT · mapping expires — Server · public | link | up |
The laptop initiates and the handshake completes. Traffic flows. The NAT device holds a UDP mapping from the laptop’s ephemeral port to the server.
What changed
- Authenticated UDP: Laptop · behind NAT → Server · public
- NAT · mapping expires: Mapping → alive
Terms
- Allowed IPs
- In WireGuard, the prefixes associated with a peer’s public key. They install outbound routes toward that peer and filter which inner source addresses are accepted from it — one setting, two jobs.
- Cryptokey routing
- WireGuard’s peer table: a public key maps to allowed tunnel IPs and an optional underlay endpoint. There is no separate IPsec-style SPD.