4 ovpn instance with src_ip + ipset conditional routing - works great...just one little catch-22


anyone up for a challenge?

I'm currently running 4 different VPN clients on the same wrt1900acs router to 4 separate locations. My LAN clients have the ability to utilise all 4 VPNs using a combination of source based routing rules or domain based IPset matching. Thus I can potentially have any LAN client accessing resources in 4 separate VPNs simultaneously in infinite combinations.

This is very cool and super versatile when you've got kids/devices/content libraries everywhere and a need to go between them a lot. (in Australia we are blocked out of everything!) It all works fine...except for a challenging dns leak conundrum I need some help with ...

#the catch-22
My source IP routed expressVPN LAN clients require that be their locally set dns server. When this is done as per expressvpn's recommendation, you get a perfectly dns-leak free VPN.


Conversely, for leak free simultaneous IPset domain matching, LAN clients must NOT point to,. Instead they must instead point to the local Openwrt instance of dnsmasq ( so as to trigger the creation of the ipset-tag that is needed by the ipset rule that forwards the appropriate traffic to the appropriate VPN gateway. DNSmasq rules also forward the DNS query though the assigned server in dnsmasq.conf ie


The catch-22 is that if a LAN client is set to use, ipset triggers can never occur because local dnsmasq is bypassed. AND setting LAN client to local DNS so as to trigger an IPset routed VPN selection causes the source ip based VPN clients to leak as cannot be used... and so on....

So I'm hoping the forum might have some creative ideas as to how I can trigger the local DNSmasq ipset matches while keeping client DNS at, or some other workable combination.

Under DDWRT I used to force all lan dns queries to and it all used to work leak free...I'm not sure if that's an option here. After loads of searching I cant find any working documentation how to redirect LAN dns to external IPs (there's plenty of docs explaining how to force the other way though which I've also tried for curiosity sake)

I'm running 18.06.4 /openvpn-ssl/dnsmasqfull/mwan3

all ideas welcome!

Perhaps I missed this...but can't you set your dnsmasq to forward resolution requests only to (i.e. setting it as your only DNS server)?

Sure it is. If you only set one server, how would the router "guess" another one?

I would:

  • Browse on the web GUI to Network > Interfaces > WAN
  • Uncheck:


  • and then:


Hi Blowfly,

I can't really help a lot with your question... just an thought:
Why don't you just kick the expressVPN DNS-Service ?
Just set your Router as DNS server and use --> "DNS over HTTPS" or "DNS over TLS" to a trusted DNS-Server <--- to get a "DNSleak free" connection ?
Would be the best solution IMHO.

A personal question: Your setting is pretty close to a setting i try to set up in near Future.

running 4 different VPN clients on the same [...] router to 4 separate locations. My LAN clients have the ability to utilise all 4 VPNs using a combination of source based routing rules or domain based IPset matching.

Any chances that you share your config files with us ? :smiley:

1 Like

If only it were that simple, but unfortunately these suggestions can’t work.

In a multi instance config the VPN default routes must be altered so as all instances can be split tunnels. (Ie the usual open VPN forced routes must be blocked and metrics changed ) which means dns traffic no longer defaults to a tun interface first.

In this scenario Dnsmasq forwards queries out the wan interface, as it should, because it can’t know which of the multiple tunnels to direct queries to until it is told. This is where the dnsmasq server=/domain/tun.dns.IP directive works perfectly and thus no leaks

Currently a source routed VPN client must have set as dns for their query to be sent through the tunnel to replicate the server = / directive above

So, the question is how to push dns queries through the correct tun interface for source routed vpn traffic when client must also be set to use local dns - (which currently causes queries to escape out the wan). This would be a totally killer setup if I could crack this problem.

How many instances of dns have you got running? I got mine working where the dns requests go via the tunnel interface, but it requires dns server per tunnel
Alternative, it might be worth investigation bind dns server, it might do what you want

1 Like

I like your thinking Sammo. I'm trying to visualise how you've achieved this.. I've got 4 instances running. My approach means there's really no limit to how many instances I can now run. I've using 4 coz I have 5 licences in total. I could even run services from multiple vpn suppliers as the same time... its only router RAM, flash space and cpu that will be the limiting factors. mwan is your friend!

Can I assume you are running separate bind instances, each with bind running on a separate IP that is included in each tunnel?? Or is it some other way? How are you keeping all dns forwards sent to other dns servers inside the tunnel. (sorry, my brain is tired after work today!)

I'd be so happy if you could elaborate a little more please


Check this post out


-S, --local, --server=[/[]/[domain/]][[#][@|[#]]

Specify IP address of upstream servers directly. Setting this flag does not suppress reading of /etc/resolv.conf, use --no-resolv to do that. If one or more optional domains are given, that server is used only for those domains and they are queried only using the specified server. This is intended for private nameservers: if you have a nameserver on your network which deals with names of the form xxx.internal.thekelleys.org.uk at then giving the flag --server=/internal.thekelleys.org.uk/ will send all queries for internal machines to that nameserver, everything else will go to the servers in /etc/resolv.conf. DNSSEC validation is turned off for such private nameservers, UNLESS a --trust-anchor is specified for the domain in question. An empty domain specification, // has the special meaning of "unqualified names only" ie names without any dots in them. A non-standard port may be specified as part of the IP address using a # character. More than one --server flag is allowed, with repeated domain or ipaddr parts as required.

More specific domains take precedence over less specific domains, so: --server=/google.com/ --server=/www.google.com/ will send queries for *.google.com to, except *www.google.com, which will go to

The special server address '#' means, "use the standard servers", so --server=/google.com/ --server=/www.google.com/# will send queries for *.google.com to, except *www.google.com which will be forwarded as usual.

Also permitted is a -S flag which gives a domain but no IP address; this tells dnsmasq that a domain is local and it may answer queries from /etc/hosts or DHCP but should never forward queries on that domain to any upstream servers. --local is a synonym for --server to make configuration files clearer in this case.

IPv6 addresses may include an %interface scope-id, eg fe80::202:a412:4512:7bbf%eth0.

The optional string after the @ character tells dnsmasq how to set the source of the queries to this nameserver. It can either be an ip-address, an interface name or both. The ip-address should belong to the machine on which dnsmasq is running, otherwise this server line will be logged and then ignored. If an interface name is given, then queries to the server will be forced via that interface; if an ip-address is given then the source address of the queries will be set to that address; and if both are given then a combination of ip-address and interface name will be used to steer requests to the server. The query-port flag is ignored for any servers which have a source address specified but the port may be specified directly as part of the source address. Forcing queries to an interface is not implemented on all platforms supported by dnsmasq.

1 Like

thanks sammo, great suggestion. This strategy will certainly work for a single VPN. I'll play around with this concept and see where it takes me. I'm not sure how it will go with so many VPNS at once, I need to think that one through.

You will need a dns instance per tunnel for this to work. 2 dns instance for 2 tunnels

If you use special tables for this (e.g. table 2, table 3 and table 4, table 5):


# in /etc/config/network

config route
	option interface 'vpn1'
	option target ''
	option table '2'

config route
	option interface 'vpn2'
	option target ''
	option table '3'

config route
	option interface 'vpn3'
	option target ''
	option table '4'

config route
	option interface 'vpn4'
	option target ''
	option table '5'

config rule
	option src '192.168.a.a/24'
	option target ''
	option table '2'

config rule
	option src '192.168.x.x/24'
	option target ''
	option table '3'

config rule
	option src '192.168.y.y/24'
	option target ''
	option table '4'

config rule
	option src '192.168.z.z/24'
	option target ''
	option table '5'
  • Also, you may also need to setup separate instances of dnsmasq on those IP ranges.
1 Like

Thanks @lleachii this is really helpful. I've been thinking about multiple dnsmasq instances (thanks to @sammo) but this suggestion still may not work in my particular situation. - this is my bad because I haven't explained myself fully. Please forgive me as I've only been using operwrt for two weeks!

My goal has been to be able to toggle any LAN device between 1 or more vpns -- but without ever switching that device between different networks. Switching networks gets old quickly plus other intra-lan issues ariearies with wemo/sonos etc if devices need to be spread over many networks.

I have achieved all this functionality using a single client network but multiple instances of dnsmasq, i assume, will each need their own network?

You can have an dns instance listen to ip address


Listen on the given IP address(es). Both --interface and --listen-address options may be given, in which case the set of both interfaces and addresses is used. Note that if no --interface option is given, but --listen-address is, dnsmasq will not automatically listen on the loopback interface. To achieve this, its IP address,, must be explicitly given as a --listen-address option.

1 Like