jeffsf
I appreciate the engagement. There is a lot of power buried that often doesn’t get used.
The secret (and what GL-iNet implemented in the latest test versions) is a bit messy but straightforward…
-
Configure dnsmasq to add to an ipset when it finds a match on a domain name. Thus, dnsmasq ends up building a list of ip addresses which match the domain name. For the new GL-iNet version, the set to route via VPN is named gl_via_vpn_domain. Over time, this accumulates the ip net for anything resolved with any of the specified domain names.
-
Iptable entries are created with a special matching rule on ipset name. When the rule is matched (viz. ip address is in domain) a mark is set. The mark can be used for further matching in iptables rule evaluation. GL-iNet’s script creates: iptables -t mangle -A ROUTE_POLICY -i br-lan -m set --match-set gl_bypass_vpn_domain dst -j MARK --set-mark 0x80000/0x80000. Thus any packet from the lan matching an IP previously placed in ipset gl_via_vpn_domain by dnsmasq is marked with mark 0x80000.
-
There’s an ip rule that says if you match mark 0x80000, use table 52 for routing. LIkewise, a mark of 0x100000 routes through table 52. One is ip rule add fwmark 0x100000/0x100000 lookup 51 pref 51
-
Finally, gl_route_policy add an explicit route under table number 51 to force traffic through the wg0 interface while table 52 forces traffic to route through the wan interface. The former is used when the policy is to route “via” and the latter for “bypass”.
It’s a long chain (forgive the iptables pun) from a domain name being resolved in dnsmasq to finally being routed, but it works pretty well.
If you’re interested, grab a copy of /etc/init.d/gl_route_policy as well as an iptable, ipset and ip route table dump and enjoy.