How to bypass VPN on GL router

I find that as soon as a VPN client is active on a GL router with Tailscale enabled, all traffic from external clients set to use that router as a Tailscale exit node, will go through that VPN.

Is there any way to make Tailscale exit node traffic not go through the VPN without turning the VPN off (which is not acceptable in my case)?

1 Like

Mabye you can check vpn policy?

I have. I tried exclusion by domain and exclusion by client MAC but neither are respected by remote Tailscale clients using the GL router as an exit node. They always go through the VPN no matter the policy.

You can try mark traffic to 0x8000 to bypass vpn.

iptables -w -t mangle -I PREROUTING -i tailscale0 -j MARK --set-mark 0x8000/0xc000
2 Likes

I am willing to try this, but I can only do it on an important router because the other's don't support Tailscale. As I am not familiar with iptables, could you also give the matching undo command in case it causes problems?

Also, will this firewall setting survive a reboot or would I need to do something else for that? Perhaps by going through LuCi?

It does not survive a reboot. So just try.

Wow, it worked. Ok, now I do want to know how to make it permanent.

Just write to custome firewalls.

Pls go to
luci/admin/network/firewall/custom

1 Like

I copy/pasted the iptables command in that field in LuCi and rebooted, but then the VPN bypass no longer worked. The command was properly saved in LuCi though, as it is still there. I ran the command again from the terminal and, strangely, that also no longer produced the desired VPN bypass. I then commented out the command in LuCi, saved, rebooted, passed the command manually and it worked again. Any idea what might be going on?

Maybe LuCi does not have the necessary privileges to run the command and beyond that there is some issue with running the command twice?

1 Like

Use this command to write it here for better compatibility with route_policy scripts.

cat >>/etc/firewall.vpn_server_policy.sh <<EOF


iptables -w -t mangle -D PREROUTING -i tailscale0 -j MARK --set-mark 0x8000/0xc000
iptables -w -t mangle -I PREROUTING -i tailscale0 -j MARK --set-mark 0x8000/0xc000
EOF

To recover back:

cp /rom/etc/firewall.vpn_server_policy.sh /etc/

Add a brief explanation:

0x8000 is the mark for any packet that bypass vpn.
That the ip rule is the root control point, rule 1100 and rule 1101.

root@GL-X3000:~# ip rule
0:      from all lookup local
1099:   from all fwmark 0x80000/0xc0000 lookup main    #this is to force tailscale low layer traffic to go main router table
1100:   from all lookup main suppress_prefixlength 0       # this means other than default route, the directly connected routes in main table has high priority (1100)
1101:   not from all fwmark 0x8000/0xc000 lookup 8000  # this means if the packet is not marked with 0x8000, it will go by table 8000 which is to use vpn.
32766:  from all lookup main # packets marked with 0x8000, will not use VPN
32767:  from all lookup default

For example, wireguard 51820 port traffic will bypass vpn to avoid route loop.
This idea is from: https://www.wireguard.com/netns/ Improved Rule-based Routing

You can see there is fwmark:0x8000.

root@GL-X3000:~# wg
interface: wgclient
  public key: lUKZXMFZ6x0C==================
  private key: (hidden)
  listening port: 53328
  fwmark: 0x8000

peer: OLtF4VV9Fo2IVp======================
  endpoint: 1.2.3.4:51820
  allowed ips: 0.0.0.0/0, ::/0
  latest handshake: 1 minute, 43 seconds ago
  transfer: 30.33 MiB received, 29.59 MiB sent
  persistent keepalive: every 25 seconds

The route table for non vpn traffic is main table:
root@GL-X3000:~# ip route show table main

default via 192.168.10.1 dev eth0 proto static src 192.168.10.135 
10.90.0.0/24 dev wgclient proto kernel scope link src 10.90.0.2 
192.168.9.0/24 dev br-guest proto kernel scope link src 192.168.9.1 
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.135 
192.168.135.0/24 dev br-lan proto kernel scope link src 192.168.135.1 

The route table for vpn traffic is table 8000.

root@GL-X3000:~# ip route show table 8000
default dev wgclient scope link

The mark 0x8000 is also used in vpn policy.

2 Likes

Thank you very much. This way I was able to achieve persistence across reboots.

What about persistence across firmware updates?

After confirming there's no side effect with existing functions, we can merge this change into firmware.

I am not sure about that. I think in other scenarios it may be preferable for remote Tailscale clients to be routed through the VPN. In fact, I also have that scenario. And in that scenario, one thing that is still missing is support for the kill switch, meaning, if the VPN is down, then remote Tailscale clients should not simply bypass it as is currently the case.

1 Like