Computing History · Networking History

DNS Delegation, Glue Records, and the Referral Loop

How authority for a name is handed down a zone tree, why a child in the same zone as its parent forces address records into the parent, and what breaks when glue is wrong.

The domain name system is a tree of administrative cuts, and almost every operational difficulty in it follows from one structural fact: the parent of a zone does not hold the child’s data, it holds only a pointer to who does. A resolver that wants the address of a name must walk from a starting point down through those pointers, and the walk is only possible because each pointer includes the name of the server to ask next. That name must then be resolved, which normally means asking a different server, which may itself require a walk.

Most of the time the recursion terminates cleanly and quickly. The interesting engineering is in the cases where it does not, and those cases are almost all caused by a name server whose own address lives inside the zone it is authoritative for.

Zones, cuts, and what a referral contains

A zone is a contiguous subtree of the name space for which one set of servers is authoritative. The root zone is the whole tree minus every subtree that has been cut away. com is a cut below the root, example.com is a cut below com, and www.example.com is usually not a cut at all: it lives inside the example.com zone and is answered by that zone’s servers.

The cut is expressed by a delegation, which is a pair of records in the parent zone: an NS record set at the child’s name naming the child’s authoritative servers, and usually a DS record for the signed case. When a resolver asks the parent for something below the cut, the parent does not answer. It returns a referral: a response with no answer records, the NS record set in the authority section, and the response code NOERROR. The answer is authoritative for the existence of the delegation, but not for anything below it, so the authoritative flag in the header is clear.

The parent also sends the child’s NS names in the authority section, and, when it has them, their addresses in the additional section. Those additional address records are glue, and their presence or absence is the difference between a walk that converges and one that dead-ends.

Why glue is sometimes mandatory

Consider a delegation of example.com to a server named ns1.example.com. The child zone contains the A record for ns1.example.com, because the name is inside the child. A resolver that receives the referral now needs the address of ns1.example.com in order to ask it anything. If it tries to resolve that name through the ordinary process, it asks the root, which refers it to com, which refers it back to ns1.example.com, the very server whose address is unknown. The referral loop is closed and nothing resolves.

The escape is for the parent to include the address in the additional section of the referral. That address is glue: it is not authoritative data of the parent zone, it is a copy of data that belongs to the child, included only to break the circular dependency. The parent is asserting “this is the address I believe the child’s server has”, and the resolver must treat it as a hint rather than as an answer.

;; Referral for www.example.com, as a com server would return it
;; (sections abbreviated, addresses illustrative)

QUESTION
  www.example.com.  IN  A

AUTHORITY
  example.com.      172800  IN  NS  ns1.example.com.
  example.com.      172800  IN  NS  ns2.example.net.

ADDITIONAL
  ns1.example.com.  172800  IN  A   192.0.2.53
  ns2.example.net.  172800  IN  A   198.51.100.53

Only one of those two glue records is required. ns2.example.net is outside the delegated zone, so its address can be resolved by the ordinary walk through net, which does not depend on example.com existing. ns1.example.com is in-bailiwick for the delegation and cannot be resolved without the glue.

The requirement generalises: a name server must be reachable through a path that does not require the zone it serves. A delegation to a single in-bailiwick server with no glue, or with glue that is stale, is a lame or unreachable delegation, and every name below the cut becomes unresolvable for resolvers that have to start from the root.

Bailiwick checking and why resolvers are suspicious

Glue is untrusted data by construction, and a resolver that accepts arbitrary additional-section records can be poisoned. The rule resolvers apply is a bailiwick check: an address record in the additional section is usable only if the name it describes lies within the zone that the responding server is authoritative for. A com server may supply glue for a name inside example.com because that name is inside the zone being delegated, which is inside com. It may not supply an address for a name in an unrelated zone, and a resolver that cached such a record on trust would accept an answer from a party with no authority over it.

