Closed folbricht closed 3 months ago
Actually now that I've read up on what recursion actually is could you revert this please?
When a DNS server receives a non-recursive request or a request from a client that it is not willing to perform recursion for, it typically responds immediately with whatever local data it has available at the time without doing any additional processing.
The warning sucks of course but I think the ra
bit is necessary for differentiating between an actual NXDOMAIN
and a block (especially for EDE-unaware clients). Your call though; if you think the warning is ugly leave it as it is :)
You might be right. Do you happen to know what other blocking DNS services do in this case? I'll take a look
Both, cloudflare and opendns seem to be setting the RA (Recursion Available) bit in responses.
$ dig phishing.testcategory.com @1.1.1.3
; <<>> DiG 9.18.28 <<>> phishing.testcategory.com @1.1.1.3
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49904
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; EDE: 16 (Censored)
;; QUESTION SECTION:
;phishing.testcategory.com. IN A
;; ANSWER SECTION:
phishing.testcategory.com. 60 IN A 0.0.0.0
;; Query time: 13 msec
;; SERVER: 1.1.1.3#53(1.1.1.3) (UDP)
;; WHEN: Mon Aug 19 08:23:11 CEST 2024
;; MSG SIZE rcvd: 76
$ dig @208.67.222.222 www.internetbadguys.com
; <<>> DiG 9.18.28 <<>> @208.67.222.222 www.internetbadguys.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39484
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1410
;; QUESTION SECTION:
;www.internetbadguys.com. IN A
;; ANSWER SECTION:
www.internetbadguys.com. 0 IN A 146.112.61.108
;; Query time: 14 msec
;; SERVER: 208.67.222.222#53(208.67.222.222) (UDP)
;; WHEN: Mon Aug 19 08:31:00 CEST 2024
;; MSG SIZE rcvd: 68
RA bit in an answer is set if the client request contains the RD bit (Recursion Desired). When RD is not set, only local answers should be provided (if any), and RA should not be set.
RD is almost always set by any stub/client, providing RA always doesn't hurt is my experience.
Not providing RA might have a positive effect to stop generating unwanted consequent requests when a NXDOMAIN (or local answers are provided), is received by a client/stub for example. Optimizing traffic potentially (depends on the client/stub).
Also... When providing local or generated answers, you might set the AA bit (Authoritative Answer) instead of messing with the RD bit.
It's not changing the RD bit. The change was to set RA in the if RD is set in blocked or static responses. Should AA be set as well in those responses? Cloud services don't appear to include that based on the example responses above.
No. Only set the RA bit (answer) when the RD bit is set (request). As you provide Recursion as a DNS forwarder.
When RD is not set, only provide local/generated answers and answer with NXDOMAIN when you cannot or have no answer.
The AA bit might be a better way as an indicator in my opinion.
Do you happen to know what other blocking DNS services do in this case?
Pi-hole seems to expect NXDOMAIN
+ no ra
(or 0.0.0.0
via static-responder
). And apparently that's based on the behaviour of Cisco Umbrella (although I couldn't confirm that myself).
Edit: Also this: https://github.com/NLnetLabs/unbound/commit/392c1f0f5495cb0cc1170e126945caa7e988f47d
apparently that's based on the behaviour of Cisco Umbrella (although I couldn't confirm that myself).
My memory tricked me. I found e-mail (as in: non-public) conversation with Quad9 employees back from 2018 where they described that a blocked query can be detected by the criterion NXDOMAIN = 1, AD = 1, RA = 0
. Later (2019), they revised this and asked us to ignore AD
, making the condition NXDOMAIN, RA = 0
.
Looking at their FAQ page, it's unclear:
What will I see if a domain is blocked by Quad9?
Users receive an “NXDOMAIN” response if a site is blocked; the end user system acts as if the domain does not exist. This behavior is subject to change in the future to point individual requests to a Quad9 operated information page, informing the user of the threat mitigation and additional information.
As they are not telling us which blocking lists they are using, finding a domain where we know it is blocked may be tricky. However, if someone is willing to invest the time, this page may be useful.
What I've found - on their Pi-hole instructions - is:
Domains which are blocked by Quad9 will record
Blocked (external, NXRA)
in the Status column of the Query Log
which exactly corresponds to the conditions I described above (NXDOMAIN, RA = 0
from upstream). However, we obviously don't know if this part of their documentation might be dating back to 2019, too, and is not accurate any longer.
where they described that a blocked query can be detected by the criterion
NXDOMAIN = 1, AD = 1, RA = 0
That seems to be the case:
$ dig @9.9.9.9 www.internetbadguys.com | grep -m2 'status\|flags'
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 26268
;; flags: qr rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
Both, cloudflare and opendns seem to be setting the RA (Recursion Available) bit in responses.
Also just realized that both of your examples return IP addresses so the ra
bit is expected. AdGuard DNS seems to be another such case.
I think there are two behaviours:
NXDOMAIN
(or REFUSED
, or even an empty answer with NOERROR
)0.0.0.0
)In both cases when the answer is locally generated (by RouteDNS), it doesn't really matter that the RA
bit is set or not. it becomes informative and doesn't really matter for DNS resolution at that point.
In all other cases it should follow suit of the dns client. When RD
is set, and the answer is retrieved, the RA
bit has to be set. When RD
is not set (by the client in the query), recursion is not requested, and forwarding or resolution down the tree is not necessary (and shouldn't be done), and RA
is just informative at this point as well.
As indicator the AA
bit can be set when generating the answer (return-code-only or spoofed), assuming authority of the answer/domain (we are so for the "blocking" and generating the answer). Adding a SOA
record to the ns
section of the answer, with some (fake) info to elaborate the answer works as well.
I am actually doing this by default when blocking using a static-responder
, adding a SOA
record with some information that points out it is blocked (example):
[groups.null-a]
type = "static-responder"
rcode = 0
answer = [". 666 IN A 0.0.0.0"]
ns = [". 666 IN SOA blocked blocked 666 666 666 666 666"]
(Using a TTL of 666
as an easy indicator as well)
Adding a
SOA
record to thens
section of the answer, with some (fake) info to elaborate the answer works as well.
That's what EDE is for. This discussion was about if the ra
bit should be returned if the answer was static/empty (when blocking). Based on the observations above it should be yes when static (0.0.0.0
) and no when empty (NXDOMAIN
). But maybe it should always return ra
if rd
was sent and Quad9 is just an outlier.
Sets RecursionAvailable flag in static responses (static-responder, blocklists, etc) when the query requested it. This is to avoid the warning
Ref https://github.com/folbricht/routedns/pull/403