Desired scenario: Configure a router to create a VPN connection that is only used by specific client devices (and not the router itself, unless, I suppose, the router’s interface is explicitly configured in the VPN policy to use the VPN connection).
Model: AXT1800 and GL-A1300
Firmware: 4.4.6
OpenWrt 21.02-SNAPSHOT r16399+159-c67509efd7
VPN: Wireguard
Adblock Home: Enabled and configured to intercept all client traffic
Set up: Configured (wireguard) VPN client with VPN policy based on client device → Traffic from following device USE VPN [list of device MAC addresses].
When the VPN is up, the local (default?) route table (when SSHed into the router) is as follows:
0.0.0.0/1 dev wgclient scope link
default via [external_ip] dev eth0 proto static src [external_ip]
[vpn_subnet] dev wgclient proto kernel scope link src [vpn_ip]
128.0.0.0/1 dev wgclient scope link
This route table configures all processes running on the router to route through the VPN connection (0.0.0.0/1 and 128.0.0.0/1 to use the wgclient device). It breaks DNS resolution for local processes running on the router for ISPs that restrict DNS to their local network. This includes breaking UI features like looking up the latest firmware, performing firmware updates, or plug-in lookups. It also creates asymmetric routing for remote access to the WAN interface by routing connection request responses through the VPN rather than back out the WAN interface.
Global (VPN) Options do not help:
Disabling “Services from GL.iNet Use VPN” works properly for GL.iNet services (VPN is not used), but not for other local services running on the router which use the “local” (default?) route table (like DNS resolution using the WAN interface for local processes). This includes breaking UI features like looking up the latest firmware, performing firmware updates, or plug-in lookups.
Disabling “Block Non-VPN Traffic” does not affect the route table options and does not “fix” broken DNS lookups or asymmetric routing.
I am also using Adblock Home, so my ability to configure local router processes to use alternative DNS (not provided by the ISP DHCP) is limited in the UI. Everything works as expected for clients. The issue is with the route table used by local processes running on the router.
I updated /etc/rc.local to add ISP DNS servers to the local route table to enable DNS lookups. I am not sure what else I might break if I script removing the 0.0.0.0/1 and 128.0.0.0/1 from the local route table (or the best place to remove these as they will likely come back if the VPN connection is interrupted and gets reestablished).
Is there a recommended work around/patch to configure the appropriate route table to disable using the VPN for the router’s local processes (unless specifically configured by the VPN policy or for specifically configured networks)? And, is this something GL.iNet could fix in a future firmware release?
Something smells off. OP, check IP Leak from one of your client devices on the MAC whitelist then do the same from one not configured to use said WG Client connection. You should see the VPN vs ISP IPs.
Client devices work fine and there is no “leak” for clients on the MAC allow list. Every other device is supposed to bypass the VPN including the router itself.
What processes need to use the ISP DNS (since GL.iNet does not configure the router itself to use Adblock Home for DNS)?
opkg for updating package list to install (or upgrade) “plugins”
Firmware checking and upgrade processes
What happens in this situation is the router sends DNS requests out the VPN connection instead of the WAN interface to the ISP’s DNS servers. The ISP rejects the DNS requests because the requests originate from the VPN server’s IP address, which is outside the ISP’s network.
Besides DNS, setting up any inbound port forwarding on the WAN interface for remote management (like SSH) does asymmetric routing and won’t work (Syn comes in on WAN interface, response gets sent out VPN).
Putting this all aside, there are multiple VPN configurations supported by GL.iNet.
Everything ignores VPN by default, except for MACs in allow list that are supposed to use VPN
Everything uses the VPN by default, except for MACs in allow list that are supposed to bypass VPN
A few different route-based options that use routing to determine when to use the VPN and when not to.
Explicit Global Setting to block all non-VPN traffic (to completely avoid leaks).
I am specifically asking about option 1, where I want everything to ignore VPN by default except for my explicit allow list of MACs. #4 is explicitly disabled.
I believe everything works perfectly for clients (allowed MACs use the VPN, all other clients do not) with the exception of the route table the the router uses for itself. I think the configuration to use the VPN by default is a mistake/bug. It is the right configuration for just about every other VPN setting, but not for #1 (when the VPN should not be used by default).
I’m not seeing the supposed ‘bug.’ Most VPN providers don’t allow incoming & IPv4 DNS:53 can be specified in the VPN confs. f/w 4.4.6 still uses iptables. Hack away to your heart’s content, try S2S or just change out to Cloudflare or Quad9.
As best I can tell (I can’t track down the exact script/line of code to point out the specific bug), GL.iNet configures multiple route tables to handle different types of traffic (VPN vs non-VPN). These appear to be:
main (also 1) → used by the local router
51 → used for DNS
52 → used for VPN clients (e.g. via_vpn)
53 → used for non-VPN clients (e.g. bypass_vpn)
When a VPN connection is established, the router configures the main AND via_vpn route tables to route 0.0.0.0/1 and 128.0.0.0/1 through the VPN connection (dev wgclient). It does not add these routes to the bypass_vpn route table so the non-VPN devices will not route through the VPN (as expected.
Since I am used an vpn policy that defaults to non-VPN devices, I believe the behavior should be to only configure the via_vpn route table with 0.0.0.0/1 and 128.0.0.0/1 and NOT the main or bypass_vpn route tables.
As I said, this is best I can tell. It’s clear from /usr/bin/route_policy that the 51, 52, and 53 route tables are populated from the main route table, and that the actual route policy marks/tags traffic coming from VPN devices (0x80000) and non-VPN (0x60000). So perhaps the route tables aren’t actually used? I’m not sure.
The main thing I am trying to figure out is how best to configure the main route table to not use the VPN. I could simply delete the 0/1 and 128/1 routes, but am not sure if that will have a downstream impact on for client devices?
Short version is I really love the out-of-the-box convenience provided by GL.iNet and love how (for the most part, with this exception) configuration “just works” without a lot of manual tweaking and configuration. I am a long-time (former now that I’ve migrated all my devices over to GL.iNet) DD-WRT fan. So my goal here is to see if I can influence GL.iNet to tweak their settings specifically when using VPN is NOT the default – if necessary, add another toggle (similar to “allow LAN access” or “use VPN for GL.iNet services”) to allow users to choose if they want local processes on the router to use the VPN or not (I recall an option worded like this in v3 that was replaced in v4 specifically asking about GL.iNet services rather than all services on the router - but I haven’t tracked down the exact differences between v3 and v4 firmware in this respect).
Short answer is that I would if the router was local. I manage a fleet of 12 GL.iNet routers for my family all with slightly different VPN configurations, ISPs, and needs. One of my remote routers has this type of configuration on a university network where I need to balance which devices have access to university network resources (by default) and which route back through my network. I also have my own network admin scripts and capabilities for remotely managing the devices (I use GoodCloud, but I like to have backup remote connectivity options too). I am worried about messing up routing on the device that would affect my family members use of the Internet in unknown ways or disabling my ability to remotely manage the device. And I would like to avoid experimenting with changes that are obviously wrong to someone more knowledgeable than me of how GL.iNet configures its routing.
And in firmware 4.5,128.0.0.0/1 and 0.0.0.0/1 route is gone.
The ip rule is also simplified. The only thing that needs to be remembered is mark 0x8000/0xc000 is not to go via VPN interface.
root@GL-S1300:/tmp# ip rule
...
1100: from all lookup main suppress_prefixlength 0
1101: not from all fwmark 0x8000/0xc000 lookup 8000
...
32766: from all lookup main
32767: from all lookup default
root@GL-S1300:/tmp#
root@GL-S1300:/tmp# ip route show table 8000
default dev wgclient scope link
But in 4.5 firmware there’s still a minor issue for DNS when adguardhome and VPN are both on.
adguardhome will override VPN dns.
I’m working on a new schema for DNS traffic separation.
Services are only for certain local processes, mainly goodcloud.
In firmware 4.4.6, deleting these routes means turning off VPN so that’s not recommended.
Thank you. This is exactly what I was looking for. In most of my situations, adguardhome overriding ISP DNS with VPN is probably sufficient. But nice to know that is being looked at too.
Also nice to know there are beta builds being tested. I will wait for them to get to stable, but it looks like that won’t be too far off. Thanks!
Back again. @hansome, I upgraded to 4.5.0 and I see that 128/1 and 0/1 routes are gone!
Reminder - my configuration is VPN Policy based on the client device; traffic from the following device Use VPN.
Expected behavior - only specifically identified devices (MAC address) will use the VPN. If the router is added to the list, it should use the VPN. If the router is not included in the list of identified devices, it should not use the VPN.
When using the router shell:
VPN Global Option → Allow access to WAN appears to work for upstream DNS
Commands executed on the router still route through the VPN. For example,
traceroute www.gl-inet.com → will go through the VPN
traceroute -i eth0 www.gl-inet.com → will use the WAN interface and not use the VPN (desired default behavior)
Is router originated traffic somehow being marked with 0x8000/0xc000?
Is there a way to make traceroute (all commands from the router, actually) work without the VPN by default without using “sudo -g nonevpn” or specifying the interface (-i [WAN_INTERFACE]) as part of the command?
Similarly, I enable SSH for remote WAN management, but I cannot access it from the WAN interface because (I suspect) the return traffic is getting routed through the VPN (similar to the default behavior of traceroute).
With the configuration I have, I think the default should be to not use the VPN, with the ability to force use of the VPN by using sudo -g vpn or -i options.