Dnsmasq doesn't reply upstream server responses

I have two upstream local dns servers for example.tld which I can resolve directly:

root@OpenWrt:~# dig subdomain.example.tld @172.29.30.31

; <<>> DiG 9.20.15 <<>> subdomain.example.tld @172.29.30.31
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12295
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;subdomain.example.tld.               IN      A

;; ANSWER SECTION:
subdomain.example.tld.        60      IN      A       172.29.30.10
subdomain.example.tld.        60      IN      A       172.29.30.20

;; Query time: 10 msec
;; SERVER: 172.29.30.31#53(172.29.30.31) (UDP)
;; WHEN: Sun Nov 23 11:31:07 UTC 2025
;; MSG SIZE  rcvd: 65

tcpdump
root@OpenWrt:~# tcpdump -A -i any -n 'udp and (host 172.29.30.30 or host 172.29.30.31)'
tcpdump: WARNING: any: That device doesn't support promiscuous mode
(Promiscuous mode not supported on the "any" device)
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

### dig subdomain.example.tld @172.29.30.31 

11:31:07.273129 eth4  Out IP 192.168.110.4.49285 > 172.29.30.31.53: 12295+ [1au] A? subdomain.example.tld. (56)
E..T.{..@..;..n...d....5.@?40.. .........subdomain.example.tld.......).........
..+.}..9-.
11:31:07.282074 eth4  In  IP 172.29.30.31.53 > 192.168.110.4.49285: 12295 2/0/0 A 172.29.30.10, A 172.29.30.20 (65)
E..]..@.=.k...d...n..5...I..0............subdomain.example.tld..............<....d
.........<....d.

but I get no answer if I dig 127.0.0.1

root@OpenWrt:~# dig subdomain.example.tld @127.0.0.1

; <<>> DiG 9.20.15 <<>> subdomain.example.tld @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48256
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;subdomain.example.tld.               IN      A

;; Query time: 10 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Nov 23 11:31:27 UTC 2025
;; MSG SIZE  rcvd: 33

root@OpenWrt:~#

however tcpdump shows it did query the server and got a response :

tcpdump
root@OpenWrt:~# tcpdump -A -i any -n 'udp and (host 172.29.30.30 or host 172.29.30.31)'
tcpdump: WARNING: any: That device doesn't support promiscuous mode
(Promiscuous mode not supported on the "any" device)
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes


### dig subdomain.example.tld @127.0.0.1 

11:31:27.931569 eth4  Out IP 192.168.110.4.58912 > 172.29.30.30.53: 19864+ [1au] A? subdomain.example.tld. (56)
E..T.m@.@.^]..n...d.. .5.@? M.. .........subdomain.example.tld.......).........
.....}I..e
11:31:27.931635 eth4  Out IP 192.168.110.4.58912 > 172.29.30.31.53: 19864+ [1au] A? subdomain.example.tld. (56)
E..Ts.@.@.....n...d.. .5.@?4M.. .........subdomain.example.tld.......).........
.....}I..e
11:31:27.940663 eth4  In  IP 172.29.30.31.53 > 192.168.110.4.58912: 19864 2/0/0 A 172.29.30.20, A 172.29.30.10 (65)
E..].)@.=.f...d...n..5. .I..M............subdomain.example.tld..............<....d..........<....d

11:31:27.941686 eth4  In  IP 172.29.30.30.53 > 192.168.110.4.58912: 19864 2/0/0 A 172.29.30.20, A 172.29.30.10 (65)
E..]P%@.<.....d...n..5. .IZ.M............subdomain.example.tld..............X....d..........X....d


Same goes for nslookup :

root@OpenWrt:~# nslookup subdomain.example.tld 172.29.30.31
Server:         172.29.30.31
Address:        172.29.30.31:53

Non-authoritative answer:
Name:   subdomain.example.tld
Address: 172.29.30.10
Name:   subdomain.example.tld
Address: 172.29.30.20

*** Can't find subdomain.example.tld: No answer
Tcpdump
root@OpenWrt:~# tcpdump -A -i any -n 'udp and (host 172.29.30.30 or host 172.29.30.31)'
tcpdump: WARNING: any: That device doesn't support promiscuous mode
(Promiscuous mode not supported on the "any" device)
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

## nslookup subdomain.example.tld 172.29.30.31

13:32:08.032625 eth4  Out IP 192.168.110.4.32918 > 172.29.30.31.53: 29796+ A? subdomain.example.tld. (33)
E..=..@.@.....n...d....5.)?.td. .........subdomain.example.tld.....
13:32:08.032714 eth4  Out IP 192.168.110.4.32918 > 172.29.30.31.53: 30565+ AAAA? subdomain.example.tld. (33)
E..=..@.@.....n...d....5.)?.we. .........subdomain.example.tld.....
13:32:08.040892 eth4  In  IP 172.29.30.31.53 > 192.168.110.4.32918: 29796 2/0/0 A 172.29.30.10, A 172.29.30.20 (65)
E..].>@.=.No..d...n..5...I.jtd...........subdomain.example.tld..............<....d
.........<....d.
13:32:10.533925 eth4  Out IP 192.168.110.4.32918 > 172.29.30.31.53: 30565+ AAAA? subdomain.example.tld. (33)
E..=..@.@.....n...d....5.)?.we. .........subdomain.example.tld.....


