Dnsmasq multiple forwarder instances ignore option dnsmasq_config and select faster answering server

OpenWrt SNAPSHOT, r6806-fd569e5
dnsmasq-full - 2.79-3

Experimenting with my own build of OpenWrt/LEDE on x86 computer. Trying to create this configuration https://openwrt.org/docs/guide-user/base-system/dhcp#multiple_dhcpdns_serverforwarder_instances
Required patch seem to be already included a long time ago in LEDE.

dhcp configuration

config dnsmasq 'main'
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option strictorder '1'
        option sequential_ip '1'

config dhcp 'lan'
        option interface 'lan'
        option leasetime '30m'
        option ra 'disabled'
        option dhcpv6 'disabled'
        list dhcp_option '6,192.168.1.1'
        option start '100'
        option limit '100'
        option dnsmasq_config 'main'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'
        option dnsmasq_config 'main'

config host
        option name 'beam-me-up'
        option dns '1'
        option displayName 'beam-me-up'
        option mac '38:d5:47:94:2e:5e'
        option ip '192.168.1.99'
        option dnsmasq_config 'main'

config dnsmasq 'opennic'
        option nonwildcard '1'
        option strictorder '1'
        option resolvfile '/root/resolv.conf.ns0'

config dnsmasq 'cloudflare'
        option nonwildcard '1'
        option strictorder '1'
        option resolvfile '/root/resolv.conf.ns1'

config dnsmasq 'quad9'
        option nonwildcard '1'
        option strictorder '1'
        option resolvfile '/root/resolv.conf.ns2'
root@tinwoodman:~# cat /root/resolv.conf.ns0
nameserver 217.12.210.54
root@tinwoodman:~# cat /root/resolv.conf.ns1
nameserver 1.1.1.1
root@tinwoodman:~# cat /root/resolv.conf.ns2
nameserver 9.9.9.9
root@tinwoodman:~# cat /tmp/resolv.conf.auto
# Interface wan
nameserver 10.12.1.10
nameserver 10.12.1.15

DNS server ping test

15:54[1]root@beam-me-up:~>ping -c1 217.12.210.54
PING 217.12.210.54 (217.12.210.54) 56(84) bytes of data.
64 bytes from 217.12.210.54: icmp_seq=1 ttl=59 time=10.4 ms

16:05[1]root@beam-me-up:~>ping -c1 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=60 time=1.40 ms

Yeah, 9.9.9.9 answer quite fast too

16:05[1]root@beam-me-up:~>ping -c1 9.9.9.9
PING 9.9.9.9 (9.9.9.9) 56(84) bytes of data.
64 bytes from 9.9.9.9: icmp_seq=1 ttl=60 time=2.02 ms

16:05[1]root@beam-me-up:~>ping -c1 10.12.1.10
PING 10.12.1.10 (10.12.1.10) 56(84) bytes of data.
64 bytes from 10.12.1.10: icmp_seq=1 ttl=128 time=73.5 ms

And I'm always getting Cloudflare server IP in checks

16:06[1]root@beam-me-up:~>ping -c1 whoami.fluffcomputing.com
PING whoami.fluffcomputing.com (172.68.237.53) 56(84) bytes of data.
64 bytes from 172.68.237.53 (172.68.237.53): icmp_seq=1 ttl=60 time=1.34 ms

16:08[1]root@beam-me-up:~>ping -c1 whoami.akamai.net
PING whoami.akamai.net (162.158.248.233) 56(84) bytes of data.
64 bytes from 162.158.248.233 (162.158.248.233): icmp_seq=1 ttl=60 time=1.37 ms

Or https://dnsleaktest.com. Doesn't matter.

Also there is no traffic to other dns servers at all. Checked with:
tcpdump -ni eth0 udp port 53 and host not 1.1.1.1

I did the same experiments on 17.01.4 and it worked as intended.
Repeated experiments on 17.01.4 and looks like it doesn't work there too.

So I'm curious is it bug or feature?

I see a few things:

You don't have to tell the DHCP to give out it's own address. This config is used to give out other servers.

Regarding your title, I've witnessed that dnsmasq always uses the answer from the fastest resolver - on both OpenWRT and Debian-based OSes. It then stops listening for the other answers, and gives out an ICMP Destination Port Unreachable to the other resolvers.

This command seems incorrect...and I'm not certain what traffic you wish to see. If you're looking for dnsmasq sending requests, you would listen to outbound packets on WAN, udp and dest port 53. If you want to see what your clients are querying, you listen to LAN.

Lastly, all Global DNS servers should provide the same answers. You should want your dnsmasq to take the answer of the fastest-responding forwarder. This is normal behavior.

In my case dhcp_option change nothing. If it absent default would be router or dhcp server IP (same in my case).

All look good for me. I'm checking dnsmasq sending requests to whatever server except 1.1.1.1. No need to narrow filter more in my case (no requests to dnsmasq from outside net). eth0 is my WAN interface.

This is not always the case: IANA root servers can't provide information about OpenNIC domains, you not always want your traffic analysed by specific DNS servers and use VPN. That's why strict order exist in dnsmasq configuration.
In this topic I showed exact discrepancy with documentation but in more complex configuration my experiments include VPN tunnels and custom routes to specific DNS servers. Wide use of VPR VPN Policy-Based Routing + Web UI -- Discussion

Well, you wouldn't see the requests on the WAN if you used VPN to send the requests, you'd see it on the tunnel.

OK, well then that's not to RFC, and I understand. As some of OpenNIC domains are not in the real top-level roots.

With your config i would assume that all DNS queries go to the DNS servers that configured on your wan interface.
Because you only use dnsmasq_config 'main' everywhere.
And the main instance uses the DNS servers from resolved.conf.auto
(10.12.1.10, 10.12.1.15).

What are you trying to do?
Should all queries from all hosts go to all DNS servers you specified separately?
If yes, I would add all those DNS servers to the 'main' instance. (list server option)
Remove all DNS servers from all interfaces (in your case wan only).
Remove all those dnsmasq instances and dnsmasq_config references since there are not needed anymore.

If no you should exactly use of those separate instances.

But I'm not quite sure if that is the intended purpose. I think this used if you want different instanes of dnsmasq with different options on different interfaces. But I have to check that x)

If you don't want to use opennic servers for generic name resolution you can do the following:
For each opennic TLD (.geek, .glue, .free, .pirate and so on, add to your dnsmasq config:
list server '/.geek/opennicdnsserverip'

Yes, all queries go to 10.12.1.10, 10.12.1.15 is what I was expecting to happen but problem is that it's not true. It appeared that those servers answer even slower than 1.1.1.1 or 9.9.9.9. beam-me-up should always get answers from 10.12.1.10, 10.12.1.15 but in fact it almost always 1.1.1.1 (9.9.9.9 sometimes).

I'm trying to configure different hosts in LAN use different DNS servers.

Now I use this approach https://unix.stackexchange.com/questions/144482/iptables-to-redirect-dns-lookup-ip-and-port. Sure dnsmasq working as described in doc is preferable.
This firewall config work as I expect it to work:

config ipset
        option name 'dns0group'
        option enabled '1'
        option storage 'hash'
        option match 'src_ip'

config redirect
        option target 'DNAT'
        option src 'lan'
        option ipset 'dns0group'
        option src_dport '53'
        option proto 'udp'
        option dest_ip '217.12.210.54'
        option dest_port '53'
        option name 'group0dnsredirect'

Then add IP into ipset ipset add dns0group 192.168.1.99

The patch was merged, but the option name dnsmasq_config was changed to instance. (I've also updated that wiki page.)

1 Like