[Solved] DNS query sent on wrong interface

So, I discovered some really unexpected behavior on my network.
TL;DR: DNS queries from my LAN clients is sent out on a WireGuard VPN interface, which I have never configured it to do, it was meant to be sent on WAN.

I'm simplifying the explanation a little bit to remove anything that is not relevant. Let's say that I had the original network interfaces, LAN and WAN.

LAN interface:

config interface 'LAN'
	option proto 'static'
	option ipaddr '10.0.10.1'
	option netmask '255.255.255.0'
	option type 'bridge'
	option device 'eth0.10'

In tihs config, "list dns" is not set. So the clients send their DNS requests to the router at 10.0.10.1, which in turn send it to the upstream DNS server over the WAN interface (WAN is a DHCP client). Everything is perfectly normal so far.

The problem comes when I add a WireGuard VPN interface, and another local interface (LAN2, on another VLAN), that is supposed to use the VPN interface instead of WAN.

WireGuard VPN interface:

config interface 'WireGuard_VPN'
	option proto 'wireguard'
	option private_key 'SuperSecretKey'
	list addresses '10.0.69.5/32'
	option delegate '0'

WireGuard Peer:

config WireGuard_VPN
	option description 'SomePeer'
	option public_key 'PublicKeyOfPeer'
	option route_allowed_ips '1'
	option endpoint_host '50.100.150.200'
	option endpoint_port '51820'
	list allowed_ips '10.0.69.0/24'
	list allowed_ips '1.1.1.1'

LAN2 interface:

config interface 'LAN2'
	option proto 'static'
	option device 'eth0.20'
	option ipaddr '10.0.20.1'
	option netmask '255.255.255.0'
	option delegate '0'
	option defaultroute '0'
	list dns '1.1.1.1'

The key thing here is that LAN2 is set to use DNS server 1.1.1.1, which is routed over the WireGuard VPN interface, not on WAN. I set firewall rules to allow LAN to send to WAN, but not WireGuard_VPN. LAN2 is allowed to send to WireGuard_VPN, but not WAN. Everything seems to be working ok.

Then I did some packet capture with tcpdump, and saw DNS queries originating from LAN clients, on the WireGuard_VPN interface. LAN clients are sending queries to 10.0.10.1:53, which I expected to be sent out on WAN, but instead the router are sending some queries from 10.0.69.5, to 1.1.1.1:53 over WireGuard_VPN.

As far as I can tell, some queries are sent over WAN (to the DNS server provided by my ISP), and some over WireGuard_VPN. By no means do I have insight into the inner workings of OpenWrt, but it seems that dnsmasq are just treating these DNS servers as equal, so I get this really unwanted and unexpected behavior.

I have solved the symptoms of this issue, partially by using Pi-hole on LAN, and specifying some public IPv4 addresses as upstream DNS, so OpenWrt is not handling any DNS queries anymore. The details are not that relevant.

I would love to hear your thoughts on this. It may or may not be a bug, but it was certainly very unexpected for me. Is there perhaps something that can be done to avoid users accidentally ending up in this situation?

TL;DR works as expected.

If you add dns servers under interfaces, they will be added in the pool of available dns when the interface is up. And all the available dns will be used by dnsmasq.
To force the clients to use specific DNS, use dhcp options.
Otherwise you can create multiple dnsmasq instances and assign for each one the proper upstream dns server.

1 Like

Thanks for the explanation and suggestions, I figured it was most likely not a bug. But I must say it is very easy to misunderstand this feature. In LuCI, this field is named "Use custom DNS servers", which led me to believe clients connected to this interface would use the specified DNS server.

Yeah, a lot of people don't realize that. However this is due to misunderstanding how dns works and what to expect from a dns server.

I disagree; this is bizarre settings UI/UX design, not an issue of not understanding the underlying protocols. There ought to be a list field under the DHCP tab for setting the DNS servers advertised in DHCP exchanges, rather than expecting the router admin to manually enter DHCP options in the format "6,<dns server>,..."; the latter, current method is extremely opaque.

