[4.9.0] Policy-routing rule writes tunnel client virtual-IP as /8 — entire 10.0.0.0/8 routed into VPN tunnel; exclusion list cannot carve it out
Device: GL-MT6000 (Flint 2) Firmware: 4.9.0 VPN: WireGuard client (Surfshark, native integration login), VPN Dashboard in Policy Mode, two concurrent tunnels
Summary
On 4.9.0, the VPN Dashboard's policy routing installs an ip rule that expresses the tunnel's client virtual IP (a /32 host address) with an /8 prefix. This matches the entire 10.0.0.0/8 range, so all RFC1918 10-space traffic — including the router's own upstream WAN gateway/DNS — is force-routed into the tunnel. The VPN Exclude Specified Domain / IP List feature cannot fix this, because the capture happens via broad ip rule entries (including router-origin traffic) that the exclusion list does not act on.
Specifically, if the WAN port is configured with a DNS address in a 10.x.x.x range, only a single VPN tunnel can connect successfully.
Environment / topology
The router's WAN faces a private 10.9.9.0/24 network. The upstream gateway and DNS server is 10.9.9.1; the router's WAN IP is 10.9.9.2. The tunnel's assigned client virtual IP is 10.14.0.2.
Steps to reproduce
-
GL-MT6000 on 4.9.0, WAN connected to a
10.x.x.xsubnet whose gateway/DNS is a10.xaddress (here10.9.9.1). -
Configure a WireGuard VPN client (Surfshark native login), Policy Mode, and activate it. The client virtual IP is in
10.14.0.x. -
Observe the router can no longer reach any
10.xaddress on the WAN side (e.g. its DNS resolver at10.9.9.1) — the traffic is routed into the tunnel and dies at the VPN exit. -
Try to fix via VPN Dashboard → tunnel → To → Exclude Specified Domain / IP List → add
10.9.9.1. It has no effect.
Evidence
ip rule — note rule 20000 (/8 on a host address) and rule 90109 (router-origin traffic to the tunnel table):
0: from all lookup local
1: from all iif lo lookup 16800
800: from all lookup 9910 suppress_prefixlength 0
6000: from all fwmark 0x1000/0xf000 lookup 1001
6000: from all fwmark 0x2000/0xf000 lookup 1002
6000: from all fwmark 0x8000/0xf000 lookup main
9000: not from all fwmark 0/0xf000 lookup main
9910: not from all fwmark 0/0xf000 blackhole
9920: from all iif br-lan blackhole
10000: from 10.14.0.2 lookup 1001
20000: from all to 10.14.0.2/8 lookup 1001 <-- /8 on a /32 host address = matches all of 10.0.0.0/8
32766: from all lookup main
32767: from all lookup default
90109: from all iif lo lookup 1001 <-- router-origin (locally generated) traffic sent to tunnel table
ip route show table 1001 — the tunnel table also carries a 10.0.0.0/8 route:
default dev wgclient1 proto static scope link
blackhole default proto static metric 254
10.0.0.0/8 dev wgclient1 proto static scope link
ip route get 10.9.9.1 and an unmarked lookup both resolve into the tunnel, not the WAN:
# ip route get 10.9.9.1
10.9.9.1 dev wgclient1 table 1001 src 10.14.0.2 uid 0
# ip route get 10.9.9.1 mark 0
10.9.9.1 dev wgclient1 table 1001 src 10.14.0.2 uid 0
nft list ruleset | grep -i mark returns nothing — confirming the capture is in ip rule policy routing, not nftables marks, which is why the fwmark-based client exclusion list has no bearing on it.
Expected behaviour
-
The tunnel client virtual IP should be associated with the tunnel as a /32 host (
10.14.0.2/32), not/8. Rule 20000 should readto 10.14.0.2/32. -
The tunnel table should not carry a blanket
10.0.0.0/8route; a full-tunnel is served by thedefaultroute already present. -
Directly-connected WAN subnets and the upstream gateway/DNS should remain reachable via the WAN and not be captured by the tunnel.
Actual behaviour
The entire 10.0.0.0/8 is routed into the tunnel. The router cannot reach its own upstream 10.x gateway/DNS, so its own DNS resolution fails whenever the tunnel is up; a second concurrent tunnel cannot resolve its endpoint hostname; and any 10.x resource the router needs is silently blackholed into the VPN exit. The exclusion list cannot correct it.
Likely root cause
The route/rule prefix for the tunnel client virtual IP appears to be derived using classful assumptions — a 10.x address treated as class A (/8) — rather than the /32 host address or the WireGuard interface's actual assigned prefix.
Impact
This breaks any deployment where the router's WAN faces a private 10.0.0.0/8 network — common in enterprise/MSP setups where the GL.iNet sits behind a firewall on a 10.x transit segment. It does not surface for typical home users (LAN 192.168.8.0/24, WAN 192.168.x or a public address), which is likely why it has gone unreported.
Workaround (not a fix)
Pointing the router's own DNS at a public resolver (reachable through the tunnel) restores resolution, and placing the WAN/transit link outside 10.0.0.0/8 avoids the capture — but the underlying /8 route remains and will still swallow any other 10.x destination the router must reach.