Keys and peers
WireGuard runs on your laptop and on your home server. Each makes a key pair: a private key that never leaves the device and a public key it can share. Both are 32-byte Curve25519 keys.
You copy each public key to the other side once, like swapping phone numbers. Each side lists the other as a peer: its public key plus the tunnel addresses it may use, called allowed IPs.
The attack fails
An attacker sends a made-up handshake to UDP port 51820. Its mac1 check field needs the server's public key, which the attacker lacks, so the server drops it without a reply. A scanner cannot tell anything is listening.
1-RTT handshake
The laptop sends one 148-byte message: a fresh one-time public key, its own public key encrypted, an encrypted timestamp, and mac1. Only the real server can open the encrypted parts.
The server checks mac1, decrypts the laptop's public key and finds it in its peer list. The timestamp must be newer than the last one it saw, so a recorded old handshake is refused.
The server answers with 92 bytes and its own one-time key. Both sides mix four key exchanges into the same pair of session keys, one for each direction. One round trip, done.
Inside the tunnel
The laptop pings 10.8.0.1. The ping is encrypted with ChaCha20-Poly1305, numbered with a counter and put inside an ordinary UDP packet. This first packet also proves to the server that the new keys work.
Only the laptop's session key opens this packet, so the server knows which peer sent it. The inside source, 10.8.0.2, must be in that peer's allowed IPs; any other source is dropped.
To answer 10.8.0.2, the server looks up which peer owns that address, encrypts with that peer's key and sends it to wherever the laptop last spoke from. The laptop can change networks freely.
The attacker captured a tunnel packet and sends it again. Its counter was already used, so it is dropped. Changing even one byte breaks the 16-byte Poly1305 tag, so an edited copy is dropped too.
WireGuard and IPsec
IPsec is an older family of standards that negotiates its algorithms with IKEv2 and runs on most routers. WireGuard has no negotiation: one fixed modern set, under 4,000 lines of code, and fresh session keys every two minutes.
The message, field by field
;; step 1/11 · keys · setup ;; at the laptop + home server on each device, once: private key 32 random bytes (Curve25519), kept on the device public key 32 bytes, computed from the private key config files show them as 44 characters of base64 fixed crypto, no choices to make: Curve25519 · ChaCha20-Poly1305 · BLAKE2s
Sizes are from the WireGuard whitepaper: initiation 148 bytes, response 92 bytes, data = 16-byte header + padded packet + 16-byte tag. Sessions are re-keyed after 120 seconds of use, and keys older than 180 seconds are refused.