Why does the field "Use custom DNS server" / list dns even exist under each interface if it is ultimately adding addresses to a single pool that is used by dnsmasq for DNS relaying? Why isn't such setting under the dnsmasq setings (LuCi > Network > DHCP and DNS) instead?

Whoever designed this needs to rethink/rework it. It's impenetrable as it currently stands.

Maybe it is opaque if you don't read carefully.

There is there too.

If you have a better way feel free to send a PR to the devs. Complaining in the forum won't make any difference.

There is helper text under "DHCP-Options" that gives an example on how to use DHCP option 6. But there is no such helper text under "Use custom DNS servers". Adding a phrase about how this works would avoid a lot of confusion.

Anyone could make PR to fix this, personally I have no idea what file I would even need to edit to add this.

Hello,
It seems like I have the same issue. I have two interfaces.

1- ipv4gre6 Which one is the tunnel interface with 8.8.8.8,8.8.4.4 custom DNS.
2: pppoe-wan is local internet with 85.15.1.15 and 85.15.1.14 custom DNS.

My problem is that when I ping on a specific interface, my DNS queries go to both interfaces (ipv4gre6 and pppoe-wan).
So there will be DNS leaks, and I also can't open some blocked websites in my country due to dns rebind attack.

root@OpenWrt:~# ping -I gre6-gre6 facebook.com

It should go to 8.8.8.8 and 8.8.4.4 via tunnel interface only, not 85.15.14 and 15. In this case, I am getting 10.10.34.36, which means DNS rebind attacks.

root@OpenWrt:~# cat /etc/config/dhcp

config dnsmasq
        option domainneeded '1'
        option localise_queries '1'
        option rebind_protection '0'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option localservice '1'
        option ednspacket_max '1232'
        option logqueries '1'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        option ra_slaac '0'
        option dns_service '0'

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

> root@OpenWrt:~# route -n
> Kernel IP routing table
> Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
> 0.0.0.0         172.18.15.x   0.0.0.0         UG    1      0        0 pppoe-wan
> 0.0.0.0         192.168.154.x   0.0.0.0         UG    2      0        0 gre6-gre6
> 91.107.x.x  172.18.15.x   255.255.255.255 UGH   1      0        0 pppoe-wan
> 172.18.15.x   0.0.0.0         255.255.255.255 UH    0      0        0 pppoe-wan
> 192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 wan
> 192.168.31.0    0.0.0.0         255.255.255.0   U     0      0        0 br-lan
> 192.168.154.0   0.0.0.0         255.255.255.252 U     0      0        0 gre6-gre6
root@OpenWrt:~# cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fddb:79f1:x::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.31.1'
        option netmask '255.255.255.0'
        option delegate '0'

config device
        option name 'wan'
        option macaddr 'a4:a9:30:2a:x:x'

config interface 'modem'
        option proto 'static'
        option device 'wan'
        option ipaddr '192.168.1.150'
        option netmask '255.255.255.0'
        option delegate '0'

config interface 'wan'
        option proto 'pppoe'
        option device 'wan'
        option username 'x'
        option password 'x'
        option ipv6 'auto'
        option peerdns '0'
        option defaultroute '0'
        option dns_metric '2'
        list dns '85.15.1.14'
        list dns '85.15.1.15'

config interface '6to4'
        option proto '6in4'
        option peeraddr '91.107.x.x'
        option ip6addr 'fc00:x::x/64'
        option mtu '1480'
        option defaultroute '0'

config interface 'gre6'
        option proto 'grev6'
        option peer6addr 'fc00:x::x'
        option ip6addr 'fc00:x::x'
        option mtu '1436'
        option defaultroute '0'

config interface 'ipv4gre6'
        option proto 'static'
        option device '@gre6'
        option ipaddr '192.168.154.2'
        option netmask '255.255.255.252'
        option defaultroute '0'
        list dns '8.8.8.8'
        list dns '8.8.4.4'
        option dns_metric '1'

