Embedded dnsmasq2.91rc4 causes upstream problems, due to "DNS-0x20 encoding"

example, not limited to...
use the admin page link or browse to docs.pi-hole.net

entries in the pi-hole log (127.10.10.2#5552 = unbound):

Feb 20 10:10:03 dnsmasq[10597]: UDP 616 192.168.2.228/57121 query[AAAA] docs.pi-hole.net from 192.168.2.228
Feb 20 10:10:03 dnsmasq[10597]: UDP 616 192.168.2.228/57121 forwarded docs.pi-hole.net to 127.10.10.2#5552
Feb 20 10:10:03 dnsmasq[10597]: UDP 617 192.168.2.228/63309 query[A] docs.pi-hole.net from 192.168.2.228
Feb 20 10:10:03 dnsmasq[10597]: UDP 617 192.168.2.228/63309 forwarded docs.pi-hole.net to 127.10.10.2#5552
Feb 20 10:12:04 dnsmasq[15716]: UDP 18 192.168.2.228/62868 query[AAAA] docs.pi-hole.net from 192.168.2.228
Feb 20 10:12:05 dnsmasq[15716]: UDP 18 192.168.2.228/62868 forwarded docs.pi-hole.net to 127.10.10.2#5552
Feb 20 10:12:05 dnsmasq[15716]: UDP 19 192.168.2.228/58534 query[A] docs.pi-hole.net from 192.168.2.228
Feb 20 10:12:05 dnsmasq[15716]: UDP 19 192.168.2.228/58534 forwarded docs.pi-hole.net to 127.10.10.2#5552

entries in unbound log, note the different upper/lower case requests:

Feb 20 10:12:05 unbound[15684:3] info: resolving docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:3] info: response for docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:0] info: response for DOcs.PI-holE.NET. AAAA IN
Feb 20 10:12:05 unbound[15684:0] info: response for DOcs.PI-holE.NET. AAAA IN
Feb 20 10:12:05 unbound[15684:0] info: resolving DOcs.PI-holE.NET. AAAA IN
Feb 20 10:12:05 unbound[15684:3] info: response for docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:3] info: resolving docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:0] info: response for DOcs.PI-holE.NET. AAAA IN
Feb 20 10:12:05 unbound[15684:3] info: response for docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:0] info: response for DOcs.PI-holE.NET. AAAA IN
Feb 20 10:12:05 unbound[15684:3] info: response for docS.pi-HoLE.net. A IN
Feb 20 10:12:05 unbound[15684:0] info: response for DOcs.PI-holE.NET. AAAA IN

cause dnsmasq2.91rc4; embedded in pihole-FTL?

edit

from the dnsmasq-2.91rc4 changelog:

	Implement "DNS-0x20 encoding", for extra protection against
	reply-spoof attacks. Since DNS queries are case-insensitive,
	it's possible to randomly flip the case of letters in a query
	and still get the correct answer back.
	This adds an extra dimension for a cache-poisoning attacker
	to guess when sending replies in-the-blind since it's expected
	that the legitimate answer will have the same  pattern of upper
	and lower case as the query, so any replies which don't can be
	ignored as malicious. The amount of extra entropy clearly depends
	on the number of a-z and A-Z characters in the query, and this
	implementation puts a hard limit of 32 bits to make resource
	allocation easy. This about doubles entropy over the standard
	random ID and random port combination. This technique can interact
	badly with rare broken DNS servers which don't preserve the case
	of the query in their reply. The first time a reply is returned
	which matches the query in all respects except case, a warning
	will be logged. If this coincides with DNS not functioning, it
	is necessary to disable bit 0x20 encoding with --no-0x20-encode.

so, adding a dnsmasq setting no-0x20-encode eliminates this behavior, unbound happy again...

2 Likes

Could you show me an incident of when this actually happens? Capital letter randomization is indeed a wanted feature for added security by making DNS cache poisoning attack harder. dnsmasq intentionally shows then all-lowercase even when this is not true. This is because Simon Kelley thinks showing the mixed-case domains may confuse users more than than needed.

What would be interesting to me now is what happens when you seen an issue. What do the unbound logs show? Please also consider doing a packet recording between your Pi-hole and unbound so we can see what is actually going over the wire.

Recording should be as simple as running

sudo pihole-FTL --config files.pcap /tmp/dns.pcap

starting the recording into /tmp/dns.pcap. It can be disabled again by setting

sudo pihole-FTL --config files.pcap ""

The better approach would, quite obviously, be fixing the dnsmasq feature so it works as it should, not causing spurious issues

The reason I don't want to use "DNS-0x20 encoding"

TLDR; the upstream cache (unbound / redis) has an entry for every case variation, this implies dnsmasq needs to request a previously used variation, in order to get a cache match.

  • I enabled "DNS-0x20 encoding" by deleting the setting no-0x20-encode and restarting pihole-FTL.
  • I than browsed to docs.pi-hole.net, the unbound log now shows (notice the case variations):
