VPNSmith
self-host-vpnINFO

WireGuard AllowedIPs: One Field That Does Two Jobs (and Why Yours Is Wrong)

AllowedIPs is not a route. The wg man page says it decides both which traffic is accepted FROM a peer and which traffic is sent TO it. That double role explains the handshake that works with no traffic, the peers that cannot overlap, and why you cannot simply subtract your LAN.

By Eric Gerard · Founder · VPNSmith - Self-host VPN & GDPR VPS specialist4 min readPhoto via Pexels

Nearly every WireGuard configuration problem that survives a working handshake comes down to one field, and to the fact that almost nobody reads it correctly. AllowedIPs looks like a routing directive. It is that, and it is also something else at the same time.

What the manual actually says

The wg man page defines it in a single sentence worth reading slowly:

a comma-separated list of IP (v4 or v6) addresses with CIDR masks from which incoming traffic for this peer is allowed and to which outgoing traffic for this peer is directed

Two clauses, two different jobs. Outgoing: packets whose destination falls in that list are sent to this peer. That is the routing half, and it is the one everybody knows. Incoming: packets arriving from this peer are accepted only if their source address falls in the same list. That is an access control list, and it is the half that gets ignored.

This is what WireGuard calls cryptokey routing: the association between a public key and a set of addresses is the entire authorisation model. There is no separate firewall rule deciding which peer may claim which address.

The consequence nobody plans for

Put AllowedIPs = 0.0.0.0/0 on a peer and you have not only routed all your traffic through it. You have also declared that this peer may send you a packet claiming any source address on the internet, and your interface will accept it.

On a client whose only peer is your own server, that is exactly what you want and it is the normal full-tunnel configuration. On a server with several peers, or on any machine where a peer is not fully trusted, it is a hole you opened without noticing.

A black and white close-up of numbered metal letterboxes, the numbers 31 to 40 handwritten on small labels. Each box has exactly one number, and no number appears twice: that is the constraint AllowedIPs imposes across peers.
A black and white close-up of numbered metal letterboxes, the numbers 31 to 40 handwritten on small labels. Each box has exactly one number, and no number appears twice: that is the constraint AllowedIPs imposes across peers.

Why two peers can never share a range

Since the list decides which peer a destination is sent to, the same address cannot belong to two peers at once: the mapping has to be unambiguous. In practice this is why, on the server side, each client gets its own /32 (or /128 in IPv6) rather than the whole subnet.

The asymmetry surprises people. On the client, AllowedIPs describes what you want to reach through the tunnel, often everything. On the server, it describes who that specific peer is allowed to be, usually a single address. The same field, read from two ends, means two different things.

The LAN exclusion problem, and why subtraction does not exist

The most common real question is "how do I route everything except my local network". There is no syntax for subtraction. 0.0.0.0/0 minus 192.168.1.0/24 cannot be expressed, because the field is a list of ranges and nothing more.

The answer is to enumerate the complement: instead of one catch-all, you list the set of CIDR blocks that cover the whole address space apart from the range you want to keep local. It is unglamorous, it produces a long line, and it is the only correct way. The catch-alls themselves are documented plainly: 0.0.0.0/0 matches all IPv4 addresses, ::/0 matches all IPv6.

The symptom that points here

A handshake that completes, and then nothing. wg show displays a recent handshake, the peers clearly found each other, and no traffic passes. When the handshake works, the keys and the endpoint are right by definition, so the problem is downstream, and AllowedIPs is the first place to look: either the destination is not in the list on the sending side, or the source is not accepted on the receiving side.

If the handshake itself never completes, that is a different diagnosis entirely and our handshake troubleshooting guide covers it. And if packets do flow but pages hang halfway, you are probably looking at an MTU problem rather than this field.

Not to be confused with PersistentKeepalive

These two get mixed up because both appear in the peer section and both seem to be about "keeping the connection working". They are unrelated. The manual describes PersistentKeepalive as an interval, between 1 and 65535 seconds, controlling how often an authenticated empty packet is sent to the peer, for the purpose of keeping a stateful firewall or NAT mapping valid. It is disabled by default, and the manual adds that most users will not need it.

AllowedIPs decides what is permitted. PersistentKeepalive decides how often you knock so that a NAT box does not forget you exist.

Getting it right the first time

Set the server peer entries to one address per client and nothing more. Set the client to the ranges you actually want to reach, which for a full tunnel means the catch-alls and for a split tunnel means the specific subnets. Read every AllowedIPs line twice: once as a route, once as a guest list. Our ready-to-use configuration templates apply that separation.

The field is small, it accepts almost anything you type, and it fails silently when it is wrong. That combination is why it deserves more attention than it usually gets.

★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed

Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region

Frequently asked questions

What does AllowedIPs do in WireGuard?
It does two things at once. The wg manual defines it as the list of addresses from which incoming traffic for that peer is allowed, and to which outgoing traffic for that peer is directed. So it is simultaneously a routing rule for what you send and an access control list for what you accept. Most configuration mistakes come from reading only the first half.
Why does my handshake succeed but no traffic passes?
Because the handshake only proves the keys and the endpoint are correct. What happens to packets afterwards is decided by AllowedIPs. Either the destination you are trying to reach is not listed on the sending side, so nothing is routed into the tunnel, or the source address is not listed on the receiving side, so the packet is dropped on arrival.
Can two peers have the same AllowedIPs?
No, and the reason is structural rather than a rule imposed for tidiness. Since the list decides which peer a given destination is sent to, an address belonging to two peers would make the choice ambiguous. This is why each client normally gets its own /32 on the server side rather than the whole subnet.
How do I exclude my local network from the tunnel?
By enumerating the complement, because the field has no subtraction syntax. Rather than one catch-all you list the CIDR blocks that together cover the whole address space except the range you want to keep local. The result is a long line, and it is the only correct way to express it.
What is the difference between AllowedIPs and PersistentKeepalive?
They solve unrelated problems. AllowedIPs decides which traffic is permitted in each direction. PersistentKeepalive is an interval, between 1 and 65535 seconds, controlling how often an authenticated empty packet is sent so a stateful firewall or NAT mapping stays valid. It is off by default, and the manual notes most users will not need it.