Clients on the LAN resolve through the tunnel and the router's own lookups quietly do not. Package updates, time sync and dynamic DNS all leave by the ordinary uplink while every forwarded query takes the VPN, and nothing in the interface suggests two different paths exist. The explanation is not a bug in the policy but a question of which hook sees the packet. Two flows, one resolver address, and only one of them crosses the router. Sorting them apart is the whole fix.

Two flows, one resolver address

The first flow is the one people picture. A client asks the router's resolver, the resolver forwards upstream, and that forwarded packet passes through the router on its way out. That packet is visible to anything watching forwarded traffic.

The second flow never arrives from anywhere. The router creates it, so there is no inbound packet and no forwarding step to match.

Both may target the same resolver address, which is exactly why the difference is easy to miss. Same destination, different origin, different chain. Once you see the origin, the rest of the diagnosis follows.

Forwarded and locally generated packets enter differently

Forwarded traffic is evaluated when it arrives from another interface. Policy routing packages expose that as a prerouting chain, and a rule placed there sees every packet crossing the router. That is why client lookups behave exactly as the policy describes, and why the router ignores it. The rule is not wrong, it is merely attached to a hook the router never reaches. Move it, and the same match starts working.

Locally generated traffic is created by a process on the router and enters the output path instead. It is routed by the router's own decision and only meets policy if the policy covers that chain. There is no inbound interface to match and no forwarding decision to observe.

That is a property of where packets are born rather than of any particular package. A rule written for one chain simply has no opinion about the other. No amount of rule tuning changes that.

Select the output chain, then narrow the match

The fix is to attach the same intent to the output chain as well, or to move the rule there when the router's own queries are what you care about. In an OpenWrt setup built on a policy routing package, that means choosing output rather than prerouting in the rule's chain setting. Keep both rules if both populations need coverage.

Then narrow what the rule matches. Destination resolver addresses on the port the resolver actually uses is a much smaller decision than sending everything the router originates into the tunnel.

Keep the two rules explicit rather than trying to write one that covers both chains. Separate rules are easier to read, and they let you disable the router's path without disturbing client traffic when you are debugging. They also make the counters meaningful one at a time.

Keep the tunnel's own transport out of the rule

The tunnel's outer connection is also created by the router. A rule that sends all locally generated traffic into the tunnel will route the tunnel through itself, and it will not come up at all.

Management access is the second casualty. Administrative sessions originated from the router, or replies to them, can be pulled into the tunnel by an over-broad local rule and become unreachable from the LAN.

Exclude the tunnel endpoint from the match, and keep the rule scoped to the resolver addresses. That is enough for the DNS requirement and small enough to reason about.

Test both populations, not one

Watch the router make its own query and note which interface carried it. Repeat the lookup from a LAN host and note the path that one took. Counters on the policy rules make both answers visible without guessing.

Treat the results as two findings. A client that resolves through the tunnel says nothing about the router, and a router that resolves correctly says nothing about a client on a different listener. Write them as separate lines in the change record.

Check the port as well: a rule matching destination port 53 misses a resolver reached over DNS over TLS on 853 or an HTTPS endpoint. Match the transport the configured upstream really uses, and the leak closes for the right reason.

Erthyglow kevrennek