AllowedIPs: cryptokey routing
AllowedIPs is the heart of WireGuard, and it does two jobs at once. WireGuard calls the combination cryptokey routing: every address belongs to exactly one public key.
- Outbound, it's a routing table. When the server sends a packet into
wg0, WireGuard looks up the destination in the peers'AllowedIPsto choose which peer, and therefore which key, encrypts it. A packet for 10.20.0.10 goes to the branch router, because only the branch peer lists 10.20.0.0/24. - Inbound, it's an access list. When a packet arrives from a peer and is decrypted, its source address must be in that peer's
AllowedIPs, or WireGuard drops it.
The lab tests the second job directly. bob adds a second address to his tunnel and pings from it. The server receives the encrypted packet, decrypts it, sees the source 10.9.0.99, which isn't bob's, and drops it, before it ever appears on wg0. Pinging from his real address, 10.9.0.11, works. A user can't pretend to be another user, and the server's firewall rules can trust the source address of anything arriving on wg0.
A network behind a peer
The branch router is a peer like any other, but its AllowedIPs on the server also includes the branch LAN, 10.20.0.0/24. That one line routes the branch LAN to it, and allows packets from the branch PCs to come out of its tunnel. OpenVPN needed two settings for this (route and iroute); WireGuard needs one. The branch router itself forwards between its tunnel and its LAN.
wg show on the server now lists every peer: each user's endpoint (the address they're connecting from), their allowed IPs, the latest handshake and their traffic.
root@bob:~# ip addr add 10.9.0.99/24 dev wg0 && ping -c 2 -W 1 -I 10.9.0.99 10.9.0.1; ping -c 2 -W 1 -I 10.9.0.11 10.9.0.1
PING 10.9.0.1 (10.9.0.1) from 10.9.0.99 : 56(84) bytes of data.
--- 10.9.0.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1036ms
PING 10.9.0.1 (10.9.0.1) from 10.9.0.11 : 56(84) bytes of data.
64 bytes from 10.9.0.1: icmp_seq=1 ttl=64 time=0.460 ms
64 bytes from 10.9.0.1: icmp_seq=2 ttl=64 time=0.473 ms
--- 10.9.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1046ms
rtt min/avg/max/mdev = 0.460/0.466/0.473/0.006 ms- Lines 1–5: From 10.9.0.99: the server decrypts the packet, finds a source that isn't in bob's
AllowedIPs, and drops it. - Lines 7–13: From his own address, 10.9.0.11: fine.
root@vpn:~# timeout 6 tcpdump -lnni wg0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
06:47:23.701837 IP 10.9.0.11 > 10.9.0.1: ICMP echo request, id 4725, seq 1, length 64
06:47:23.701959 IP 10.9.0.1 > 10.9.0.11: ICMP echo reply, id 4725, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel- Lines 4–5: Only the 10.9.0.11 ping. The 10.9.0.99 packets never reached
wg0, let alone the firewall.
# /etc/wireguard/wg0.conf on the branch router (wg-quick up wg0)
[Interface]
Address = 10.9.0.20/24
PostUp = wg set %i private-key /etc/wireguard/branch.key
[Peer]
# The VPN server: reach the VPN and the office LAN through it.
PublicKey = /S03YCIRbPGjlhE53GYhxFEh8LVo/Joel3BkEgWeeXk=
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.9.0.0/24, 10.10.0.0/24
PersistentKeepalive = 25- Line 10: The branch only needs the VPN and the office LAN through the tunnel; its internet traffic goes direct.
root@vpn:~# wg show
interface: wg0
public key: /S03YCIRbPGjlhE53GYhxFEh8LVo/Joel3BkEgWeeXk=
private key: (hidden)
listening port: 51820
peer: sh5Ul4rjT56yt7ZYYVSrpJvxEIqKFx/HxkeICJIgGws=
endpoint: 198.51.100.23:35959
allowed ips: 10.9.0.20/32, 10.20.0.0/24
latest handshake: Now
transfer: 308 B received, 220 B sent
peer: 8BpkL72eT8cHe8HTgKE8yWD464E0FVbQGlQ1FPi0tnc=
endpoint: 198.51.100.22:34037
allowed ips: 10.9.0.11/32
latest handshake: Now
transfer: 308 B received, 220 B sent
peer: hwCdM7ImFlIKfF0sQHngu9THMAenVRLSD1JYIrqR2Qw=
endpoint: 198.51.100.21:44820
allowed ips: 10.9.0.10/32
latest handshake: 17 seconds ago
transfer: 980 B received, 604 B sent- Lines 7–11: The branch router, connecting from 198.51.100.23.
- Lines 13–23: bob and alice: each with an endpoint, a handshake and a byte count. This is your list of who's connected.
Check your understanding
On the server, bob's peer has AllowedIPs = 10.9.0.11/32. What happens to a packet the server routes to 10.9.0.11, and to a packet arriving from bob with source 10.9.0.12?
- The first is encrypted to bob's key; the second is dropped.
- Both are dropped until the firewall allows them.
- The first goes to whichever peer answers first; the second is accepted because it's in 10.9.0.0/24.
- Both are accepted, because bob has a valid handshake.
Check your understanding
The branch router's LAN is 10.20.0.0/24. Which server-side setting makes the server send traffic for it to the branch, and accept traffic from it?
- Adding 10.20.0.0/24 to the branch peer's AllowedIPs.
- An
irouteon the server. - A static route only.
- Nothing: the branch announces it in the handshake.