Cryptokey routing, the wg0 network interface, roaming between addresses, and living inside containers.
WireGuard wraps IP packets inside UDP and sends them to a peer. That sentence is almost the whole design. What makes it interesting is what it refuses to do: there is no key distribution mechanism, no configuration push, no negotiation about which cryptography to use. Those problems are real, but WireGuard treats them as somebody else’s layer, which is why it stays small.
The model to hold in your head is SSH. Two machines already know each other’s public keys. Nothing else needs arranging before traffic flows.
It is just a network interface
Section titled “It is just a network interface”WireGuard appears as an ordinary network interface — wg0, wg1, and so on,
sitting alongside eth0 and wlan0 in every tool you already use. Addresses go
on it with ip address, routes go through it with ip route, and your firewall
sees it the way it sees anything else. Only the WireGuard-specific parts — keys,
peers, endpoints — need the wg tool.
This is a bigger deal than it sounds. It means WireGuard inherits your operating system’s networking stack instead of reimplementing one, and it means your existing monitoring, routing and firewalling knowledge transfers unchanged.
Cryptokey routing
Section titled “Cryptokey routing”Every interface holds one private key and a list of peers. Every peer has a public key and a list of tunnel addresses that key is allowed to use.
That list does double duty, and understanding which job it is doing in which direction is the thing worth learning.
Sending. The interface is handed a packet and looks at its destination address. It searches the peers’ allowed-address lists for the one that covers that destination, encrypts the packet to that peer’s public key, and sends it to the last endpoint that peer was seen at. No match means the packet is dropped — there is no default route through a tunnel that isn’t configured for it.
Receiving. A UDP packet arrives. If it decrypts and authenticates, WireGuard now knows which peer’s key produced it. It then reads the source address of the plaintext packet inside and asks whether that key is permitted to claim that address. If yes, the packet goes up the stack. If not, it is dropped.
So the same list behaves as a routing table on the way out and an access control list on the way in. A peer cannot spoof another peer’s address, because the address is checked against the key that actually did the cryptography.
What that looks like configured
Section titled “What that looks like configured”A machine acting as a hub, with two peers:
[Interface]PrivateKey = <hub private key>ListenPort = 51820
[Peer]# laptop — one address, and only that addressPublicKey = <laptop public key>AllowedIPs = 10.7.0.2/32
[Peer]# a branch office router, which fronts a whole subnetPublicKey = <branch public key>AllowedIPs = 10.7.0.3/32, 172.20.8.0/24The laptop’s own configuration is shorter, because it has exactly one peer:
[Interface]PrivateKey = <laptop private key>
[Peer]PublicKey = <hub public key>Endpoint = hub.example.org:51820AllowedIPs = 0.0.0.0/0AllowedIPs = 0.0.0.0/0 on the laptop means two things at once, both following
from the rules above: send everything through this peer, and accept packets from
it regardless of what source address they carry. That is how you route all your
traffic over the tunnel — not a special mode, just the wildcard case of the same
table.
The branch entry shows why the list is a list. That peer may speak for itself at
10.7.0.3 and for everything behind it in 172.20.8.0/24, and the hub will
accept both from that key and nothing else.
Roaming is the default
Section titled “Roaming is the default”Notice that the laptop’s configuration names an endpoint for the hub, but the hub’s configuration names no endpoint for the laptop. It doesn’t need one.
When a packet authenticates, WireGuard records where it came from and uses that address for replies. So a peer that moves — wifi to mobile data, one café to the next, a new address from DHCP — simply keeps working. The next authenticated packet from the new address updates the record. There is no reconnect, no session to re-establish, and nothing for you to configure.
This is also why WireGuard doesn’t need to distinguish clients from servers. The asymmetry in the example above is only that one side knows where to find the other first.
Silence, and what it costs
Section titled “Silence, and what it costs”When neither side has traffic to send, WireGuard sends nothing at all. No keepalives, no heartbeat. That is excellent for a phone’s battery and awkward for NAT, because a stateful firewall that stops seeing packets eventually drops the mapping — and then nothing can reach you until you speak first.
Where that matters, a persistent keepalive fixes it, at the cost of the silence. See Install for the setting and the interval the project recommends.
Containers and namespaces
Section titled “Containers and namespaces”The interface and the encrypted socket do not have to live in the same place. You can create a WireGuard interface inside a network namespace while the UDP socket that carries its traffic stays outside, in a different namespace.
That inversion is genuinely useful. A container can be given a network interface whose only route to the outside world is the tunnel, while the host retains the actual internet connection. The process inside cannot reach the network except through WireGuard, and it cannot turn that off, because the socket isn’t in its namespace to interfere with.
Where to go deeper
Section titled “Where to go deeper”The protocol summary and the technical whitepaper on the official site are the authoritative descriptions, and the whitepaper is a genuine academic paper rather than marketing — see Cryptography and security for what it covers and where to find it.