Feb 21 06:01:24 unbound[915:3] info: resolving docs.pi-hole.net. AAAA IN
Feb 21 06:01:24 unbound[915:2] info: resolving docs.pi-hole.net. A IN
Feb 21 06:01:24 unbound[915:3] info: response for docs.pi-hole.net. AAAA IN
Feb 21 06:01:24 unbound[915:3] info: resolving docs.pi-hole.net. AAAA IN
Feb 21 06:01:24 unbound[915:2] info: response for docs.pi-hole.net. A IN
Feb 21 06:01:24 unbound[915:2] info: resolving docs.pi-hole.net. A IN
Feb 21 06:01:24 unbound[915:3] info: response for docs.pi-hole.net. AAAA IN
Feb 21 06:01:24 unbound[915:2] info: response for docs.pi-hole.net. A IN
Feb 21 06:01:24 unbound[915:3] info: response for docs.pi-hole.net. AAAA IN
Feb 21 06:01:24 unbound[915:2] info: response for docs.pi-hole.net. A IN
Feb 21 06:01:24 unbound[915:3] info: response for docs.pi-hole.net. AAAA IN
Feb 21 06:24:04 unbound[915:2] info: resolving docs.pi-hole.net. A IN
Feb 21 06:24:04 unbound[915:2] info: resolving docs.pi-hole.net. A IN
Feb 21 06:24:04 unbound[915:2] info: response for docs.pi-hole.net. A IN
Feb 21 06:38:09 unbound[915:0] info: resolving dOCs.Pi-hole.NEt. AAAA IN
Feb 21 06:38:09 unbound[915:0] info: resolving dOCs.Pi-hole.NEt. AAAA IN
Feb 21 06:38:09 unbound[915:1] info: resolving docs.PI-HOlE.NET. A IN
Feb 21 06:38:09 unbound[915:1] info: resolving docs.PI-HOlE.NET. A IN
Feb 21 06:38:09 unbound[915:0] info: response for dOCs.Pi-hole.NEt. AAAA IN
Feb 21 06:38:09 unbound[915:1] info: response for docs.PI-HOlE.NET. A IN
Feb 21 06:38:09 unbound[915:0] info: response for dOCs.Pi-hole.NEt. AAAA IN
Feb 21 06:43:11 unbound[915:0] info: resolving DoCs.pI-hOLE.nET. AAAA IN
Feb 21 06:43:11 unbound[915:0] info: resolving DoCs.pI-hOLE.nET. AAAA IN
Feb 21 06:43:11 unbound[915:2] info: resolving docS.pi-hoLE.NEt. A IN
Feb 21 06:43:11 unbound[915:2] info: resolving docS.pi-hoLE.NEt. A IN
Feb 21 06:43:11 unbound[915:0] info: response for DoCs.pI-hOLE.nET. AAAA IN
Feb 21 06:43:11 unbound[915:2] info: response for docS.pi-hoLE.NEt. A IN
Feb 21 06:43:11 unbound[915:0] info: response for DoCs.pI-hOLE.nET. AAAA IN
  • I than checked the redis (unbound cache) content and found there are multiple entries, one for each case variation. The process to look at the redis cache content is dirty, only showing screenshots of the relevant portion.

docS.pi-hoLE.NEt

DoCs.pI-hOLE.nET

docs.PI-HOlE.NET

dOCs.Pi-hole.NEt

docs.pi-hole.net

docs.pi-hole.net

Some unbound users have opted for dnsmasq cache-size=0, relying on the upstream unbound cache. Since it will take some time before there is a match for the DNS-0x20 encoded query (case sensitive in cache), a lot more queries require resolving, using the actual DNS servers, thus resolving becomes slow, the number of cache hits decrease dramatically.

I don't know any method to look at the dnsmasq cache, thus cannot confirm / deny the dnsmasq cache stores the individual queries. Needs to be verified?

I agree that "DNS-0x20 encoding" is (can be) a valuable feature for added security, however, in my opinion, it would be best applied on the instance that actually talks to the outside world (unbound), with the added assumption the cache is storing everything in lower case, thus minimizing the number of cache entries and achieving an acceptable number of cache hits.

If the dnsmasq upstream server is something like 8.8.8.8 (external) using "DNS-0x20 encoding" is a good idea, however the cache behavior still needs looking into.

My 2 cents...

1 Like

SIGHUP when in debug mode but yes, dnsmasq caches this correctly as - internally - everything is processed in lowercase. Only the packet sent to the upstream and its reply have miXEd cAse. Everything else is always lowercase.

Agreed, so this was a misunderstanding. I was thinking your "causes upstream" problems in the title of this particular discussion means you had issues resolving domains. But now I read it is more an issue of your cache on the next level not being aware of the case-insensitivity.

You are right that in this case, setting the option to opt-out is the way to go. Case closed here.

trying...
DNS-0x20 encoding reduces cache hit count

This has also been brought up to the devs at NLnet Labs, hopefully they'll implement this in unbound so that the upstream servers can handle it. Question: how/where did u disable the encoding for dnsmasq on Pihole, I'd like to disable it myself as I have cache disabled for dnsmasq. Thanks.

adding a dnsmasq setting no-0x20-encode eliminates this behavior, see also the dnsmasq-2.91rc4 changelog. Also mentioned in the first entry of this topic (after edit).

I've decided to enable use-caps-for-id in Unbound to see if it alleviates the error.

FYI
unbound/doc/Changelog at master · NLnetLabs/unbound

24 February 2025: Yorgos
	- Fix hash calculation for cachedb to ignore case. Previously, cached
	  records there were only relevant for same case queries (if not
	  already in Unbound's internal cache).

edit
unbound configuration info received here.

now running with:
dnsmasq: no-0x20-encode
unbound: use-caps-for-id: yes

the result: You will NOT see any mixed case entries in the unbound log, however a packet capture reveals mixed case queries.

After compiling unbound from github source, the redis cache no longer contains mixed case entries.
You may need to add caps-exempt entries in case of (DNSSEC?) errors.

/edit

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.