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

[FR] Support for RESINFO RRType 261 (RFC9606) #1207

Open
mdavids opened this issue Dec 18, 2024 · 15 comments
Open

[FR] Support for RESINFO RRType 261 (RFC9606) #1207

mdavids opened this issue Dec 18, 2024 · 15 comments
Assignees

Comments

@mdavids
Copy link

mdavids commented Dec 18, 2024

Current behavior
It seems that the RFC9606 RESINFO RRType 261 is not yet supported.
(I checked version 1.22.0)

Describe the desired feature
Support RESINFO RRType

Potential use-case
For example to be able to use it in local-data, like:

local-data: 'resolver.arpa RESINFO "qnamemin temp-dnssecval infourl=https://example.nl"'

UPDATE:

Probably this would be better given the discussion below:

local-data: 'resolver.arpa RESINFO "qnamemin" "temp-dnssecval" "infourl=https://example.nl"'

(I have left the original wrong line here also, so the discussion below can be better understood)

gthess added a commit that referenced this issue Dec 20, 2024
  LDNS_RR_TYPE_RESINFO similar to LDNS_RR_TYPE_TXT.
@gthess gthess self-assigned this Dec 20, 2024
@gthess gthess added this to the Future release milestone Dec 20, 2024
@gthess
Copy link
Member

gthess commented Dec 20, 2024

Hi @mdavids,

I added the RESINFO type, so the potential use-case can be used in the configuration.

However I believe this needs a second pass in the future (why I leave the issue open atm), to properly address the RFC.
With that in mind, Unbound needs to intercept the RESINFO type (because it could be any name AFAIK) and, if enabled to reply, give out the information or refuse otherwise. It would be possible to custom configure the contents of the record to accommodate for unknown keys like temp-dnsseceval in your example.

@mdavids
Copy link
Author

mdavids commented Dec 20, 2024

Thank you for doing this. And I appreciate you leave the issue open for a second pass.

I've been thinking about this as well, as the RFC raises some questions with me. It might perhaps be a bit ambiguous.

The RFC says that a client: "MUST set the RD bit to 0 and MUST discard the response if the AA flag in the response is set to 0".

The 'local-data method' seems to provide the proper response under these conditions (I tested it with TXT, for the lack of RESINFO), so that could be sufficient. But maybe you can think of better ways to implement RFC9606-support in Unbound?

To me RFC9606 has some resemblance with RFC4892 ("id.server"), but then again, maybe not. It seems okay to forward any RESINFO queries when there is no local-data or similar 'interception mechanism' defined, given the RD and AA requirements mentioned above. But I'm still a bit puzzled here.

Anyway... You might want to test this in real life with DNS4ALL, where we made an attempt to implement it:

dig +https +norec @resolver.dns4all.eu RESINFO resolver.dns4all.eu

dig +https +norec @resolver.dns4all.eu RESINFO resolver.arpa

With and without RD-bit, to see the difference. What do you think?

Also, please note the DoH-option, which is one of two REQUIRED options mentioned in the _Security Consideration_s section. The other one is 'local DNSSEC validation', which I don't quite understand (we do not prohibit Do53 however, because we don't care).

@gthess
Copy link
Member

gthess commented Dec 20, 2024

The RFC says that a client: "MUST set the RD bit to 0 and MUST discard the response if the AA flag in the response is set to 0".

I believe the part about the AA flag is so that client is sure the reply is coming from the resolver itself.
The part about the RD is for the resolver to not try and process/forward that further if it doesn't know about RESINFO.

So I believe if your resolver knows about RESINFO, it can reply with the AA flag and don't care about the client RD bit because it will never try to resolve it in the first place.

To me RFC9606 has some resemblance with RFC4892 ("id.server"), but then again, maybe not. It seems okay to forward any RESINFO queries when there is no local-data or similar 'interception mechanism' defined, given the RD and AA requirements mentioned above. But I'm still a bit puzzled here.

Actually this is exactly how I was planning to implement this. Intercept the RESINFO type regardless of the qname and return back the information depending how Unbound is configured. If no information is to be returned, refused would be used. But since Unbound would know about RESINFO, it will never process the query further.

The other one is 'local DNSSEC validation', which I don't quite understand (we do not prohibit Do53 however, because we don't care).

I don't think that DNSSEC can help in practice. For sure you can't sign resolver.arpa, and having signed information in a zone-ish thing does not mean that the resolver that happens to serve that record has those capabilities. It would also be an operational nightmare I suppose.
So transport security does help for the client, but the resolver can just answer with RESINFO anywhere.


Btw I am thinking along these lines for configuration (also note to self):

server:
    ...
    resinfo: yes
    resinfo-qnamemin: yes
    resinfo-exterr: yes
    resinfo-exterr-override: "<provide own values for the exterr key>"
    resinfo-infourl: ""
    resinfo-override: "<a whole custom RESINFO record, it will override everything>"
    resinfo-additional: "<additional data to include, like temp-dnsseceval"
    ...

