Add Support for "proxy-dnssec": Display DNSSEC info

dnsmasq offers the 'proxy-dnssec' option to not validate DNSSEC itself but cache and provide the information from the upstream DNS server.

If I set this option in /etc/dnsmasq.d/02-local.conf, dnsmasq forwards the DNSSEC info (ad flag) but the information is not displayed in query log.

I'd like to see this information in the query log (same as if DNSSEC has been turned on).
Would that be possible?

I voted for this feature request, but unfortunately, I don't think it is possible.

I used to enable this feature in pihole, when it was still using dnsmasq, but after numerous discussions on this forum, I decided to disable DNSSEC on dnsmasq (=pihole-FTL) and enabled DNSSEC validation on unbound.

With or without proxy-dnssec, there appears to be no way to distinguish the difference, e.g. the results in the logs are always the same:

Dec  8 19:20:48 dnsmasq[9241]: query[A] sigok.verteiltesysteme.net from 127.0.0.1
Dec  8 19:20:48 dnsmasq[9241]: forwarded sigok.verteiltesysteme.net to 127.10.10.2
Dec  8 19:20:48 dnsmasq[9241]: reply sigok.verteiltesysteme.net is 134.91.78.139
Dec  8 19:20:50 dnsmasq[9241]: query[A] sigfail.verteiltesysteme.net from 127.0.0.1
Dec  8 19:20:50 dnsmasq[9241]: forwarded sigfail.verteiltesysteme.net to 127.10.10.2
Dec  8 19:20:50 dnsmasq[9241]: reply error is SERVFAIL

A valid response with proxy-dnssec enabled simply returns the A record, an invalid response returns SERVFAIL.

When DNSSEC is enabled in pihole-FTL, response would be SECURE, INSECURE, BOGUS

The query log currently cannot handle this configuration, confirmed by the following test:

  • move proxy-dnssec into /etc/dnsmasq.d/01-pihole.conf
  • as soon as you start performing queries and refresh the query log in the admin console, every entry will have an UNKNOWN status, the query log doesn't even show SERVFAIL, even though the dig command showed that result.
dig sigfail.verteiltesysteme.net @127.0.0.1

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> sigfail.verteiltesysteme.net @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 2120
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

Don't forget to undo the test scenario!

There are DNSSEC plugins for chrome and firefox, the proposed configuration might still be beneficial for these browsers, using that plugin, but I didn't test this....

Basically, for me this is not working with pi-hole. It's true for the first query but the second which is answered from cache does not provide the ad flag.

pi@pi-mail:~ $ dig mail.gmx.net

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> mail.gmx.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17754
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1280
;; QUESTION SECTION:
;mail.gmx.net.                  IN      A

;; ANSWER SECTION:
mail.gmx.net.           900     IN      A       212.227.17.190
mail.gmx.net.           900     IN      A       212.227.17.168

;; Query time: 238 msec
;; SERVER: 192.168.40.2#53(192.168.40.2)
;; WHEN: Mon Dec 16 17:16:02 GMT 2019
;; MSG SIZE  rcvd: 73

pi@pi-mail:~ $ dig mail.gmx.net

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> mail.gmx.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62841
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;mail.gmx.net.                  IN      A

;; ANSWER SECTION:
mail.gmx.net.           896     IN      A       212.227.17.168
mail.gmx.net.           896     IN      A       212.227.17.190

;; Query time: 7 msec
;; SERVER: 192.168.40.2#53(192.168.40.2)
;; WHEN: Mon Dec 16 17:16:06 GMT 2019
;; MSG SIZE  rcvd: 73

For me it looks as if the first query id proxied (it is forwarded and the reply passed to the origin requestor), but the ad flag is noch cached ... so it's not in the second response pi-hole answers from its cache.

But it is cached, if I enable dnssec on the pi-hole.

If I enable DNSSEC on dnsmasq/pi-hole, I get the ad flag on each dig, even when it comes from cache.. If I use proxy-dnssec, I don't get the ad flag on cached responses.
If I use, as I do, a postfix mail server, subsequent checks on mail.gmx.net fail and DANE can't be verified. So this behaviour is no good at all.

Hi
The check for a DANE records goes to the domain, not mail server. So it's
https://dane.sys4.de/smtp/gmx.net
and it's valid.
Bypassing the pi-hole or dnsmasq is an idea. But for what then do we need DNSSEC or proxy-dnssec in pi-hole / dnsmasq.

