DNS requests from different subnets to different DNS servers on different WAN interfaces

I am trying to set up OpenVPN split tunneling (with one WiFI network connected to the VPN and all the other interfaces going via the normal WAN) and (after many, many hours being wasted to a stupid bug that breaks a firewall zone if the interface in it has an all caps name!) I have finally got it mostly working.

But it has a problem of leaking the DNS requests out the standard WAN interface and to whatever DNS server the WAN interface has been set to.

I have set up OpenVPN with the route-nopull option and I am using a policy based routing rule to direct all traffic from the subnet I set up for that WiFi network to the VPNs tun0 interface.

I can see the DNS server the OpenVPN connection is trying to push, but I am not sure how to make dnsmasq use that server for all requests from that WiFi networks subnet and only send them out via tun0, while at the same time not doing it for the other subnet (and thus a normal setup of sending those requests out the normal WAN interface).

Any ideas would be appreciated.

-Is your wifi logically separated? ( i.e. Explain the router subnet structure )
-Will you require fallback to WAN ( dns/traffic ) for the tunneled hosts

##################################### Add to /etc/openvpn/"vpn".conf
#script-security 2
#up "/etc/openvpn/tunup.sh"
#down "/etc/openvpn/tundown.sh"
cat<<'EOF' > /etc/openvpn/tunup.sh
#!/bin/sh
VPNCLINET="192.168.77.0/22"
IPT=$(which iptables)
echo "$IPT -A zone_lan_prerouting -s $VPNCLINET -p udp -m udp --dport 53 -m comment --comment "VPN-DNS-MANGLE" j DNAT --to-destination $(echo $foreign_option_1 | sed -e 's/dhcp-option DOMAIN//g' -e 's/dhcp-option DNS//g')"
EOF
chmod +x /etc/openvpn/tunup.sh

etc. etc.

Or if you run another bind/dnsmasq instance..... something like;

echo $foreign_option_1 | sed -e 's/dhcp-option DOMAIN/domain/g' -e 's/dhcp-option DNS/nameserver/g' > /tmp/resolv.dnsmasq2
echo $foreign_option_2 | sed -e 's/dhcp-option DOMAIN/domain/g' -e 's/dhcp-option DNS/nameserver/g' >> /tmp/resolv.dnsmasq2

then add /tmp/resolv.dnsmasq2 to conf for the second dnsmasq instance listening on the WIFI subnet instance under resolv files etc.

The second instance is way simpler :slight_smile: Use a down script to switch back the resolv.wan if you want no killswitch. Also will depend on how much resources you have.....

I don't know if it's possible. But you could configure the dhcp server with the dns servers from the VPN provider. It is done as custom dhcp options. You can also block access to port 53 on the router itself from the WiFi network to stop the clients from using its dnsmasq.

1 Like

The WiFi SSID I want to use for the VPN is a second SSID off the 5ghz radio (physical interface wl0.1) and that is put in a separate interface that is using a static address that I set in a different subnet than the normal LAN interface and with DHCP running, that is then put into a firewall zone that is connected with an other zone I setup with tun0 in it.

I will not be needing fallback, I want this network to be completely VPN only.

How much resources do you have.....

Basically, you all good cause you have a separate router ip to run dnsmasq on..... but as stated, that will use a bit more memory....

To start with... take your dnsmasq off the router wifi subnet.....

/etc/config/dhcp ( under the dnsmasq section )

option notinterface 'wifi0whatever'
/etc/init.d/dnsmasq restart
netstat -lnp ( change your public ip if your posting )

This page https://openwrt.org/docs/guide-user/base-system/dhcp#multiple_dhcpdns_serverforwarder_instances is a tad hard to follow .... see how you go with it.....

Make a backup if your /etc/ directory too i suppose before you start..... The webgui backup will do....

1 Like

I have a WRT1200AC, so plenty of RAM and CPU power.

Methods:

  • Intercept and redirect DNS-traffic via iptables based on source address/interface.
  • Use multiple instances of Dnsmasq with different configurations running on different interfaces/ports.
  • Push different DNS-settings via DHCP-option as suggested by @mikma.
1 Like

Multiple instances of your DNS server is another option. Either multiples of dnsmasq or some combination of dnsmasq and unbound would work.

1 Like

Would running 2 copies of dnsmasq break adblock?

