Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set RecursionAvailable in static responses #404

Merged
merged 1 commit into from
Aug 11, 2024
Merged

Conversation

folbricht
Copy link
Owner

Sets RecursionAvailable flag in static responses (static-responder, blocklists, etc) when the query requested it. This is to avoid the warning

;; WARNING: recursion requested but not available

Ref #403

@folbricht folbricht merged commit dfa62e2 into master Aug 11, 2024
3 checks passed
@folbricht folbricht deleted the recursion-requested branch August 11, 2024 06:11
@Anuskuss
Copy link

Anuskuss commented Aug 17, 2024

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

@folbricht
Copy link
Owner Author

You might be right. Do you happen to know what other blocking DNS services do in this case? I'll take a look

@folbricht
Copy link
Owner Author

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

@cbuijs
Copy link
Contributor

cbuijs commented Aug 19, 2024

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

@cbuijs
Copy link
Contributor

cbuijs commented Aug 19, 2024

Also... When providing local or generated answers, you might set the AA bit (Authoritative Answer) instead of messing with the RD bit.

@folbricht
Copy link
Owner Author

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.

@cbuijs
Copy link
Contributor

cbuijs commented Aug 19, 2024

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.

@Anuskuss
Copy link

Anuskuss commented Aug 19, 2024

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: NLnetLabs/unbound@392c1f0

@DL6ER
Copy link

DL6ER commented Aug 21, 2024

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.

@Anuskuss
Copy link

Anuskuss commented Aug 21, 2024

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.

@cbuijs
Copy link
Contributor

cbuijs commented Aug 21, 2024

I think there are two behaviours:

  • Block a query responding with a return-code like NXDOMAIN (or REFUSED, or even an empty answer with NOERROR)
  • Block a query responding with a spoofed/generated answer (like 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)

@Anuskuss
Copy link

Adding a SOA record to the ns 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants