[Dnsmasq-discuss] proxy-dnssec, how does it work (with unbound as upstream)

Petr Menšík pemensik at redhat.com
Mon Apr 17 00:10:18 UTC 2023


I do not understand why should be proxy-dnssec caching unreliable. It 
should be as simple as storing AD bit from the reply in cache entry. I 
expect just extra bit is something we can afford. Network Manager should 
stop passing dnssec-proxy in case it is configured via DBus however. I 
think this is not what people really want and definitely not when remote 
resolvers addresses are provided and not really protected. Far better 
would be ability to configure DNSSEC validation per connection. I hope I 
will find time to prepare a change allowing to do that soon. Would need 
just DBus interface to turn validation on and off. Trust anchor can stay 
present always.

On 4/13/23 23:15, Simon Kelley wrote:
> I'm not clear where the EDE in a reply fits in to this.
I agree, it seems to be all about AD bit in reality.
>
> --proxy-dnssec does only one thing: it stops dnsmasq from zeroing the 
> authenticated data (AD) bit in replies before returning them to 
> clients. This means that clients can rely on the AD bit to tell if the 
> answer is secure, with a couple of caveats.
>
> 1) The path  between dnsmasq and it's upstream servers is trusted. 
> There's nothing to stop an attacker spoofing answers with the AD bit 
> set since there's no cryptographic validation being done by dnsmasq.
>
> 2) Dnsmasq caching must be off. The AD bit is NOT cached, so replies 
> from the dnsmasq cache will always have the AD bit set to zero. Only 
> replies coming direct from upstream queries potentially have the AD 
> bit set. This is why the man page tells you to set the cache size to 
> zero.
This seems somehow easy to fix. Just save AD bit when proxy-dnssec is 
enabled. Or save it always, but after AD bit is reset when not using 
proxy-dnssec.
>
> The reason why caching the AD bit isn't done is that it doesn't work 
> because the AD bit refers to ALL the answers in to answer section: 
> it's set only if they are all validated. If only some of the answers 
> are validated, AD will be zero, and when a validated answer is cached, 
> the validation status will be wrong.
It seems to be just small corner case, which does not matter usually. If 
we do not mark the response with AD bit which still was, it is not a big 
deal. A problem it would be if we marked response which had not it in 
the original answer.
>
> A real world example is www.comcast.com comcast.com is DNSSEC signed, 
> and www.comcast.com is a CNAME to a CDN which is not validated. If you 
> lookup the CNAME www.comcast.com you'll get an AD bit set.
>
>
> ; <<>> DiG 9.16.1-Ubuntu <<>> CNAME www.comcast.com
> ;; global options: +cmd
> ;; Got answer:
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41970
> ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, 
> ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
> ; EDNS: version: 0, flags:; udp: 1232
> ;; QUESTION SECTION:
> ;www.comcast.com.        IN    CNAME
>
> ;; ANSWER SECTION:
> www.comcast.com.    6962    IN    CNAME www.comcast.com.edgekey.net.
>
> ;; Query time: 0 msec
> ;; SERVER: 192.168.8.129#53(192.168.8.129)
> ;; WHEN: Thu Apr 13 22:00:40 IST 2023
> ;; MSG SIZE  rcvd: 85
>
> But if you lookup the A record for www.comcast.com you'll get the same 
> CNAME and A record it points to.
>
> ; <<>> DiG 9.16.1-Ubuntu <<>> www.comcast.com
> ;; global options: +cmd
> ;; Got answer:
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6633
> ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
> ; EDNS: version: 0, flags:; udp: 1232
> ; OPT=15: 00 03 ("..")
> ;; QUESTION SECTION:
> ;www.comcast.com.        IN    A
>
> ;; ANSWER SECTION:
> www.comcast.com.    6901    IN    CNAME www.comcast.com.edgekey.net.
> www.comcast.com.edgekey.net. 11680 IN    CNAME e523.dscb.akamaiedge.net.
> e523.dscb.akamaiedge.net. 0    IN    A    23.40.214.165
>
> ;; Query time: 0 msec
> ;; SERVER: 192.168.8.129#53(192.168.8.129)
> ;; WHEN: Thu Apr 13 22:01:41 IST 2023
> ;; MSG SIZE  rcvd: 145
>
>
> Now either edgekey.net or akamaiedge.net or both are not signed, so 
> the AD bit is zero. Caching the www.comcast.com CNAME from this answer 
> will cache it as unvalidated, so a subsequent query which answers from 
> the dnsmasq cache will give the wrong value for the AD bit. Caching AD 
> bits from upstream is impossible to do correctly, so dnsmasq doesn't try.
I thought dnsmasq relies on CNAME following to upstream recursor. I 
expect it cannot follow cname chains anyway so it does not try and save 
complete answer in cache. Then it can save also the reply with AD bit 
and it should be reasonably secure. If I request AAAA record for the 
same name, would it forward to upstream original query or just CNAME 
target name query? In any case, doing AND operation on AD bits from all 
cache entries used should restore original AD bit for all well behaved 
servers.
>
> There's not much reason not to do DNSSEC validation in dnsmasq in this 
> case. The cost is extra DNS records that dnsmasq needs to do the 
> validation, but by the time dnsmasq gets an answer it needs to 
> validate, those records are necessarily cached in knot or unbound 
> because they've already done validation.
>
> I'd like to know how EDE replies are being used, and what the changes 
> referred to in this statement by Peter are.
>
> "Note that the changes made by the pi-hole developers have been
> implemented in pi-hole-FTL, the dnsmasq code for proxy-dnssec hasn't
> been changed, so using EDE only works with pi-hole, not with the
> official dnsmasq v2.89"
>
>
> Cheers,
>
> Simon.

