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...
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.
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.
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.
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).
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).
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.