The check is subtle because bailiwick is about the delegated zone, not about the server’s own name. The com servers are named inside net and com, yet they legitimately supply glue for names inside com’s children. A resolver that required glue names to be inside the responder’s own zone would reject every legitimate referral.

Walking down, and what gets cached

An iterative resolver with no cached knowledge starts from a set of root server addresses, which it must have configured because there is no way to look them up without already knowing them. It sends a query for the full name with recursion not desired, receives a referral to a top-level domain, sends the same query to a server from that referral, receives a referral to the second level, and repeats until a server answers authoritatively.

Each step caches something, and the TTL on the cached record governs how long the knowledge survives. The delegation’s NS records carry a TTL, commonly a day or two for large zones; glue carries the TTL of the address record it copies, which may be shorter. A resolver that caches the NS set but not the glue will need to resolve the server’s name on the next query, and if that name is in-bailiwick it will need a fresh referral from the parent, which is why caching the glue alongside the delegation matters for latency. None of it helps if the address itself is not carried by the routing system, so a delegation is only as durable as the prefix announcement behind it, a dependency examined in Path Vectors, Policy, and Why BGP Does Not Minimize Anything.

Negative answers cache differently. A response stating that a name does not exist carries a SOA record in the authority section, and the lifetime of the cached non-existence is the smaller of that record’s minimum field and the SOA’s own TTL. This is the rule in RFC 2308, and it exists because the original specification left the interpretation of the SOA minimum ambiguous, with implementations disagreeing about whether it bounded the SOA’s own TTL or the negative answer’s lifetime.

Failure modes that show up in practice

The first is a delegation whose glue does not match reality. The parent’s copy of the address is refreshed only when the parent zone is edited, and an operator who moves a server without updating the parent leaves every resolver that has no cached address unable to reach the zone. Resolvers with cached glue continue to work until the TTL expires, so the failure appears gradually and unevenly, which makes it harder to diagnose than an outright outage.

The second is a delegation to a name that has no address at all. Some parents accept an NS record whose target does not resolve, producing a delegation that can never be followed. The referral is well-formed and the parent is behaving correctly; the child simply does not exist as a reachable server.

The third is the CNAME at a zone apex. A zone’s own name must have SOA and NS records, and a CNAME is defined to be the only record at a name it occupies, so a CNAME at the apex conflicts with the delegation itself. Implementations differ in how they handle the conflict, and the resulting behaviour ranges from a refusal to serve the zone to an answer that silently drops the CNAME. The DNAME record was added later to provide redirection of an entire subtree without that conflict.

The fourth is the interaction with transport. A referral can exceed the 512-byte limit of a classic UDP response once a zone has enough name servers, and the truncated flag then forces the resolver to retry over TCP. Modern practice advertises a larger buffer with EDNS, but the buffer size is a claim the resolver makes and the server may ignore, and a middlebox that drops large UDP fragments makes the fallback path load-bearing. The same indirection appears at the application layer: a mail domain names its receivers through DNS and lets the sender retry for days, as described in Store-and-Forward Delivery and the MX Indirection.

The fifth is the difference between an authoritative server and a recursive one. A server that is authoritative for a zone and also offers recursion must separate the two roles by source address or by query flag, because a recursive server answering from its cache for a name it is authoritative for can return stale data with the authoritative bit set. The separation is a configuration requirement rather than a protocol one, and getting it wrong produces answers that look correct until the zone changes.

None of these failures is visible from a single query. Each produces a response that is well-formed and consistent with the protocol, and the error appears only as a name that does not resolve, or resolves to a host that does not answer. That is why the tree is usually tested by walking it from the root rather than by querying the name directly, and why a delegation that has never been exercised from outside the site can survive for years.

References

  1. RFC 1034: Domain Names — Concepts and Facilities — IETF
  2. RFC 1035: Domain Names — Implementation and Specification — IETF
  3. RFC 2308: Negative Caching of DNS Queries (DNS NCACHE) — IETF
  4. RFC 8499: DNS Terminology — IETF