@mdavids
Copy link
Author

mdavids commented Dec 20, 2024

FYI: please note that I did not make up 'temp-dnsseceval' entirely out of the blue:

https://datatracker.ietf.org/doc/draft-bortzmeyer-add-resinfo-dnssecval-dns64/

jedisct1 added a commit to jedisct1/unbound that referenced this issue Dec 26, 2024
* nlnet/master:
  - For NLnetLabs#1207: [FR] Support for RESINFO RRType 261 (RFC9606), add   LDNS_RR_TYPE_RESINFO similar to LDNS_RR_TYPE_TXT.
  Changelog entry for NLnetLabs#1204: - Merge NLnetLabs#1204: ci: set persist-credentials: false for actions/checkout   per zizmor suggestion.
  set persist-credentials: false per zizmor suggestion
  - Fix typo in log_servfail.tdir test.
  Changelog entry for NLnetLabs#1187: - Merge NLnetLabs#1187: Create the SSL_CTX for QUIC before chroot and privilege   drop.
  Create the SSL_CTX for QUIC before chroot and privilege drop (NLnetLabs#1187)
  - Safeguard alias loop while looking in the cache for expired answers.
  - Merge NLnetLabs#1198: Fix log-servfail with serve expired and no useful cache   contents.
  - For NLnetLabs#1175, the default value of serve-expired-ttl is set to 86400   (1 day) as suggested by RFC8767.
  Changelog entry for NLnetLabs#1189, NLnetLabs#1197: - Merge NLnetLabs#1189: Fix the dname_str method to cause conversion errors   when the domain name length is 255. - Merge NLnetLabs#1197: dname_str() fixes.
  - For NLnetLabs#1193, introduce log-servfail.tdir and cleanup the log-servfail   setting from other tests.
  - Fix NLnetLabs#1193: log-servfail fails to log host SERVFAIL responses in   Unbound 1.19.2 on Ubuntu 24.04.1 LTS, by not considering cached   failures when trying to reply with expired data.
  - For NLnetLabs#1189, homogenize the input buffer size for dname_str().
  - For NLnetLabs#1189, add unit tests for dname_str() and debug check the input   buffer size.
  Fix the dname_str method to cause conversion errors when the domain name length is 255
@rwfranks
Copy link

Perhaps it does not belong here, but I have been playing with this in Net::DNS and have an issue with the example above.

The three attributes are concatenated as a single TXT style text string. However, RFC9606 section 6 leads me to suppose that each attribute inhabits a separate text string in the RR (i.e. unquoted, no internal spaces). This distinction is important if the response is to be processed by a perl script.

;; Response received from [194.0.5.3] 100 octets
;; HEADER SECTION
;;	id = 46638
;;	qr = 1	aa = 1	tc = 0	rd = 0	opcode = QUERY
;;	ra = 0	z  = 0	ad = 0	cd = 0	rcode  = NOERROR
;;	do = 0	co = 0
;;	qdcount = 1	ancount = 1
;;	nscount = 0	arcount = 0

;; QUESTION SECTION (1 record)
;; resolver.dns4all.eu.	IN	RESINFO

;; ANSWER SECTION (1 record)
resolver.dns4all.eu.	60	IN	RESINFO	(
	"qnamemin temp-dnssecval infourl=https://dns4all.eu" )

@rwfranks
Copy link

RFC9606 defines the format indirectly by reference to RFC6763 section 6.3:

"Each key/value pair is encoded as its own constituent string within the
DNS TXT record, ..."

I have raised an erratum against RFC9606 to make that an explicit requirement.

@mdavids
Copy link
Author

mdavids commented Jan 1, 2025

Perhaps it does not belong here, but I have been playing with this in Net::DNS and have an issue with the example above.

Please try again.

@rwfranks
Copy link

rwfranks commented Jan 2, 2025

Perfect!

;; ANSWER SECTION (1 record)
resolver.arpa.	0	IN	RESINFO	( qnamemin temp-dnssecval
	infourl=https://dns4all.eu )

Thanks

@bortzmeyer
Copy link

I have raised an erratum against RFC9606 to make that an explicit requirement.

https://www.rfc-editor.org/errata/eid8223

@pemensik
Copy link
Contributor

I am against intercepting any qname and answering for it itself. I just did dns4all query from my localhost resolver and it worked. I would expect this should work for everything but resolver.arpa name. Instead, unbound should allow to be told with own FQDN presented to clients and listen only on those owner names.

If I use unbound as localhost resolver, I could dig RESINFO resolver.dns4all.eu without connecting directly to it. For example our internal RH network does not allow clients to do DNS queries to outside sources, because RPZ filtering for malware is applied to network resolvers. US gov will make mandatory protective DNS feature over encrypted channel, doing exaclty this. Requiring its clients to use it and only it for resolution. You would lose ability to ask RESINFO of other resolvers, but I do not think that is necessary. If it replies with RA bit, you know it does not handle RESINFO correctly. If you ask with RD bit, you signal forwarding that request is correct. You would have to return REFUSED instead, but I do not see a real benefit.

Anyway, I think unbound should synthetize also _dns.resolver.arpa IN SVCB record from listeners it knows about. For possible NAT redirections or dnsdist before server it may require manual override, but except unknown FQDN owner name it already knows everything needed.

If I would configure own-name: "resolver.example.com", it would respond just to resolver.arpaandresolver.example.com`` with RESINFO. All other names without RD bit would get delegations and would miss AA, if they were cached but remote originated.

I would prefix it with resinfo-, but ideally user should configure own name just once and have both RESINFO and SVCB working from that. In addition it may use its primary name, once it knows it, in empty zones mname SOA responses too.

I admit for separate recursive and authoritative public zone server this creates a problem. Because resolver.example.com name would have to be authoritative on normally recursive server. seems like a problem in RESINFO design, because only RESINFO record cannot be delegated to other server from resolver.example.com authoritative server.

@pemensik
Copy link
Contributor

pemensik commented Feb 12, 2025

I mean, even for resolver.dns4all.eu:

;; ANSWER SECTION:
dns4all.eu.		3600	IN	NS	ns2.sidnlabs.nl.
dns4all.eu.		3600	IN	NS	ns5.sidn.nl.
dns4all.eu.		3600	IN	NS	ns1.sidnlabs.nl.
;; ANSWER SECTION:
resolver.dns4all.eu.	3401	IN	A	194.0.5.3

;; ANSWER SECTION:
resolver.dns4all.eu.	3387	IN	AAAA	2001:678:8::3

Indicates authoritative records for resolver are not served by the resolver itself.

Even in this case RESINFO is on authoritative server, where it cannot react to direct resolver configuration changes (for example disabling validation). It seems resolver would have to use dynamic updates to update its records on authoritative server. So maybe resolver should only respond to resolver.arpa qname (by default) and use only other names only if explicitly configured to do so. Which makes it somehow fragile, because it depends on changes on two different places. Otherwise RESINFO would not be accurate.

@gthess
Copy link
Member

gthess commented Feb 14, 2025

I don't understand any of this :)
RESINFO is there to help clients pick their resolver(s). I don't understand what they will do with the information that a resolver somewhere supports X features if they are not talking to it?
If they are talking through a forwarder always (and probably want to configure such forwarder), then the forwarder is the one that should pick the correct resolvers to talk to.

RESINFO traversing DNS does not seem trivial and robust to me. Let alone the reliance on (globally) resolvable names for forwarders.
It is also specifically mentioned in the RFC that "The DNS client MUST set the Recursion Desired (RD) bit of the query to 0.", so I don't see how resolution can occur past the first reachable resolver.

@mdavids
Copy link
Author

mdavids commented Feb 14, 2025

Without wanting to sound rude, I sometimes feel that the thinking process about RFC9606 here in this issue already goes a lot further than the original authors ever did (were they perhaps Bind9 focussed, where an authoritative and a recursor can be combined in one daemon ?). But I hope i'm wrong.

In any case; the (main) reason why we made RESINFO (also) available on the authoritative side, has to do with the Security Considerations section - bullet point 2, which suggests that (in our case) resolver.dns4all.eu SHOULD be DNSSEC signed.

And for us, putting it in the dns4all.eu zone was the easiest way to accomplish that.

@mdavids
Copy link
Author

mdavids commented Feb 14, 2025

am against intercepting any qname and answering for it itself.

So, your against id.server, version.bind, hostname.bind, authors.bind, trustanchor.unbound and the others as well?

Not sure if I got it right; but that is how I read RFC9606 initially - like some sort of 'internal record' (but also see my comment above - which got me confused).

@pemensik
Copy link
Contributor

I interpret is the client must set RD=0 to query his local resolver. If only that is ever desired, there is no need to respond to other qname than resolver.arpa. The RFC does not say what exactly should happen when RD=1 is used with RESINFO and FQDN not belonging to the current resolver.

I think _dns SVCB is there to pick their resolvers. RESINFO is to get more details about the resolver they have chosen IMO.

I think there should be some way to query configured forwarders (global or specific zone), which clients allowed to recurse might be able to query. That does not yet exist. But if the server has record on FQDN name, I expect naturally it should be able to query it by any normal way, like a normal record.

No, because version.bind CH cannot be delegated to other server. That way it behaves the same as resolver.arpa. IN name. I think that is sufficient to query only local resolver in any case.

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

No branches or pull requests

5 participants