RFC 973

Domain system changes and observations

๐Ÿ“… published January 1986, from ietf

Domain System Changes and Observations โœจ

Hey bestie, here's the RFC 973 tea ๐Ÿซถ It's by Paul Mockapetris at ISI, dated January 1986. It's the update note for the Domain Name System, and it updates RFC-882 [1] and RFC-883 [2]. Main character energy for real ๐Ÿ’…


STATUS OF THIS MEMO ๐Ÿ“œ

okay so this memo is the update to the DNS specs RFC-882 [1] and RFC-883 [2] ๐ŸŒธ It also drops some operational tips and talks about experiences and problem areas in the system as it stands. Distribution of this memo is unlimited ๐Ÿ’–

This doc has every change to the Domain System through January, 1986 โœจ The change notices and extra discussion live online in the file [USC-ISIB.ARPA]<DOMAIN>DOMAIN.CHANGES. Go check it out, it's giving archive vibes ๐Ÿ—‚๏ธ

OVERVIEW ๐Ÿฆ‹

This memo is split into four major sections ๐Ÿ‘‘

  • "UPDATES" covers changes to the domain spec that are already in widespread use, so treat them as part of the spec itself ๐Ÿ’…
  • "OPERATION GUIDELINES" has rules-of-thumb for using the domain system and setting up your database ๐Ÿ“ They work in most cases, but there can be rare exceptions.
  • "EXPERIENCES" covers weird situations and common bugs in the current system, super helpful for problem solving and tuning ๐Ÿ”ง
  • "PROBLEM AREAS" talks about shortcomings that might get fixed in future versions ๐Ÿ”ฎ

UPDATES ๐Ÿ”ฅ

this section is the final stuff that you should bake into all your domain system software ๐Ÿ’– no cap, these are the non-negotiables bestie ๐Ÿ’…

TTL timeouts too small โฐ

the TTL field in RRs was a 16 bit field, which was lowkey way too small. Using seconds, it maxed out at around 18 hours ๐Ÿ’€ That's not enough for real life ๐Ÿ™ˆ

So now all time values get expanded to 32 bits, including every TTL and the MINIMUM field of the SOA RR โœจ iconic glow-up

CLASS changes ๐ŸŽ€

Class 2 was originally reserved for CSNET, and it's obsolete now ๐Ÿซ  Class 3 got assigned to CHAOS instead ๐Ÿงš

CNAME usage ๐Ÿฆ‹

the spec lets CNAME RRs sit next to other RRs at the same node, and that creates drama ๐Ÿ˜ญ The other RRs stored with the CNAME at the alias might not match what's stored at the primary name. Not it ๐Ÿ™…โ€โ™€๏ธ

So the rule is: if a node has a CNAME RR, it should have no other RRs. ๐Ÿ’…

* semantics ๐ŸŒˆ

the * wildcard was supposed to stand in for a single label, and then people started allowing multiple * labels, and it got messy ๐Ÿ˜ตโ€๐Ÿ’ซ Servers got harder to build and the search algorithms got super complicated. There were also questions about whether a * rule could point at names that weren't even in the zone it was defined in ๐Ÿค”

okay so, inheritance would be nice in some cases, but it causes real implementation headaches. The big one: whenever a server can't find an RR in a zone, it has to search all parent zones for a matching * result. (You could automate consistency or copy inherited data super carefully instead, but ngl that's its own mess ๐Ÿ˜ฉ) Then you also have to handle conflicts, like what if a subdomain doesn't want to inherit the defaults?

Given all that, the fix is: delegation of authority cancels the * defaults ๐Ÿ™Œ This is actually simple to build. Just check for delegation before you go looking for * RRs.

There's another issue too: * only matches a single label. So if a name server is looking up A.B.C.D.E.F, it has to check *.B.C.D.E.F, then *.*.C.D.E.F, then *.*.*.D.E.F, and so on ๐Ÿ˜ญ It also has to be careful about zone boundaries, and it multiplies the work for every query.

The solution is to allow a single * label in the leftmost part of a name stored in a zone, and let that label match any number of unknown labels or a single known label in the query name โœจ The catch: the * match only counts for parts of the tree that are neither delegated nor explicitly represented.