root@OpenWrt:~# nslookup subdomain.example.tld 127.0.0.1
Server:         127.0.0.1
Address:        127.0.0.1:53

Non-authoritative answer:

*** Can't find subdomain.example.tld: No answer

Tcpdump

root@OpenWrt:~# tcpdump -A -i any -n 'udp and (host 172.29.30.30 or host 172.29.30.31)'
tcpdump: WARNING: any: That device doesn't support promiscuous mode
(Promiscuous mode not supported on the "any" device)
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

#######nslookup subdomain.example.tld 127.0.0.1


11:32:47.987048 eth4  Out IP 192.168.110.4.37277 > 172.29.30.30.53: 23226+ A? subdomain.example.tld. (33)
E..=.|@.@.Ie..n...d....5.)?     Z.. .........subdomain.example.tld.....
11:32:47.987137 eth4  Out IP 192.168.110.4.37277 > 172.29.30.31.53: 23226+ A? subdomain.example.tld. (33)
E..={.@.@.....n...d....5.)?.Z.. .........subdomain.example.tld.....
11:32:47.987359 eth4  Out IP 192.168.110.4.55877 > 172.29.30.30.53: 37405+ AAAA? subdomain.example.tld. (33)
E..=.}@.@.Id..n...d..E.5.)?     ... .........subdomain.example.tld.....
11:32:47.987433 eth4  Out IP 192.168.110.4.55877 > 172.29.30.31.53: 37405+ AAAA? subdomain.example.tld. (33)
E..={.@.@.....n...d..E.5.)?.... .........subdomain.example.tld.....
11:32:47.996742 eth4  In  IP 172.29.30.31.53 > 192.168.110.4.37277: 23226 2/0/0 A 172.29.30.10, A 172.29.30.20 (65)
E..]..@.=.H...d...n..5...I..Z............subdomain.example.tld..............<....d
.........<....d.
11:32:47.997406 eth4  In  IP 172.29.30.30.53 > 192.168.110.4.37277: 23226 2/0/0 A 172.29.30.20, A 172.29.30.10 (65)
E..]._@.<..b..d...n..5...I..Z............subdomain.example.tld..............X....d..........X....d

11:32:50.490065 eth4  Out IP 192.168.110.4.55877 > 172.29.30.30.53: 37405+ AAAA? subdomain.example.tld. (33)
E..=.r@.@.Ho..n...d..E.5.)?     ... .........subdomain.example.tld.....
11:32:50.490132 eth4  Out IP 192.168.110.4.55877 > 172.29.30.31.53: 37405+ AAAA? subdomain.example.tld. (33)
E..=|.@.@.....n...d..E.5.)?.... .........subdomain.example.tld.....

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

config dnsmasq
        option domainneeded '1'
        option localise_queries '1'
        option rebind_protection '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option localservice '1'
        option ednspacket_max '1232'
        option localuse '1'
        list rebind_domain 'example.tld'
        list server '/example.tld/172.29.30.30'
        list server '/example.tld/172.29.30.31'
        
config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        
root@OpenWrt:~#

The “rebind protection” option is probably blocking the answers. Enable the verbose logging, and watch the logs.

1 Like

Dnsmasq is a caching nameserver, it's not recursive.

Am I missing something?

Edit:

To be clear, is your TLD globally registered?

(This is important.)

And yes, this needs to be disabled. Dnsmasq in OpenWrt by default will not provide a private IP in an A Record response to a global query (for security reasons). The log should show this occurred.

1 Like

He has an exception in rebind_domains, so it theoretically shouldn’t be a problem. Enabling “Log queries” would certainly shed more light on it.

also, running a rebind test through dig and dnsmasq should mention “EDE: 15 (Blocked)”

2 Likes

it is in the rebind_domain list

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

config dnsmasq
        option rebind_protection '1'
        list rebind_domain 'example.tld'
        list server '/example.tld/172.29.30.30'
        list server '/example.tld/172.29.30.31'

yes but locally administrated,

as Dave also mentioned it is already in rebind allowed list, however I also tried with disabled rebind protection to no avail.

Have you enabled logging yet? Is this domain DNSSEC enabled publicly?

I made the changes below

config dnsmasq

        option localise_queries '1'
        option rebind_protection '0'

        option logqueries '1'
        option logdhcp '1'


and this was the only output :‌

root@OpenWrt:~# logread -f
Tue Nov 24 18:43:42 2025 daemon.warn dnsmasq[9161]: possible DNS-rebind attack detected: subdomain.example.tld

Disable DNS Rebind. OpenWrt is configured by default (for security reasons) not to allow a [public] A Record response containing a private IP address.

1 Like

Try with list rebind_domain '/example.tld/'

Then the logqueries option didn’t take effect. You should have seen a lot more log entries for the query being received and sent upstream. What version of OpenWrt are you running? You don’t seem to be running dnsmasq in a ujail which has been standard for a few versions now.

Can you show the full dhcp config?

uci export dhcp