The router reaches the internet through its tunnel while a laptop behind it still reports the ISP address. Adding accept rules does not help, and that failure is informative: filtering answers whether a packet may pass, not where it goes. The interface choice was already made by a routing lookup that knows nothing about your client list. Fix the lookup and the firewall stops being the suspect.

A filter rule cannot choose an interface

Packet flow on a Linux router runs the routing decision first and the forward hook afterwards. By the time a rule matches on the outgoing tunnel device, the kernel has already decided that the tunnel is the way out. If the main table still prefers the WAN default route, the packet is on its way to the ISP and the accept rule you just wrote never sees it. That single ordering fact explains why a page of new firewall rules changes nothing.

The example below uses a LAN of 192.168.8.0/24 on br-lan, a tunnel device tun0, and one set-top box at 192.168.8.23 that should take the tunnel.

Read the lookup before editing rules

Ask the kernel to resolve a route on behalf of that client. The reply includes the outgoing device and the source address that would be chosen, which is everything you need to confirm the diagnosis. If the answer names the WAN device, the packet never had a chance to reach your rule.

ip -4 route get 198.51.100.7 from 192.168.8.23

Repeat the query for a client that should stay on the ordinary path. When both answers name the same device, no per-source policy is in play yet, and the fix belongs in routing rather than filtering.

Attach a table to the clients you mean to cover

Policy routing inserts a rule lookup ahead of the main table. Build a table whose default route is the tunnel, then bind that table to a selector: an input interface, a source address, or a firewall mark. Priorities decide order, and the main table sits far down the list at 32766, so a low-numbered rule is consulted first. Interface selectors cover every client on the bridge; address selectors cover one machine.

ip -4 route add default dev tun0 table 200
ip -4 rule add iif br-lan lookup 200 priority 200

Firmware interfaces usually expose the same objects as a policy routing or VPN policy page. A device list there is easier to maintain than hand-written rules and tends to survive upgrades that change rule syntax.

Pick the selector on purpose. An interface rule is short and future-proof but also catches the router's own management traffic arriving on that bridge. A source rule is exact and needs an edit whenever the device list changes. Write the choice down, because the next person to ask why one device behaves differently will need it.

Keep local destinations out of the tunnel

A fresh table knows only the routes you put in it. The LAN prefix is missing, so printer and NAS traffic would follow the tunnel default and disappear. A throw route ends the lookup in this table and hands the decision back to the main table.

ip -4 route add throw 192.168.8.0/24 table 200

Skip that route and local shares break, and the router's own management session can vanish if the selector is broader than intended. Then settle the source question: tunnel packets that still carry LAN addresses need the far side to know a return path, while masquerading on the tunnel removes that requirement and also removes the client identity the far side would see.

Rules and routes added at runtime are gone after a reboot or a firmware update. Add them to the router's startup mechanism, reboot once, and retest from the client: its public address, a second client that should stay on the WAN, and the tunnel counters during a fresh connection.

Lahatsoratra mifandraika