The idea of proxy-dnssec is, that not the dnsmasq / pi-hole itself does the DNSSEC validation but takes this from a trusted upstream server (in our case our unbound) and forwards it to its clients as if it would do the DNSSEC validation itself.
Now, this is not working as long as the ad flag is not provided with replies that comes form cache.

There have been a lot of bug fixes when it comes to DNSSEC in dnsmasq beginning of the year. They are contained in our branch update/dnsmasq if you want to give them a try...

So what I found is a few discussions on http://lists.thekelleys.org.uk.

Last one states that the flag just works the opposite to what one would expect ([Dnsmasq-discuss] Caching the AD flag with proxy-dnssec) but I haven't tested it.
Second one is a discussion from the time when it has been implemented which is a bit confusing ... ([Dnsmasq-discuss] dnsmasq and "AD" flag forwarding).

As dnsmasq has its problems with validating DNSSEC, having a working proxy-dnssec option would be very helpful.With that the DNSSEC validation could be made by my unbound and just proxied by the dnsmasq to the clients. This would eliminate the need for an additional unbound on the mail server for 'just' doing the DNSSEC validation.

The ad-flag is meaningfull. If the feature would work. As he wrote: when I query a domain that is already in the cache dnsmasq does not respond with a proper ad-flag as retrieved from the upstream server. It just replies with the value of the ad flag in the request ... and this is nonsense.

I tried my dnsmasq on the OpenWrt router yesterday and it works the same way as the on in pi-hole. The first query not answered from cache gets the ad flag from the upstream server (my unbound) and passes it through to the client. Any subsequent query that is answered from the cache does not include the ad flag. So the proxy-dnssec is simply not working.

I will add me to the dnsmasq mailing list and see if I can get more information on this and I will have a look on the dnsmasq code (even though it's 20 years ago I worked with C).

Sorry, I'm not getting what your point is.

Caching records and removing them after ttl elapsed from cache is working.

The only thing that ist not working and that is the topic of this thread is: AD flag is not chached when the --proxy-dnssec parameter has been set.

In general an AD flag should not been cached. This is normal behaviour as one can't trust an upstream dns by default. So if one would like to have dnssec, the resolver (here dnsmasq) shall do the validation on its own.
So far, so good.

The --proxy-dnssec is a feature to overrule this as it clearly says: we trust the upstream server, so we take the ad flag from the record we get from the upstream server, cache it and provide it to our clients.

And this is not working as expected and described in the documentation as the AD flag is not cached and therefor the whole feature is not usable at the moment.

Don't know if it's relevant to this discussion.
Frank Dennis just released a new beta of dnscrypt-proxy, change log:

 - Conformance: the `DO` bit is now set in synthetic responses if it was
set in a question, and the `AD` bit is cleared.

Sorry, we do have a missunderstanding here.

I say: everything works ok, except for --proxy-dnssec feature of dnsmasq. dnsmasq works well when validating dnssec (even though there are a few issues), it caches correctly and everything else.

The only thing that ist not working is the caching of the AD flag and delivering it to clients when someone enables --proxy-dnssec. That's all. The --proxy-dnssec is just NOT working as it does NOT cache the AD flag.

I didn't say that. If my server (dnsmasq) is doing the dnssec validation, then I trust it and it can be cached. And that's how it works.
I say: a dns resolver shall remove the ad flag if it gets one from its upstream server as long as it don't trust that server on its dnssec validation. That's wha a server shall do it sown validation.

Only if I explicitly trust the upstream server, than I can relayon the AD flag I get. And that's what --proxy-dnssec is for. And would be great for, if it just would work.

Just to be clear on what I'm talking about and what the topic of the threat is:

From the dnsmasq manual:

--proxy-dnssec
    Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between dnsmasq and the upstream servers, and the trustworthiness of the upstream servers. 

It states: ...from upstream servers to downstream clients and cache it.

The caching is not working. On the first request, not answered from cache, the AD flag is taken from the upstream response and passed to the client. It should also be cached, but it istn't. The second request is answered from the cache and the answer does not contain the AD flag as ist should because the AD flag is not cached.
The --proxy-dnssec is therefor not working and not a replacement to a dnssec validation (which it should be as it is intended for exactly this).

What I want, and that is the original request:

If the dnsmasq in pi-hole is not doing the dnssec validation itself, but a user enables the --proxy-dnssec option, an ad flag (together with the result (NOERROR/SERVFAIL)) from the upstream server shall be displayed in the pi-hole query log in the same way as if the pi-hole is doing dnssec validation itself (because this is what the --proxy-dnssec is intended for).

With tests and some googling it turned out, that the --proxy-dnssec feature is not working as it does not cache the ad flag (when dnsmasq does the dnssec validation itself, the ad flag is cached and delivered to clients no subsequent requests).

So there is two things that needs to be done:
a) the proxy-dnssec needs to be fixed
b) the info from the upstream server needs to be reflected in the query log (if the pi-hole/dnsmasq) is running with --proxy-dnssec set.

