AllowedIPs trips up almost everyone because it does two jobs at once:
- Routing (outbound): which destination IPs get sent into the tunnel to this peer.
- Filtering (inbound): which source IPs WireGuard will accept from this peer (cryptokey routing). Anything else from that peer is dropped.
On the SERVER: one /32 per client
Each client’s [Peer] lists just that client’s VPN IP, so the server knows which peer owns which
address:
[Peer] # laptop
PublicKey = LAPTOP_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
[Peer] # phone
PublicKey = PHONE_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32
If you put 10.0.0.0/24 on two peers, the server can’t tell them apart — use unique /32s.
On the CLIENT: what you want to reach
The client’s [Peer] (the server) lists the destinations to route through the tunnel:
# Just talk to the server's VPN IP:
AllowedIPs = 10.0.0.1/32
# Reach the whole VPN subnet:
AllowedIPs = 10.0.0.0/24
# Reach the VPN + a LAN behind the server:
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
# Full tunnel — send EVERYTHING through the server:
AllowedIPs = 0.0.0.0/0, ::/0
Mental model
- Server side = “this address belongs to this peer” (identity /
/32s). - Client side = “route these destinations to the server” (your VPN scope).
0.0.0.0/0on a client = full tunnel; a subnet list = split tunnel.
Change it live (no reconnect)
sudo wg set wg0 peer PEER_PUBLIC_KEY allowed-ips 10.0.0.0/24,192.168.1.0/24
sudo wg-quick save wg0
“Connected but can’t reach X”: X’s subnet probably isn’t in the client’s AllowedIPs (so it’s
not routed), or the server’s peer entry doesn’t include the source you’re coming from (so it’s
dropped). Fix the side that matches the direction of the missing traffic.