SOLVED: Want WireGuard ONLY for SELECTED domains

I would like to use WireGuard only for selected domains and have all other traffic go through the normal WAN interface. This is backwards to all those who want VPN on except for Netflix.

Since my exceptions are domain-based, I need to use an ipset with dnsmasq… I’ve tried the vpn-policy-routing package, but it does not work out-of-the box with GL-iNet’s setup.

I’ve tried modifying the /etc/init.d/wireguard script, but when I don’t disable lan2wan forwarding, after removing the default routes feeding wg0 (0.0.0.0/1 and 12.0.0.0/1) I can get traffic to go out through the WAN. But in testing, when I manually add a route for an IP address to the wg0 interface, it always goes out the wan.

This is not an unusual use case where I would want to route only corporate traffic, identifiable by the company’s domain names, through the VPN and send everything else out the wan port.

Any suggestions?
Thanks

Forgot to mention, I’m doing this on an MT300Nv2 device running 3.0.12

Routing works based on IP addresses, not host names. Assuming that you have one or more IP ranges, then the somewhat confusingly named AllowedIPs parameter is probably what you need.

See, for example, the Split Tunneling section of https://emanuelduss.ch/2018/09/wireguard-vpn-road-warrior-setup/

Appreciate the link. I’ll dig into it further.

It ought to be possible, however, to route by domain. Use the ipset capability of dnsmasq to record the affected ip addresses in an ipset table and apply a fwmark to those addresses.

We can incorporate the fwmark in the iptables and ip rules to separate the special domain traffic from the rest and route accordingly.

This was the basis of the vpn-policy-routing package mentioned in the OP. (See here.)

But that package was just doesn’t quite seem to work with GL-iNet’s implementation of wireguard. The /etc/init.d/wireguard script forces all traffic to wg0 and uses iptables to block lan-wan and forwarding output, leaving wg0 as the only output interface. Then it adds two routes which effectively become a default route to wg0.

Changing those routes don’t help. Adding a route to a specific ip address still forces the traffic over WG. If I disable the wg script disables, then everything goes to the wan interface and nothing to wg0.

I’m just not getting something right about how wg manipulates iptables and routing to achieve the “route-all” and how I can modify it so it could route based on an fwmark.

Maybe you can look at VPN policies, and here’s the documentation https://docs.gl-inet.com/en/3/app/vpn_policies/

Not possible, routing is done on the packet level, where you have MAC and IP addresses, not host names. Host names have long disappeared from the processing by the time routing occurs (typically gone before the socket is even opened, before any traffic flows).

ipset is a firewall (netfilter) construct. Routing tables are different. dnsmasq is something else entirely, being a DHCP and DNS server.

To dzwghx

THANK YOU. I was running the production version and scripting away. I never thought to check the alpha or beta versions.

Everything worked exactly as described.

Love these mini-routers so much I just ordered 2 more (plus a Slate).

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…

  1. 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.

  2. 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.

  3. 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

  4. 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.

You have a good analysis of the scripts.