config route
        option interface 'wan'
        option target '0.0.0.0/0'
        option metric '1'
        option gateway '172.18.15.x'
        option table 'main'

config route
        option interface 'ipv4gre6'
        option target '0.0.0.0/0'
        option gateway '192.168.154.1'
        option metric '2'
        option table 'main'

Also, there are not any extra rules in the firewall section.

Please show me how to split DNS over these two interfaces, because I need to split traffic on interfaces with PBR.

With a few static routes you can easily direct the desired interface.

Just to be clear I see a different reason the DNS requests used the tunnel - maybe it helps the course of discussion:

This is actually why DNS traffic to 1.1.1.1 is routed over the tunnel - a route was configured saying that the server is there. This would happen from any interface.

I added static routes, but they did not work. Again, when I ping on a specific interface, DNS queries go to all DNS servers on both interfaces.

default via 172.18.15.x dev pppoe-wan proto static metric 1
default via 192.168.154.1 dev gre6-gre6 proto static metric 2
8.8.4.4 via 192.168.154.1 dev gre6-gre6 proto static metric 2
8.8.8.8 via 192.168.154.1 dev gre6-gre6 proto static metric 2
85.15.1.14 via 172.18.15.x dev pppoe-wan proto static metric 1
85.15.1.15 via 172.18.15.x dev pppoe-wan proto static metric 1
91.107.x.x via 172.18.15.x dev pppoe-wan proto static metric 1
172.18.15.x dev pppoe-wan proto kernel scope link src 151.242.x.x
192.168.1.0/24 dev wan proto kernel scope link src 192.168.1.150
192.168.31.0/24 dev br-lan proto kernel scope link src 192.168.31.1
192.168.154.0/30 dev gre6-gre6 proto kernel scope link src 192.168.154.2
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 query[A] instagram.com from 127.0.0.1
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 forwarded instagram.com to 8.8.8.8
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 forwarded instagram.com to 8.8.4.4
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 forwarded instagram.com to 85.15.1.14
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 forwarded instagram.com to 85.15.1.15
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 2 ::1/36920 query[A] instagram.com from ::1
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 query[AAAA] instagram.com from 127.0.0.1
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 forwarded instagram.com to 8.8.8.8
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 forwarded instagram.com to 8.8.4.4
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 forwarded instagram.com to 85.15.1.14
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 forwarded instagram.com to 85.15.1.15
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 4 ::1/36920 query[AAAA] instagram.com from ::1
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 1 127.0.0.1/36920 reply instagram.com is 10.10.34.36
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 2 ::1/36920 reply query is duplicate
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 3 127.0.0.1/36920 reply instagram.com is NODATA-IPv6
Mon Feb 12 21:45:51 2024 daemon.info dnsmasq[1]: 4 ::1/36920 reply query is duplicate

See what @trendy already posted in this thread: [Solved] DNS query sent on wrong interface - #2 by trendy

I created a new DNS masq interface, but I don't know how to configure it. Here is what I have done. I am getting the same result as dns split issue

config dnsmasq
        option domainneeded '1'
        option localise_queries '1'
        option rebind_protection '0'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option cachesize '1000'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option localservice '1'
        option ednspacket_max '1232'
        option logqueries '1'
        list interface 'wan'
        list notinterface 'gre6'
        list notinterface 'ipv4gre6'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        option ra_slaac '0'
        option dns_service '0'

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

config dnsmasq 'TunnelDNSMasq'
        option rebind_protection '0'
        option localservice '0'
        list interface 'gre6'
        list interface 'ipv4gre6'
        list notinterface 'wan'

If you are using already PBR then your routing table is not the main, but some custom.

ip route get 8.8.8.8
ip -4 ro list table all
ip -4 ru

Or maybe I have not understood properly what is your issue.
Could you explain in simple words what is the expected behaviour in each scenario?

1 Like

PBR is installed, but due to a split DNS problem, I haven't setup it yet.
my scenario:
The router should have direct access to local internet and use local internet by default.
But my clients should use two routes: for local domains and IPs, users should use local internet; outside the country, my clients should use the gre6 tunnel interface.
Some websites, such as Instagram, Facebook, YouTube, etc., are blocked by the government, so in this case, I can't access them via the tunnel interface due to a DNS split issue.

