Hello,
I’m trying to accomplish 2 things at once:
- learn a bit about how policy based routing works in Linux
- have all outbound UDP traffic with source port 41641 (aka outbound Tailscale traffic), from
lanand from the router itself, bypass the always-on Wireguard VPN which otherwise handles all internet traffic
I’m aware of the pbr plugin but I’m wondering if I can accomplish this myself on the command line by using ip commands, so I gain better understanding of how the system works under the covers.
I’m attempting to do this on a device running vanilla OpenWrt 24.10, but I first managed to set it up on a device running GL.iNet’s flavor which also has an always-on Wireguard VPN. GL.iNet’s firmware is already set up to bypass the VPN if fwmark 0x8000/0xc000 is set on packets. I’d like to do something similar on my vanilla OpenWrt device, but I’ve gotten to the point where I’m going round and round with the documentation and I’m not sure how to proceed.
Most notably, I think there is a difference between how GL.iNet routes traffic thru Wireguard, and how vanilla OpenWrt with the luci-proto-wireguard package does it.
On the GL.iNet device, if I run ip route show table all, near the top there is a line
default dev wgclient1 table 1001 proto static scope link
if I then run ip -d route show table 1001 I see the following:
unicast default dev wgclient1 proto static scope link
blackhole default proto static scope global metric 254
unicast 10.99.101.0/24 dev wgclient1 proto static scope link
I’m very new at this, and maybe I’m misunderstanding what the complete output of ip route show table all is telling me, but this seems to me to mean that the Wireguard interface wgclient1 is set as the default way for traffic to go, by sending it (?) via table 1001.
Then when I run ip rule on the GLi device, I see these two rules among others:
6000: from all fwmark 0x8000/0xf000 lookup main
6000: from all fwmark 0x1000/0xf000 lookup 1001
Thus I can see how packets with fwmark of 0x8000 would be sent by main instead of the Wireguard interface. (I’m not sure where fwmark 0x1000 is set, if it is).
Now, on my vanilla OpenWrt device using luci-proto-wireguard to set up a Wireguard VPN for all internet traffic, it’s done differently.
When I run ip route show table all, near the top I see
default dev wg1 proto static scope link
And when I run ip -d route show table main, I see
unicast default dev wg1 proto static scope link
unicast 10.180.99.0/24 dev wg1 proto kernel scope link src 10.180.99.3
unicast x.x.x.x via 10.0.0.1 dev eth2 proto static scope global
unicast 10.0.0.0/24 dev eth2 proto kernel scope link src 10.0.0.2
unicast 192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.1
where x.x.x.x is the public IP of my VPN exit point.
I’m not really sure how to interpret this actually. I’m still too much of a noob to really understand everything these commands are telling me. But what I do believe is that when luci-proto-wireguard sets up a Wireguard interface to handle internet traffic by default, it doesn’t do so by creating a table for Wireguard and sending traffic to that. Instead it’s altering the main table (and maybe doing some other things) to accomplish this.
What I’d like to do is set things up similar to how GLi’s firmware does it, but compatible with the setup created by luci-proto-wireguard. I think what I need to do is create a table specifically for the traffic I want to bypass the VPN, then use a Traffic Rule (Luci terminology) to set a fwmark on the relevant packets, and then create a rule to send marked packets to the table I created which route them out the router’s wan interface instead of by wg1.
My issues with this are:
- I don’t know if this is a correct approach
- I don’t know if this is possible with built-in commands or if a plugin such as
pbris required - I’m not sure where to begin as far as commands to accomplish this
I’d love to hear any suggestions anyone has, or links to tutorials / guides / posts about doing what I’m trying to do. I’ve run dozens of searches at this point, but everything I find seems different enough to what I’m trying to accomplish that it doesn’t really apply.