The search algorithm for a tree-structured database goes like this:

  1. Walk down the tree matching labels from right to left. If you find a delegation, return that. If you find the specified node, go to step 2. If the tree ends, go to step 3.
  2. Look for RRs that answer the query. If you find any, return them as the answer. If you don't, look for answers in a * node that has the same name as the query except for the rightmost label. (For example, if you can't find an answer at F.ISI.ARPA, look for an RR at *.ISI.ARPA.)
  3. The search for the name has failed, so look for a node whose name is * plus however much matched, and look for answers there. (For example, if you're looking for X.Y.ISI.ARPA and the tree ends at ISI.ARPA, look at *.ISI.ARPA. Same thing goes for Y.ISI.ARPA, or any name of the form <anything>.Z.ISI.ARPA, where Z is a label that doesn't exist under ISI.ARPA.)

Note that this means * matches names that aren't in the tree, no matter how much of the tree is missing, and it also matches one level's worth of known tree ๐Ÿง โœจ

AA semantics ๐Ÿ”

when a name server is answering a query for a particular name and runs into a CNAME, it can optionally restart the search at the canonical name ๐Ÿ” If the server does the restart, the answer section of the reply has one (or more) CNAMEs, possibly followed by answers for the primary name. The canonical name is usually in the same zone as the alias, but it doesn't have to be. If the server is authoritative for one of the names but not both, it's honestly unclear whether the AA bit should be set ๐Ÿคทโ€โ™€๏ธ

The fix: the AA bit refers to the original query name ๐Ÿ’–

Master file format ๐Ÿ“

the current spec has a kinda awkward way of writing domain names in master files ๐Ÿ™ƒ

the change is that every domain name in the file is written as either absolute or relative. An absolute name ends with a .. A free standing . is taken to mean the root. A relative name doesn't end with a dot, and it's relative to the current origin ๐ŸŒธ

SERIAL number size ๐Ÿ”ข

if the master file changes super fast, a copy that rarely gets updated might miss the SERIAL wrapping around in the SOA, or count the number of updates wrong ๐Ÿ˜ต So the SERIAL field gets bumped up to 32 bits โœจ

MD and MF replaced by MX ๐Ÿ’Œ

the original spec uses MD and MF RRs for mail agent binding, and that's a problem ๐Ÿ˜ฉ A mailer making a MAILA query (which asks for both types) can't use the cache, because the cache might only have results for an MD or MF query. Having one of those types in the cache doesn't tell you anything about the other one. So mailers would either have to always ask authoritative servers, or work with partial info, and neither is really acceptable ๐Ÿ’€

The change: replace MD and MF with a new RR type called MX, which carries similar info in one RR type ๐ŸŽ€ MX got type code 15 decimal ๐Ÿ”ข The format is a 16 bit preference value followed by a domain name. A node can have multiple MX RRs, and multiple MX RRs with the same preference value are allowed at one node.

The preference values show how much the mail destination prefers each mail agent, with lower values being "better" ๐Ÿฅ‡ A mailer is expected to at least try the mail agent(s) with the lowest preference value. The meaning of specific preference values, the units, and whether they scale linearly are not defined and left open ๐Ÿคทโ€โ™€๏ธ Preference values should only be used to rank things against each other.

For example, the current RRs:

                 MAIL-ORG   MD    HOST1
                            MD    HOST2
                            MF    HOST3

might get replaced by:

                 MAIL-ORG   MX    10 HOST1
                            MX    10 HOST2
                            MX    20 HOST3

The values 10 and 20 only mean one thing: 10<20 ๐Ÿ’… The detailed discussion of MX is the subject of [3] ๐Ÿ“š

Zone transfer ๐Ÿšš

the original spec says zone transfers happen in breadth first order ๐ŸŒณ The goal was to make life easier for the server accepting the transfer. But ngl that doesn't really help anymore, and it's a real pain for implementers using hashing algorithms ๐Ÿ˜ญ The new rule: you can send the records in any order you want, as long as the SOA node of the zone is sent first and last, and no other duplication happens โœจ

IN-ADDR domain renamed ๐ŸŒ

the IN-ADDR domain is now IN-ADDR.ARPA ๐ŸŽ‰ People felt that using a top-level name was wrong for network-specific info, so it got moved ๐Ÿ’œ


Part 1 of 2. Part 2 is coming up next, so stay tuned bestie ๐Ÿฆ‹๐Ÿ’–

OPERATIONAL GUIDELINES ๐Ÿ’…

Okay bestie, this part is all about the rules of thumb ๐Ÿง  They work in most cases, but there are rare exceptions, so don't treat them as gospel ๐Ÿ™ˆ

Zone delegation ๐Ÿ 

When a domain wants to go independent from its parent, the RRs that mark the delegation in the parent and child zones need to be carefully synced so resolvers don't get confused ๐Ÿ˜ตโ€๐Ÿ’ซ

