You created a guest network, added a route for it, and the guests still leave through your normal internet connection. The tunnel is up, the main LAN works, and the guest devices report an address in the range you assigned, so nothing looks broken. What is usually missing is not a route but a selector: the router decides the path before it considers which interface the packet arrived on, and unless something explicitly matches guest traffic, that traffic inherits the default. The fix is a segment, a policy rule and a reply path, in that order.

The symptom: guests still leave through the WAN

The tell is the exit address. A guest device that reaches the internet through the tunnel will report the tunnel provider's address, and one that inherited the default will report your normal connection. Compare a guest device and a main-LAN device side by side, because the interesting case is when they differ from what you configured and match each other.

The second tell is the absence of any traffic on the tunnel interface while guests are browsing. If the counters do not move, the policy was never applied, and adjusting the tunnel itself cannot help.

Step 1: a real segment, not just a name

An SSID name does not create isolation. Check that the guest network terminates on its own interface, VLAN or bridge, and that the address range is distinct from the trusted LAN. On many consumer access points, the guest SSID is bridged into the same segment as everything else, which makes the rest of this work impossible until that is corrected.

Then confirm the guest range and its DHCP server, and keep the resolver settings associated with that segment rather than with the whole router. A guest subnet that exists only as a comment in a firewall rule is not a segment, and the router will have no interface to match against.

Do not bridge guests into the main LAN to make the VPN easier to configure. That trades the isolation you wanted for a routing shortcut, and it is the usual reason a guest network ends up with access to the printer and the NAS.

Step 2: select the tunnel by source

Routing tables are chosen by destination, so a rule that says "send 0.0.0.0/0 to the tunnel" applies to everyone. Policy routing adds a second dimension: select the table by source address. On a Linux-based router, that is an additional rule plus a dedicated table, and the order matters because the first matching rule wins:

ip rule add from 192.168.60.0/24 lookup 100 priority 1000
ip route add default dev wg0 table 100
ip route get 1.1.1.1 from 192.168.60.10

That last command answers the question directly: which interface will this source use for this destination. Run it before and after the change and you will know whether the policy took effect without touching a browser.

Most router firmware expresses the same thing as an interface rule or a source-based gateway selection. Whichever syntax your platform uses, the principle is identical: match on the ingress interface or source prefix, then override the route for that match only. A rule matched on the destination cannot distinguish a guest from a household device.

Step 3: the reply path and translation

A packet that leaves through the tunnel has to come back. Either the tunnel peer knows a route back to the guest prefix, or the router translates the guest source into the tunnel address. Choose one and write it down, because the failure modes look different: a missing return route gives you a connection that establishes and never answers, while missing translation often produces nothing at all.

nft add rule ip nat POSTROUTING ip saddr 192.168.60.0/24 oifname "wg0" masquerade

If you choose translation, remember that the peer now sees one address for every guest, so any per-client policy at the far end is gone. If you preserve addresses instead, both ends need the guest prefix in their routing and their policy, which is more work and more predictable.

IPv6 needs its own rule. A policy written for IPv4 does not cover the other family, and a guest device with working IPv6 will happily use it while your carefully routed IPv4 path sits idle. Either route both families or disable IPv6 on the guest segment, but do not assume the combined rule you wrote covers what the device actually does. Test with a client that has both families enabled, because that is the case the design has to survive. A laptop that prefers IPv6 looks correct in an IPv4-only test and leaks on the real one.

Test isolation, not just browsing

Browsing proves the exit changed. It does not prove the segment is isolated, and isolation is the reason the guest network exists. From a guest device, try to reach the router's administration interface, a trusted LAN host and a service that should be refused; all three should fail, and the failure should be a policy decision rather than a timeout nobody can explain.

Then test a main-LAN device and confirm its exit did not change. That is the regression this design most often causes: a broad rule intended for guests, applied to every interface because the match was written on the destination.

Finally, decide what happens when the tunnel is down. Guests either get no internet or fall back to a path you approve, and leaving that undecided means a silent fallback to the normal connection, which is exactly the leak the guest policy was meant to prevent. The routing-internet-traffic recipe walks through the same path selection for a pfSense-based router.

Router-originated DNS is the case that surprises people last. If guests use the router as their resolver, the router's own queries follow the router's route rather than the guest rule, so lookups can leave through the normal connection while the application traffic does not. Keep the segment, the resolver and the failure policy in one note, and the next person can check all three without re-deriving the design.

Zvinyorwa zvakafanana