Learn WireGuard - Routing & Allowed IPs
Episode 6 of 23

Learn WireGuard - Routing & Allowed IPs

This episode dissects AllowedIPs as the heart of cryptokey routing: why it is not a firewall, how to choose between a full tunnel with 0.0.0.0/0 and a split tunnel with specific subnets, and how wg-quick adds routes to ip route automatically.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Of all the WireGuard concepts, AllowedIPs is the most misunderstood. Many people think it is a firewall rule. In fact, AllowedIPs is the core of cryptokey routing: it determines which addresses are considered "owned" by a given peer, both for outbound traffic and for validating inbound traffic.

Episode 6 explains how AllowedIPs works, how to choose between a full tunnel and a split tunnel, and how wg-quick translates this line into routes in the routing table. After this episode, you will be able to design precise tunnel routing policies.

To truly master this section, you need to shift your thinking: from "a list of firewall permissions" to "a map of address ownership." This small change of perspective will prevent a lot of confusion when you design topologies with many peers and subnets.

AllowedIPs: Not a Firewall

One Field, Two Directions

Each AllowedIPs works in both directions at once. For outbound traffic, it says "send packets to this address via that peer." For inbound traffic, it says "only accept packets from this address if they come from that peer." Both directions are bound by cryptography, not by list-based filtering.

Consequently, AllowedIPs is not an allowlist that explicitly rejects everything else. Incoming packets whose source address does not match any peer's AllowedIPs are dropped by the kernel, not forwarded to the routing table. This is why adding a subnet to AllowedIPs is always balanced by adding a route on the network side.

The difference from a firewall is also visible in how WireGuard treats unmatched packets: no log, no explicit rejection, just silently dropped packets. So when tunnel traffic seems to disappear, the first step is to check whether the destination address is covered by the correct peer's AllowedIPs.

A Two-Direction Example

AllowedIPs for one peer on the server
[Peer]
PublicKey = <kunci publik client>
AllowedIPs = 10.0.0.2/32

With this line, the server sends traffic to 10.0.0.2 through the client's tunnel and only accepts packets from 10.0.0.2 if they come from that public key.

Full Tunnel with 0.0.0.0/0

Forwarding All Traffic

For remote access that wants to carry all of a device's traffic through the tunnel, use AllowedIPs = 0.0.0.0/0. This is known as a full tunnel: all of the device's IPv4 traffic enters the tunnel, exits on the server side, and is then forwarded to the internet.

Full tunnel on the client side
[Interface]
Address = 10.0.0.2/24
PrivateKey = <kunci privat client>
 
[Peer]
PublicKey = <kunci publik server>
AllowedIPs = 0.0.0.0/0
Endpoint = 203.0.113.5:51820

With AllowedIPs = 0.0.0.0/0, wg-quick makes the default route go through wg0. The effect: the public IP the outside world sees for you is the server's address, not your local one. This is the pattern used to bypass geographic filters or untrusted networks.

Keep in mind that a full tunnel also redirects your local traffic. Access to devices on your same local network via local addresses must be handled with more specific routes; otherwise that traffic also gets carried to the server.

Requirements on the Server Side

A full tunnel is only useful if the server is willing to forward your traffic. The server needs to enable forwarding and masquerade:

Enable forwarding and NAT on the server
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Without MASQUERADE, packets leaving the server still carry the tunnel address 10.0.0.2, which cannot be routed back over the internet.

Split Tunnel with Specific Subnets

Sending Only Certain Traffic

Not every connection has to go through the tunnel. With a split tunnel, you only route specific subnets through WireGuard and let everything else use the regular internet:

Split tunnel to the office subnet
[Peer]
PublicKey = <kunci publik server>
AllowedIPs = 10.0.0.0/24, 192.168.50.0/24
Endpoint = 203.0.113.5:51820

AllowedIPs can hold multiple comma-separated subnets. Traffic to 10.0.0.0/24 and 192.168.50.0/24 enters the tunnel, while normal browsing stays on your original connection. A split tunnel saves bandwidth and is faster for everyday internet access.

How It Works with ip route

When wg-quick applies AllowedIPs, it adds a specific route for each of those subnets to the routing table. Inspect the result:

See the routes added by wg-quick
ip route show

The output of ip route show shows routes to 10.0.0.0/24 and 192.168.50.0/24 with dev wg0. These specific routes win because their prefix is longer than the default route's. If you do not want wg-quick to touch the routing table at all, set Table = off in [Interface] — episode 9 will use this trick for site-to-site.

Choosing the Default Route with Priority Rules

Sometimes you want all traffic through the tunnel except a few subnets. The solution: combine AllowedIPs = 0.0.0.0/0 with explicit routes that send certain subnets back to the local gateway, or use the Table feature and ip rule policy routing for granular control.

Understanding these priority rules is important because it is easy to misconfigure: the most specific route always wins, and wg-quick adds a specific route for every AllowedIPs. Before adding ip rule entries, make sure you understand the routing table priority order on Linux.

Start from the simplest need: write down which subnets must enter the tunnel and which must not, then translate that into AllowedIPs. This discipline prevents conflicting rules later on.

Closing

Episode 6 completed your understanding of routing: AllowedIPs is a two-way cryptokey routing decision, a full tunnel is triggered by 0.0.0.0/0, a split tunnel uses specific subnets, and wg-quick translates all of it into routes in ip route.

Key takeaways:

  • AllowedIPs determines address ownership, not just firewall permission.
  • 0.0.0.0/0 creates a full tunnel through the server.
  • Specific subnets create a bandwidth-saving split tunnel.
  • wg-quick adds routes automatically; use Table = off to disable it.
  • A full tunnel needs ip_forward and MASQUERADE on the server.

In episode 7 we cover NAT traversal and endpoint discovery — how WireGuard keeps communicating with peers behind NAT, the role of PersistentKeepalive, UDP hole punching techniques, and how endpoints are learned dynamically.