Say we want to make a new zone called ISI.EDU under an existing EDU zone, and the servers for the child zone are X.ISI.EDU and Y.GOV. โœจ

We might add this to the parent zone:

ISI.EDU.      10000 NS  X.ISI.EDU.
              10000 NS  Y.GOV.
X.ISI.EDU.    10000 A   <address of X.ISI.EDU.>
Y.GOV.        10000 A   <address of Y.GOV.>

And this to the child zone:

ISI.EDU.      10000 NS  X.ISI.EDU.
              10000 NS  Y.GOV.
              50000 SOA <SOA information>
X.ISI.EDU.    10000 A   <address of X.ISI.EDU.>
Y.GOV.        10000 A   <address of Y.GOV.>

Now let's look at what's going on here ๐Ÿ‘€

  • Both zones include the A RR for Y.GOV, even though Y.GOV isn't in the EDU or ISI.EDU domains ๐Ÿซข That RR isn't authoritative. It's there so the address of Y.GOV gets passed along with delegations to it. Strictly speaking it doesn't need to be in either zone, but having it is recommended ๐Ÿ’–
  • The X.ISI.EDU A RR is absolutely essential ๐Ÿšจ
  • A server should only use the glue RRs when it's returning the NS RRs and doesn't already have the address of the server. For example, if the parent server were also authoritative for GOV, the glue RR would typically not get consulted. Still, it's a good idea to have it there so the zone is self-sufficient ๐ŸŒธ
  • The child and parent zones have identical NS RRs for the ISI.EDU domain. That means no matter which server you ask about ISI.EDU, you get the same set of name servers back ๐Ÿซถ
  • The child and parent zones have A RRs for the name servers in those NS RRs. So you know the name servers for ISI.EDU and their addresses too ๐Ÿฆ‹
  • The TTLs for the NS RRs that delegate ISI.EDU and the A RRs for the name server addresses are all the same. That way they all time out at the same moment ๐Ÿ•ฐ๏ธ The value 10000 doesn't mean anything special here, but the matching TTLs really do ๐Ÿ”ฅ

These guidelines don't change any of the flexibility of the system ๐Ÿ’… The name of a name server and the domains it serves are still independent.

It might also happen that the organization ISI wants to take over management of the IN-ADDR domain for an internal network, say 128.99.0.0 ๐ŸŒˆ In that case we'd have additions to the parent zone, say IN-ADDR.ARPA.

We might add this to the parent zone:

99.128.IN-ADDR.ARPA. 2000 NS  Q.ISI.EDU.
                     2000 NS  XX.MIT.EDU.
Q.ISI.EDU.           2000 A   <address of Q.ISI.EDU.>
XX.MIT.EDU.          2000 A   <address of XX.MIT.EDU.>

And this to the child zone:

99.128.IN-ADDR.ARPA. 2000 NS  Q.ISI.EDU.
                     2000 NS  XX.MIT.EDU.
                     5000 SOA <SOA information>
Q.ISI.EDU.           2000 A   <address of Q.ISI.EDU.>
XX.MIT.EDU.          2000 A   <address of XX.MIT.EDU.>

SOA serials ๐Ÿ”ข

The serial field of the SOA RR for a domain is supposed to be a continuously increasing (mod 2**32) value that tells you the version of the database ๐Ÿ“ˆ The whole idea is that you can tell a zone has changed just by comparing serial numbers. So whenever you change a zone, you should increment the serial field of the SOA โœจ

All RRs with the same name, class, and type should have the same TTL โณ

The logic here is that if they're all cached, they'll all time out together ๐Ÿ’œ That means the cache can be reliably used.

Case consistency ๐Ÿ” 

The domain system is supposed to preserve case but be case insensitive ๐Ÿฆ‹ Still, it does nobody any good to put both RRs for the domain name xxx and XXX in the database. It just makes caching ambiguous and makes compression less efficient ๐Ÿ’€ This consistency should also exist in the duplicate RRs that mark delegation in the delegator and the delegatee. For example, if you ask the NIC to delegate UZOO.EDU to you, your database shouldn't say uzoo.edu ๐Ÿ™…โ€โ™€๏ธ

Inappropriate use of aliases ๐Ÿšซ

Canonical names are preferred over aliases in all RRs ๐Ÿ‘‘ One reason is that canonical names sit closer to the information associated with a name. Another is that canonical names are unique and aliases aren't, so comparisons will actually work ๐Ÿซถ

In particular, using aliases in PTR RRs of the IN-ADDR domain, or in NS RRs that mark delegation, is discouraged ๐Ÿ™…โ€โ™€๏ธ