It seems to be just confusion caused by how dnssec status is presented 
in pi-hole interface. I think most resolvers answers with AD bit even if 
EDNS0 were not present in the initial query. Recent unbound certainly 
does so.

$ dig @localhost +noedns | grep flags
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 0

I know only systemd-resolved uses some EDNS0 options to inform upstream 
of its supported DNSSEC algorithms. I know no other implementation 
sending such list. Otherwise status of DNSSEC validation is unrelated to 
EDE. Except in validation failures, but they would usually cause 
SERVFAIL, which means no caching anyway.

>
>
> On 13/04/2023 11:15, Peter Russel wrote:
>> Hi
>>
>> Simon, you question (summary of what you're trying to achieve)
>>
>> Obviously, I'm running pihole-FTL, which is dnsmasq + pi-hole features.
>>
>> - dnsmasq is configured with unbound as upstream
>> - dnsmasq cache-size= 0
>> - dnsmasq DNSSEC not enabled
>> - unbound (latest master compiled) as recursive resolver with DNSSEC
>> - unbound uses cachedb module (redis)
>> - unbound is configured to use response policy zones (RPZ)
>> - knot-resolver used for entries like 
>> "server=/v.firebog.net/127.10.10.5#5555"
>> - knot resolver has DNSSEC capabilities.
>>
>> A lot of websites are hosted at cloud providers, this implies some
>> regular websites have the same IP as known DOH servers, that are
>> listed in one of my RPZ zones.
>>
>> The RPZ zone looks like (example):
>> dns.opendns.com CNAME .
>> 32.220.220.67.208.rpz-ip CNAME .
>> 32.222.222.67.208.rpz-ip CNAME .
>> 128.35.zz.35.119.2620.rpz-ip CNAME .
>> 128.53.zz.53.119.2620.rpz-ip CNAME .
>>
>> Both the domain and the IP are blocked by unbound RPZ.
>> In order to allow me to visit regular sites, sharing the same IP as
>> the known DOH server, I use knot-resolver (server= entries), this to
>> bypass the RPZ config for known regular sites.
>>
>> Since, in my opinion, it isn't very efficient to have unbound OR
>> knot-resolver validate DNSSEC, then forward the reply to dnsmasq, and
>> let dnsmasq do the DNSSEC validation all over again, I want to use
>> proxy-dnssec, thus evaluating the DNSSEC info, using the data already
>> available in EDE, supplied by unbound or knot-resolver.
>>
>> Dominik, your questions and comments.
>>
>> Thanks for explaining "add-cpe-id=01234", meaning that it informs
>> upstream that it is capable of processing EDNS data, nothing more.
>> This implies dnsmasq cannot be the cause of "not receiving EDE" data?
>> As I understood from you comments on discourse, the same could be
>> achieved with "add-mac=base64"?
>>
>> Since you "somewhat" agree this might be caused by unbound, NOT
>> caching EDE data, it was my intention to wait for the unbound PRs to
>> be merged into master, than restart testing (unless instructed
>> otherwise by one of you).
>>
>> I started posting only, because another pi-hole user is also testing
>> the feature (proxy-dnssec), and noticed the same inconsistencies, be
>> it under different circumstances (docker, using dnsmasq
>> cache-size=10000, no redis, ...)
>>
>> I don't really understand why dig queries (both on the pi-hole
>> terminal and from a remote windows machine always provide the correct
>> status (SECURE), while site visits, using a browser provide
>> inconsistent statuses (SECURE / INSECURE) I assume dig replies are
>> also cached...
>>
>> Again, thank you both for your interest in this, your valuable time 
>> and effort.

-- 
Petr Menšík
Software Engineer, RHEL
Red Hat, https://www.redhat.com/
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB




More information about the Dnsmasq-discuss mailing list