If you're trying to separate your upstream DNS providers, you'd then likely need two instances of adblock as well (I'm assuming it works as a DNS proxy between the local server and the upstream servers).

See below

adblock doesn't really work like a proxy, instead it merely injects local DNS overrides (based on the fetched block lists) into dnsmasq's configuration answering with NXDOMAIN (server=/example.com/).

No, but I presume you have to enable adblock for extra instances manually.

Out of those options I think multiple instances of dnsmasq would be what I will try for, the problem is that the linked wiki page is a bit sparse in how to configure it.
I am mainly not sure if the given example of

config 'dnsmasq' 'hotspot'

is meant to replace the

config dnsmasq

at the top of /etc/config/dhcp or if it is in addition to it (and if so, do I need 2 of them or just the normal one plus the extra instance)?

Yep, you need to add an extra section.
Clone the options and modify them if required.

OK, the problem is now that I am not sure how a instance can be directed out a different WAN interface.
I guess that would require an iptables rule?

# Use ISP DNS for Dnsmasq instance #0
uci -q delete network.wan.peerdns
uci -q delete network.wan.dns
uci -q delete network.wan6.peerdns
uci -q delete network.wan6.dns
uci commit network
service network reload
uci -q delete dhcp.@dnsmasq[0].server
uci -q delete dhcp.@dnsmasq[0].noresolv
uci commit dhcp
service dnsmasq restart
# Use VPN DNS for Dnsmasq instance #1
uci -q delete dhcp.@dnsmasq[1].server
uci add_list dhcp.@dnsmasq[1].server="VPN_DNS1"
uci add_list dhcp.@dnsmasq[1].server="VPN_DNS2"
uci set dhcp.@dnsmasq[1].noresolv="1"
uci commit dhcp
service dnsmasq restart

That did not work,
I replaced "VPN_DNS" with the VPN DNS address but it just used the ISP one instead and each time I did

service dnsmasq restart

it printed

udhcpc: started, v1.28.4
udhcpc: sending discover
udhcpc: no lease, failing
udhcpc: started, v1.28.4
udhcpc: sending discover
udhcpc: no lease, failing
udhcpc: started, v1.28.4
udhcpc: sending discover
udhcpc: no lease, failing

uci show dhcp
netstat -l -n -p | grep -e dnsmasq
pgrep -f -a dnsmasq

OK, I think I made a mistake by running it as

uci add_list dhcp.@dnsmasq[1].server="10.255.255.2"

and not

uci add_list dhcp.vpn.server="10.255.255.2"

Which is what I named my instance as.

After that I now have

dhcp.@dnsmasq[0]=dnsmasq
dhcp.@dnsmasq[0].domainneeded='1'
dhcp.@dnsmasq[0].localise_queries='1'
dhcp.@dnsmasq[0].rebind_protection='1'
dhcp.@dnsmasq[0].rebind_localhost='1'
dhcp.@dnsmasq[0].local='/lan/'
dhcp.@dnsmasq[0].domain='lan'
dhcp.@dnsmasq[0].expandhosts='1'
dhcp.@dnsmasq[0].authoritative='1'
dhcp.@dnsmasq[0].readethers='1'
dhcp.@dnsmasq[0].leasefile='/tmp/dhcp.leases'
dhcp.@dnsmasq[0].resolvfile='/tmp/resolv.conf.auto'
dhcp.@dnsmasq[0].nonwildcard='1'
dhcp.@dnsmasq[0].localservice='1'
dhcp.@dnsmasq[0].logqueries='1'
dhcp.@dnsmasq[0].serversfile='/tmp/adb_list.overall'
dhcp.@dnsmasq[0].notinterface='lanvpn'
dhcp.vpn=dnsmasq
dhcp.vpn.domainneeded='1'
dhcp.vpn.localise_queries='1'
dhcp.vpn.rebind_protection='1'
dhcp.vpn.rebind_localhost='1'
dhcp.vpn.local='/lan/'
dhcp.vpn.domain='lanvpn'
dhcp.vpn.expandhosts='1'
dhcp.vpn.authoritative='1'
dhcp.vpn.readethers='1'
dhcp.vpn.leasefile='/tmp/dhcp.leases'
dhcp.vpn.resolvfile='/tmp/resolv.conf.vpn'
dhcp.vpn.nonwildcard='1'
dhcp.vpn.localservice='1'
dhcp.vpn.logqueries='1'
dhcp.vpn.serversfile='/tmp/adb_list.overall'
dhcp.vpn.noresolv='1'
dhcp.vpn.server='10.255.255.2'
dhcp.lan=dhcp
dhcp.lan.interface='lan'
dhcp.lan.start='100'
dhcp.lan.limit='150'
dhcp.lan.leasetime='12h'
dhcp.lan.dhcpv6='server'
dhcp.lan.ra='server'
dhcp.lan.ra_management='1'
dhcp.wan=dhcp
dhcp.wan.interface='wan'
dhcp.wan.ignore='1'
dhcp.odhcpd=odhcpd
dhcp.odhcpd.maindhcp='0'
dhcp.odhcpd.leasefile='/tmp/hosts/odhcpd'
dhcp.odhcpd.leasetrigger='/usr/sbin/odhcpd-update'
dhcp.odhcpd.loglevel='4'
dhcp.@domain[0]=domain
dhcp.@domain[0].ip='192.168.77.7'
dhcp.@domain[0].name='openwrt.lan'
dhcp.lanvpn=dhcp
dhcp.lanvpn.start='100'
dhcp.lanvpn.leasetime='12h'
dhcp.lanvpn.limit='150'
dhcp.lanvpn.interface='lanvpn'
dhcp.lanvpn.instance='vpn'

But no DNS access for the VPN or the normal network, both being sent to 10.255.255.2 (which is not what I want) but never getting a response (indicating it is try to reach it over the WAN).

uci rename dhcp.@dnsmasq[0]="dnsmasq"
uci set dhcp.lan.instance="dnsmasq"
uci commit dhcp
service dnsmasq restart