EXPERIENCES ๐Ÿงš

This section covers some unusual situations and common bugs that show up in the present system ๐Ÿ› They should be helpful for problem determination and tuning. Put differently, you should try to make your code defend against these attacks ๐Ÿ›ก๏ธ and you should expect to be the object of complaint if you make these attacks yourself ๐Ÿ˜ญ

UDP addresses ๐Ÿ“ฎ

When you send a query to a host with multiple addresses, you might expect the response to come from the address you sent the query to. Nope ๐Ÿ™ƒ This isn't the case with almost all UNIX implementations.

UDP checksums ๐Ÿงฎ

Lots of versions of UNIX generate incorrect UDP checksums, and most of them ignore the checksum on incoming UDP datagrams ๐Ÿ˜ค The typical symptom is that your UNIX domain code works fine with other UNIXes but won't talk to TOPS-20 or other systems. (JEEVES, the TOPS-20 server used for 3 of the 4 root servers, ignores datagrams with bad UDP checksums ๐Ÿซ )

Making up data ๐Ÿซฃ

Plenty of name servers return RRs for the root servers with 99999999 or similarly huge values in the TTL ๐Ÿ’€ For example, some return RRs suggesting that ISIF is a root server. (It was months ago, but it's no longer ๐Ÿ˜ญ)

One of the main ideas of the domain system is that everybody gets a chunk of the name space to manage however they like ๐ŸŒˆ However, you aren't supposed to lie about other parts of the name space. It's ok to remember things about other parts of the name space for caching or other purposes, but you're supposed to follow the TTL rules โฐ

Now, it may be that you put records like that in your server to ensure a server of last resort. That's fine ๐Ÿ‘ But if you export these in answers to queries, you should be shot ๐Ÿ”ซ (dramatic, I know ๐Ÿ’…) These entries get put in caches and never die ๐ŸงŸ

Suggested domain meta-rule:

If you must lie, lie only to yourself. ๐Ÿคซ

PROBLEM AREAS ๐Ÿšง

This section covers some shortcomings of the present system that may be addressed in future versions ๐Ÿ”ฎ

Compression and types ๐Ÿ—œ๏ธ

The present specification tries to let name servers and resolvers cache RRs for classes they don't "understand," and also lets domain names get compressed so UDP datagrams stay small ๐Ÿ“ฆ These two goals clash in the current scheme, because the only way to expand a compressed name is to know that a name is expected in that position ๐Ÿ˜ต

One technique for fixing this would be to preface binary data (anything but a domain name) with a length octet ๐Ÿงฉ

The high order two bits of the length octet could contain either 01 or 10, which are illegal for domain names. To make up for the extra bytes of data, we could omit the RDATA length field and end each RR with a binary length field of zero ๐ŸŽ€

Caching non-existent names ๐Ÿ‘ป

Right now a resolver has no standard way to cache the result that a name doesn't exist, and those lookups seem to make up a bigger chunk of queries than anyone expected ๐Ÿ“ˆ Some resolvers create "does not exist" RRs with TTLs to protect against repeat queries for a non-existent name ๐Ÿ™ƒ

A standard technique might be to return the SOA RR for the zone in the reply (only authoritative servers can say a name does not exist, fyi ๐Ÿค“). The semantics would be that the requester is free to assume the name doesn't exist for a period equal to the MINIMUM field of the SOA โณ

Cache conflicts ๐Ÿ’ฅ

When a resolver processes a reply, it may well decide to cache all the RRs found in the sections of the reply ๐Ÿง The problem is that the resolver's cache may already hold a subset of those RRs, probably with different TTLs ๐Ÿ˜ฌ

If the RRs come from authoritative data in the answer section, then the cache RRs should be replaced. In other cases the correct strategy isn't totally clear ๐Ÿคทโ€โ™€๏ธ Also, if the authoritative data's TTL has changed, the resolver doesn't have enough information to make the right call in every case ๐Ÿ’”

This issue is tricky and deserves some thought ๐Ÿง โœจ


REFERENCES ๐Ÿ“š

[1] Mockapetris, P., "Domain Names - Concepts and Facilities", RFC-882, USC Information Sciences Institute, November 1983.

[2] Mockapetris, P., "Domain Names - Implementation and Specification", RFC-883, USC Information Sciences Institute, November 1983.

[3] Partridge, C., "Mail Routing and the Domain System", RFC-974, CSNET-CIC, BBN Laboratories, January 1986.

๐Ÿ“ฆ where this page comes from