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

Stable/core RRSet type #266

Open
WesleyAC opened this issue Feb 6, 2024 · 6 comments
Open

Stable/core RRSet type #266

WesleyAC opened this issue Feb 6, 2024 · 6 comments

Comments

@WesleyAC
Copy link

WesleyAC commented Feb 6, 2024

Currently, the only type for a RRSet is in the sign package, which is unstable. It seems strange to me that this is the case, since RRSets are a fairly core concept.

Would it be possible to provide a RRSet type for more general use? Perhaps the sign::records::RRSet is suitable for general use, in which case it could simply be moved, I haven't tried to evaluate whether that's the case or not.

@partim
Copy link
Member

partim commented Feb 6, 2024

Thank you for creating the issue! I’ve been tip-toeing around this for quite a while. The reason is that I’m not sure whether there is a single best way to model an RRset. Every time I think about it I end up with more doubt and keep changing my mind, so maybe it is best if I write down my thoughts and we can discuss a way forward.

Conceptionally, an RRset is a list of records that have the same owner, record type, and class. The problem arises from domain names ignoring ASCII case and RFC 1034 saying that “when you receive a domain name […] you should preserve its case.” This suggests that the RRset is best be kept as a list of records – you could save a couple bytes by leaving out type and class but that’s probably not worth it. Especially since in our design the type is intermingled with the record data type.

But then there are use cases where preserving case is unnecessary and we should do away with all the duplicate owner names. This can become relevant in memory constrained system which is a use case I do want to cater for.

One way forward might be to keep an optional owner name per record. If it is left at None, the RRset’s owner name is used. Depending on the octets type used, this can boil down to just keeping a single pointer. But that’s still a pointer per record that is never used in some scenarios and it all adds up.

We can, of course, have both, a case-preserving RRset and a compact RRset. If they both implement a well-defined set of traits, then they may be usable interchangeably in generic code without having to a have special trait.

Moreover, if you use the RRset in some sort of zone tree, you might not even want to have the owner be part of the data at all – you’ll have multiple RRsets for a given owner and if you don’t want to preserve case, it’s good enough to just keep it once. But perhaps the zone tree should just have its own types, anyway.

Finally, DNSSEC: An RRset should also have one or more RSIGs associated with it. Is that something we want to just have in the basic types or should we have special types for Signed RRsets?

@peterthomassen
Copy link

dnspython handles this by having an Rdataset class which is a set of record data which all share the same class, type, and TTL. The RRset class then extends Rdataset with an owner name. (The Rdataset class can also be used in other contexts, e.g. when mapping from a tree, as you mentioned.)

In other words, dnspython does not have an owner name per record (and not even a TTL per record!), and it seems to work well. I'd think that if you go this way, you won't run into big problems, as otherwise they would have occurred already.

I'm not sure what dnspython does when there's sibling RRset whose key only differs in owner name capitalization -- perhaps worth looking into.

@vcunat
Copy link

vcunat commented Feb 6, 2024

In other words, dnspython does not have an owner name per record (and not even a TTL per record!), and it seems to work well.

Knot * servers also represent RRsets that way internally. We don't preserve case, and even name compression is allowed to lead to changing case.

@Habbie
Copy link

Habbie commented Feb 6, 2024

RFC 1034 saying that “when you receive a domain name […] you should preserve its case.

It has since become quite clear that 1034 was not set-focused enough. I definitely would not worry about case variations within an RRset, thus you can use a single name in a single case to hold to an RRset.

@vdukhovni
Copy link

It is reasonable to preserve case at the RRset level, but not per-record. Anyone who expects case-variation within an RRset has unreasonable expectations. RRsets should be coherent (same name, type, class and TTL).

  • When signed, it also has an associated covering RRSIG RRset with same name and covered type.
  • Actually, in exotic situations one might even see two "logical" RRSIG RRsets, one from the parent and another from the child:
    • A interior name in a child zone might be subject to wildcard CNAME synthesis, with the child's apex NSEC needed as evidence.
    • If the CNAME points at the zone apex, and the query is for DS, the parent zone (served by the same server) may deny the secure delegation with an NSEC for the same name, but with a different signer (child zone signed, but not delegated signed).

SInce NSEC RRs and associated RRSIGs for the same name and class can appear on both sides of a zone cut, there's some room for debate on whether when seen together these are one RRset or two! I rather expect this exotic example would not be handled gracefully by most resolvers...

@partim
Copy link
Member

partim commented Feb 7, 2024

Thanks, everyone! This paints a pretty clear picture. I like the idea to have two types, an inner one with a sequence of TTL/record data pairs, plus class and overall TTL, and an outer one that adds the owner name to it. Might even have a third one that then also adds the RRSIGs.

(As an aside: We should probably start a document that collects all of these gotchas and tribal knowledge.)

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

6 participants