So in this case, if my clients do ping:

ping -I pppoe-wan anywebsite.ir or Iran ip cidr range, DNS servers should go via 85.15.1.14 and 85.15.1.15 only.

Rest traffic should be via tunnel with 8.8.8.8 and 8.8.4.4 dns.


root@OpenWrt:~# ip route get 8.8.8.8
8.8.8.8 via 192.168.154.1 dev gre6-gre6 src 192.168.154.2 uid 0
    cache
root@OpenWrt:~# ip -4 ro list table all
default via 172.18.15.x dev pppoe-wan proto static metric 1
default via 192.168.154.1 dev gre6-gre6 proto static metric 2
8.8.4.4 via 192.168.154.1 dev gre6-gre6 proto static metric 2
8.8.8.8 via 192.168.154.1 dev gre6-gre6 proto static metric 2
85.15.1.14 via 172.18.15.x dev pppoe-wan proto static metric 1
85.15.1.15 via 172.18.15.x dev pppoe-wan proto static metric 1
91.107.x.x via 172.18.15.x dev pppoe-wan proto static metric 1
172.18.15.x dev pppoe-wan proto kernel scope link src 151.242.x.x
192.168.1.0/24 dev wan proto kernel scope link src 192.168.1.150
192.168.31.0/24 dev br-lan proto kernel scope link src 192.168.31.1
192.168.154.0/30 dev gre6-gre6 proto kernel scope link src 192.168.154.2
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1
local 151.242.x.x dev pppoe-wan table local proto kernel scope host src 151.242.x.x
local 192.168.1.150 dev wan table local proto kernel scope host src 192.168.1.150
broadcast 192.168.1.255 dev wan table local proto kernel scope link src 192.168.1.150
local 192.168.31.1 dev br-lan table local proto kernel scope host src 192.168.31.1
broadcast 192.168.31.255 dev br-lan table local proto kernel scope link src 192.168.31.1
local 192.168.154.2 dev gre6-gre6 table local proto kernel scope host src 192.168.154.2
broadcast 192.168.154.3 dev gre6-gre6 table local proto kernel scope link src 192.168.154.2
root@OpenWrt:~# ip -4 ru
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

First remove the TunnelDNSMasq instance. Try to assign the tld to the local resolvers and everything else to GoogleDNS.

uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server="/ir/85.15.1.14"
uci add_list dhcp.@dnsmasq[0].server="/ir/85.15.1.15"
uci add_list dhcp.@dnsmasq[0].server="8.8.8.8"
uci add_list dhcp.@dnsmasq[0].server="8.8.4.4"
uci commit dhcp
service dnsmasq restart

If that doesn't help, I'd suggest to create separate lan interfaces, one for .ir and another for the rest of the world.

1 Like

Yes, it seems it's working, Thank you, but I have a cidr list also; they are the Iranian server behind any TLD except Ir, like .com.
For example, I added an Iranian cidr range like 185.142.159.194/30 with 85.15.1.14 DNS in dnsmasq like this, but it seems it's wrong. in this case what i have to do? I have a full Irancidr range list.

list server: '/185.142.159.194/30/85.15.1.14'

You cannot add a prefix in the server option of dnsmasq.
The server option basically tells dnsmasq to use a particular nameserver to resolve specific domain names.
If you want to route a prefix via a particular interface, then you need to add a static route or use PBR.

1 Like

Hello
I added the Iran cidr file to PBR,but in this case, it's not working yet. for example
The ipnumberia . com domain is behind an Iranian server IP,but when I open the website, it's showing that I am using a tunnel IP instead of a local internet IP.

Your tunnel policy routes everything via the tunnel not sure if that is really is what you want?

Destination routing with wildcard domains e.g. *.ir will only work if you use ipset/nftset

For that you need dnsmasq full, see: https://docs.openwrt.melmac.net/pbr/