There are two things you should do:

  1. Check out the most recent dnsmasq by doing
    echo "update/dnsmasq" | sudo tee /etc/pihole/ftlbranch
    pihole checkout core development
    pihole checkout web development
    
    and see if this already fixes the problems you're seeing.
  2. If that doesn't work out you can contact the mailing list at dnsmasq-discuss@lists.thekelleys.org.uk and tell them that you tried it using the most recent revision.

I will do
I already subscribed to the mailing list.

It's more of a workaround/hack, but you can disable caching on dnsmasq in 01-pihole.conf (which will be overwritten on every update/refresh/repair) by setting cache-size=0. This will mean you will rely on unbound's cache instead, but proxy-dnssec will actually "work".

I've been running this config for the last 24 hrs and it's been fine so far. The ad bit will always be set.

IPv4

 dig sigok.verteiltesysteme.net

; <<>> DiG 9.10.6 <<>> sigok.verteiltesysteme.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46953
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;sigok.verteiltesysteme.net.	IN	A

;; ANSWER SECTION:
sigok.verteiltesysteme.net. 57	IN	A	134.91.78.139

;; Query time: 11 msec
;; SERVER: 192.168.1.4#53(192.168.1.4)
;; WHEN: Sat Dec 21 11:33:45 PST 2019
;; MSG SIZE  rcvd: 71

 dig sigok.verteiltesysteme.net

; <<>> DiG 9.10.6 <<>> sigok.verteiltesysteme.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13709
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;sigok.verteiltesysteme.net.	IN	A

;; ANSWER SECTION:
sigok.verteiltesysteme.net. 49	IN	A	134.91.78.139

;; Query time: 10 msec
;; SERVER: 192.168.1.4#53(192.168.1.4)
;; WHEN: Sat Dec 21 11:33:53 PST 2019
;; MSG SIZE  rcvd: 71

IPv6

 dig -6 cloudflare.com AAAA @fdXX:XXXX:XXXX::4

; <<>> DiG 9.10.6 <<>> -6 cloudflare.com AAAA @fdXX:XXXX:XXXX::4
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8692
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;cloudflare.com.			IN	AAAA

;; ANSWER SECTION:
cloudflare.com.		300	IN	AAAA	2606:4700::6811:af55
cloudflare.com.		300	IN	AAAA	2606:4700::6811:b055

;; Query time: 20 msec
;; SERVER: fdXX:XXXX:XXXX::4#53(fdXX:XXXX:XXX::4)
;; WHEN: Sat Dec 21 11:35:50 PST 2019
;; MSG SIZE  rcvd: 99

 dig -6 cloudflare.com AAAA @fdXX:XXXX:XXXX::4

; <<>> DiG 9.10.6 <<>> -6 cloudflare.com AAAA @fdXX:XXXX:XXXX::4
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31376
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;cloudflare.com.			IN	AAAA

;; ANSWER SECTION:
cloudflare.com.		297	IN	AAAA	2606:4700::6811:af55
cloudflare.com.		297	IN	AAAA	2606:4700::6811:b055

;; Query time: 12 msec
;; SERVER: fd0f:9fd4:9605::4#53(fdXX:XXXX:XXXX::4)
;; WHEN: Sat Dec 21 11:35:53 PST 2019
;; MSG SIZE  rcvd: 99

Of course, this still means that admine-LTE won't show SECURE, BOGUS, or INSECURE. It'll just show forwarded or SERVFAIL.

I've duplicated your setup (dnsmasq cache-size=0 & proxy-dnssec). The dig commands give the expected result (AD flag + A record OR SERVFAIL), however, this test fails on my win10 workstation (tried edge and firefox). Any explanation for this?

For me the test works. My setup:

Internet
->
unbound (DNSSEC + qname minimization)
->
OpenWrt dnsmasq (DHCP, proxy-dnssec, cache-size 0)
->
pihole (ad blocking) tested with DNSSEC enabled, proxy-dnssec or wihout
->
clients