RFC 8767
Serving Stale Data to Improve DNS Resiliency
RFC 8767: Serving Stale Data to Improve DNS Resiliency ๐
okay bestie, let's get into it ๐ This is RFC 8767, and the title is literally Serving Stale Data to Improve DNS Resiliency ๐ฆ It was written by D. Lawrence from Oracle, W. Kumari (no affiliation is listed for him in the header), and P. Sood from Google ๐ง It was published in March 2020 ๐ธ and it's a Standards Track document, so it's an official Internet standard, no cap ๐ฅ Its ISSN is 2070-1721. It updates RFCs 1034, 1035, and 2181, and the header doesn't list any RFCs that it obsoletes ๐
Abstract ๐
So the big idea is that recursive resolvers can use stale DNS data, which the doc calls serve-stale, when authoritative nameservers can't be reached to refresh expired data ๐ The whole point is avoiding outages and making DNS tougher against DoS attacks, so attackers have less reason to bother ๐ The doc updates the TTL definitions from RFCs 1034 and 1035 so data can stay in the cache past its TTL expiry ๐ It also updates RFC 2181 so values with the high-order bit set count as positive instead of 0, and it suggests a cap of 7 days โจ
Status of This Memo ๐ฎ
This is an Internet Standards Track document ๐ฅ It's a product of the IETF, and it represents the consensus of the IETF community. It got public review and was approved for publication by the IESG. More info on Internet Standards is in Section 2 of RFC 7841 ๐ For the current status, any errata, and how to send feedback, check https://www.rfc-editor.org/info/rfc8767 ๐
Copyright Notice โ๏ธ
Copyright (c) 2020 IETF Trust and the persons identified as the document authors. All rights reserved. ๐ This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they're in effect on the date of publication. Please read these carefully, because they spell out your rights and restrictions for this document ๐ซถ Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License.
Table of Contents ๐
1. Introduction
2. Terminology
3. Background
4. Standards Action
5. Example Method
6. Implementation Considerations
7. Implementation Caveats
8. Implementation Status
9. EDNS Option
10. Security Considerations
11. Privacy Considerations
12. NAT Considerations
13. IANA Considerations
14. References
14.1. Normative References
14.2. Informative References
Acknowledgements
Authors' Addresses
1. Introduction โจ
okay so traditionally, a DNS Resource Record's (RR's) TTL has been understood as the maximum number of seconds a record can be used before it has to be tossed ๐๏ธ That reading comes from [RFC1035], with clarifications in [RFC2181].
This doc expands the TTL definition so expired data can be used in the exceptional case where a recursive resolver can't refresh the info ๐ It's based on the observation that when authoritative answers are unavailable, outages can happen even when the underlying data those servers would return is usually unchanged ๐ญ
We describe a method below for using stale data, and it balances the competing needs of resiliency and freshness โ๏ธ
This doc updates the TTL definitions from [RFC1034] and [RFC1035] so data can be kept in the cache past TTL expiry ๐ธ It also updates [RFC2181] by interpreting values with the high-order bit set as positive rather than 0, and it suggests a cap of 7 days ๐
2. Terminology ๐
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. ๐
If you want a DNS glossary, [RFC8499] has your back ๐
3. Background ๐ง
There are a bunch of reasons an authoritative server can become unreachable, like Denial-of-Service (DoS) attacks, network issues, and so on ๐ If a recursive server can't contact the authoritative servers for a query but still has relevant data that's aged past its TTL, that info can still be useful for making an answer. The vibe is "stale bread is better than no bread" ๐
Here's what [RFC1035] says in Section 3.2.1: the TTL "specifies the time interval that the resource record may be cached before the source of the information should again be consulted." Then in Section 4.1.3, it adds that the TTL "specifies the time interval (in seconds) that the resource record may be cached before it should be discarded." ๐
Honestly, a natural English reading would make it pretty clear that records past their TTL expiration must not be used ๐ BUT [RFC1035] came out before the more rigorous terminology of [RFC2119], which softened how "may" and "should" get interpreted. Plot twist ๐
[RFC2181] set out to give "the precise definition of the Time to Live," but Section 8 of [RFC2181] was mostly about the numeric range of values rather than how data expires. It does close that section by noting, "The TTL specifies a maximum time to live, not a mandatory time to live." That wording doesn't contain BCP 14 key words [RFC2119], but it still gives the natural language vibe that data becomes unusable past TTL expiry ๐
As of this writing, several large-scale operators use stale data for answers in some way ๐ A bunch of recursive resolver packages, including BIND, Knot Resolver, OpenDNS, and Unbound, give you options to use stale data. Apple macOS can also use stale data as part of the Happy Eyeballs algorithms in mDNSResponder โจ The collective operational experience is that stale data can give significant benefit with minimal downside ๐
4. Standards Action ๐ฅ
Here's the big moment ๐ The definition of TTL in Sections 3.2.1 and 4.1.3 of [RFC1035] gets amended to read:
TTL a 32-bit unsigned integer number of seconds that specifies the
duration that the resource record MAY be cached before the
source of the information MUST again be consulted. Zero values
are interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached. Values
SHOULD be capped on the order of days to weeks, with a
recommended cap of 604,800 seconds (7 days). If the data is
unable to be authoritatively refreshed when the TTL expires, the
record MAY be used as though it is unexpired. See Sections 5
and 6 of [RFC8767] for details.
Interpreting values with the high-order bit set as positive, rather than 0, is a change from [RFC2181], and the reasoning behind it is explained in Section 6 ๐ฆ Suggesting a cap of 7 days, instead of the 68 years allowed by the full 31 bits in Section 8 of [RFC2181], matches what major modern DNS resolvers are doing right now ๐
When a recursive resolver returns a response containing stale records, it MUST set the TTL of each expired record in the message to a value greater than 0. The RECOMMENDED value is 30 seconds ๐ซถ See Section 6 for the explanation.
Answers from authoritative servers with a DNS response code of 0 (NoError) or 3 (NXDomain), and with the Authoritative Answer (AA) bit set, MUST be considered to have refreshed the data at the resolver. Answers with any other response code SHOULD be considered a failure to refresh the data, so any previous state stays intact. See Section 6 for a discussion. โจ
Okay that's the core of it, bestie ๐ The rest of the spec builds on these rules, so keep them in your back pocket ๐ง
5. Example Method ๐
okay so there's more than one way a recursive resolver could pull this resiliency move and still totally respect what the TTL is trying to say, which is basically "hey, time to refresh this data" ๐ฐ๏ธโจ This section walks through one example method. It's giving "here's one good way," not "the only way" ๐ซถ
In this example, four timers are the main characters ๐ that decide how stale data gets used:
- A client response timer, which is the max amount of time a recursive resolver should allow between getting a resolution request and sending its response. ๐
- A query resolution timer, which caps how much total time the resolver spends processing the query. โฑ๏ธ
- A failure recheck timer, which limits how often a failed lookup gets tried again. ๐
- A maximum stale timer, which caps how long records get kept past their expiration. ๐งบ
Most recursive resolvers already have the query resolution timer and, kind of, some version of a failure recheck timer ๐ The client response timer and the maximum stale timer are the new faces in this mechanism ๐ฆ
So when a recursive resolver gets a request, it should start the client response timer. This timer exists to avoid client timeouts ๐ It should be configurable, and the recommended value is 1.8 seconds. That's just under a common timeout value of 2 seconds, which still gives the resolver a fair shot at resolving the name ๐
Next, the resolver checks its cache for any unexpired records that satisfy the request, and if it has them, it returns them โจ If it finds no relevant unexpired data and the Recursion Desired flag is not set in the request, it should immediately return the response without checking the cache for expired records. Typically this response would be a referral to authoritative nameservers covering the zone, but the specifics are implementation dependent ๐ง
If iterative lookups are going to happen, then the failure recheck timer gets consulted ๐ Attempts to refresh from non-responsive or otherwise failing authoritative nameservers are recommended to happen no more frequently than every 30 seconds. If this request came in during that window, the cache may be immediately checked for stale data to satisfy the request ๐ธ
Outside the failure recheck timer's period, the resolver should start the query resolution timer and begin the iterative resolution process. This timer bounds the work the resolver does when it contacts external authorities, and it's commonly around 10 to 30 seconds โณ If this timer expires on a lookup that's still being processed, the resolution effort gets abandoned. Bye bye, lookup ๐
If the answer still isn't fully figured out by the time the client response timer has elapsed, the resolver should check its cache to see whether there's expired data that would satisfy the request. If there is, it adds that data to the response message with a TTL greater than 0 (as specified in Section 4). Then the response goes to the client while the resolver keeps trying to refresh the data in the background ๐ซถ๐ฅ
When no authorities can be reached during a resolution attempt, the resolver should attempt to refresh the delegation and restart the iterative lookup process with the remaining time on the query resolution timer. This resumption should be done only once per resolution effort. ๐ซ Only one do-over, bestie.
Outside the resolution process, the maximum stale timer handles cache management, and it's totally independent of the query resolution process ๐งบ This timer is conceptually different from the maximum cache TTL that exists in many resolvers. That one is a clamp on the TTL values received from authoritative servers, and it's recommended to be 7 days in the TTL definition in Section 4. The maximum stale timer should be configurable. It defines how long a record should be kept in the cache after it expires. The suggested value is between 1 and 3 days ๐ ๐
6. Implementation Considerations ๐
okay so this document mainly describes the issues behind serving stale data, and it intentionally does not give a formal algorithm ๐ โโ๏ธ The concept isn't overly complex, and the details are best left to resolver authors to build in their own codebases ๐ป Serve-stale is a local operation, so the variables don't need to match between deployments for interoperability to work. Still, we want to highlight how different implementation choices land, starting with the timers ๐ง
The most obvious one is the maximum stale timer. If it's too large, it could cause excessive cache memory usage ๐ฆ๐ But if it's too small, serve-stale gets less effective, because the record might not be in the cache when it's actually needed. Shorter values, even under a day, can handle the vast majority of outages ๐ Longer values, as much as a week, give monitoring systems time to notice a resolution problem and give humans time to fix it. Operational experience has shown that sometimes the right people are hard to track down and, unfortunately, slow to remedy the situation ๐ญ
Increased memory consumption could be mitigated by prioritizing the removal of stale records over non-expired records when the cache is running out of space โจ Eviction strategies could also consider other factors, like the last time of use or the popularity of a record, so active but stale records can be kept around ๐ฆ A feature to manually flush only stale records could be useful too ๐งน
The client response timer is another variable that deserves some thought ๐ If this value is too short, there's a risk that stale answers get used even when the authoritative server is actually reachable but just slow. That can end up returning undesirable answers ๐ On the flip side, waiting too long will hurt user experience ๐ฅฒ
For the failure recheck timer, it's all about balance. You want responsiveness in detecting when authorities are available again, but you also don't want to burn extra resources on resolution ๐ฏ If this variable is set too large, stale answers may keep getting returned even after the authoritative server is reachable again. Per [RFC2308], Section 7, this should be no more than 5 minutes โฐ If this variable is too small, authoritative servers may get hit with a significant amount of excess traffic ๐จ
Now, the TTL to set on stale records in the response. Historically, TTLs of 0 seconds have been problematic for some implementations, and negative values can't be effectively communicated to existing software ๐ Other very short TTLs could lead to congestive collapse, since TTL-respecting clients would rapidly try to refresh. The recommended value of 30 seconds sidesteps those potential problems with no practical negative consequences ๐ท It also rate-limits further queries from any client that honors the TTL, such as a forwarding resolver ๐ซถ
Next up, the change to treat a TTL with the high-order bit set as positive and then clamp it, instead of [RFC2181] treating it as zero. The reasoning here is basically engineering simplicity versus an inconsequential operational history ๐ง Negative TTLs never had a rational, intentional meaning that wouldn't have been satisfied by just sending 0 instead. And there was realistically no practical purpose for sending TTLs of 2^25 seconds (1 year) or more ๐ There's also no record of TTLs in the wild having the most significant bit set in the DNS Operations, Analysis, and Research Center's (DNS-OARC's) "Day in the Life" samples [DITL] ๐ With no apparent reason for operators to use them on purpose, that leaves either errors or non-standard experiments as the possible explanations for why such TTLs might show up. Neither one gives an obviously compelling reason why the leading bit set should be treated differently from having any of the next eleven bits set and then capped per Section 4 ๐
Another implementation consideration is the use of stale nameserver addresses for lookups ๐บ๏ธ This gets called out explicitly because, in some resolvers, getting the addresses for nameservers is a separate path from a normal cache lookup. If authoritative server addresses can't be refreshed, resolution can still possibly succeed if the authoritative servers themselves are up ๐ For example, imagine an attack on a top-level domain that takes its nameservers offline. Serve-stale resolvers that had expired glue addresses for subdomains within that top-level domain could still resolve names within those subdomains, even ones they hadn't looked up before ๐งโโ๏ธโจ
The directive in Section 4 that only NoError and NXDomain responses should invalidate any previously associated answer comes from a simple fact: no other RCODEs a resolver normally runs into make any assertions about the name in the question or any data tied to it ๐ง This matches existing resolver behavior, where a failed lookup (say, during prefetching) doesn't touch the existing cache state. Some authoritative server operators have said they'd prefer stale answers get used when their servers respond with errors like ServFail instead of giving true authoritative answers ๐ฅน Implementers MAY decide to return stale answers in this situation ๐
Since the goal of serve-stale is to provide resiliency for all the obvious errors when refreshing data, these other RCODEs are treated as though they're equivalent to not getting an authoritative response ๐ NXDomain for a previously existing name might well be an error, but it isn't handled that way, because there's no effective way to tell apart operator intent in legitimate cases from error cases ๐
During discussion in the IETF, someone suggested that if all authorities return responses with an RCODE of Refused, it might be an explicit signal to take the zone down from servers that still have the zone's delegation pointed at them ๐ค But Refused is also overloaded and can mean multiple possible failures, some of which could be transient configuration problems ๐ฌ Operational experience has shown that purposely returning Refused is a poor way to explicitly take down a zone, compared to either updating the delegation or returning NXDomain with a suitable SOA for extended negative caching ๐ Even so, Implementers MAY consider whether to treat all authorities returning Refused as preempting the use of stale data ๐ซถ๐
7. Implementation Caveats ๐
Okay bestie, stale data is only okay to use when refreshing has failed ๐ . That's the original design of the DNS, and it's what operators expect. If a resolver always served stale data right away and only tried refreshing after the client already had its response, it would keep handing out data it could've easily refreshed ๐ญ. Modern resolvers use prefetching and request coalescing to stay efficient ๐ง, so every client request doesn't have to kick off a brand-new lookup when stale data is sitting there. What matters is that a good-faith effort was made recently to refresh the stale data before any client gets it โจ.
It's also super important to keep the resolution attempt going after the stale response has been sent, until the query resolution timeout ๐ฆ. Some pathological resolutions take many seconds to succeed because they're dealing with unavailable servers, bad networks, and other problems. If you stopped as soon as the expired response went out, those answers would never get refreshed ๐.
The rule against using data with a 0-second TTL beyond the current transaction also explicitly covers stale fallback ๐ซ. That data isn't cached at all, so it's not usable as stale data either ๐.
Be aware that Canonical Name (CNAME) and DNAME records [RFC6672] mingled in the expired cache with other records at the same owner name can cause surprising results ๐. This was observed with an early BIND implementation when a hostname changed from an IPv4 Address (A) record to a CNAME. That version of BIND didn't evict other types from the cache when a CNAME came in, which usually isn't a big deal. But after both records expired and the authorities went down, the stale fallback returned the older A record instead of the newer CNAME ๐ฑ.
8. Implementation Status ๐
The algorithm described in Section 5 was originally implemented as a patch to BIND 9.7.0 ๐ฅ. It's been running on Akamai's production network since 2011, and it smoothed over transient failures and longer outages that would otherwise have turned into major incidents ๐. The patch was contributed to the Internet Systems Consortium, and the functionality is now in BIND 9.12 and later through the options stale-answer-enable, stale-answer-ttl, and max-stale-ttl โจ.
Unbound has a similar feature for serving stale answers. It'll respond with stale data immediately if it recently tried and failed to refresh the answer through prefetching ๐ง. Starting from version 1.10.0, Unbound can also be configured to follow the algorithm described in Section 5. Both behaviors can be configured and fine-tuned with the available serve-expired-* options ๐.
Knot Resolver has a demo module here: https://knot-resolver.readthedocs.io/en/stable/modules-serve_stale.html ๐ฆ.
Apple's system resolvers are also known to use stale answers, but the details aren't readily available ๐คทโโ๏ธ.
In the research paper "When the Dike Breaks: Dissecting DNS Defenses During DDoS" [DikeBreaks], the authors detected some use of stale answers by resolvers when authorities came under attack ๐ง. Their results suggest that more widespread adoption of the technique would significantly improve resiliency for the large number of requests that fail or take abnormally long to resolve during an attack. Iconic research, honestly ๐ฅ.
9. EDNS Option ๐งพ
During the IETF discussion of serve-stale, someone suggested that an EDNS option [RFC6891] should be available ๐ญ. One proposal was to use it to opt in to getting data that might be stale. Another was to signal when stale data had been used in a response.
The opt-in use case was rejected, because the technique was meant to be immediately useful for improving DNS resiliency for all clients ๐ โโ๏ธ.
The reporting case was ultimately rejected too. Even the simpler version of the proposed option was still too much bother to implement for too little perceived value ๐.
10. Security Considerations ๐
Okay, this section is serious, so please pay attention ๐จ. The most obvious security issue is the increased likelihood of DNSSEC validation failures when stale data is used, because signatures could be returned outside their validity period ๐ฌ. Stale negative records can also increase the time window where newly published TLSA or DS RRs may not be used because of cached NSEC or NSEC3 records. These scenarios only become an issue if the authoritative servers are unreachable, which is the only time the techniques in this document are used. So serve-stale doesn't introduce a new failure in place of what would otherwise have been a success ๐ซถ.
Bad actors have also been known to use DNS caches to keep records alive even after their authorities have gone away ๐ป. The serve-stale feature potentially makes that attack easier, though it doesn't introduce a new risk. Attackers could also combine this with a DDoS attack on authoritative servers with the explicit goal of having stale information cached for longer. But if attackers have that kind of capacity, they probably could do a lot worse than prolonging the life of old data ๐.
In [CloudStrife], it was demonstrated how stale DNS data can be used to co-opt security. Those are hostnames pointing to addresses that the name's owner no longer uses, and they can be abused to get domain-validated certificates fraudulently issued to an attacker ๐ฑ. This document doesn't create a new vulnerability in this area, but it does potentially enlarge the window in which such an attack could be made. A proposed mitigation is that certificate authorities should fully look up each name starting at the DNS root for every name lookup. Alternatively, certificate authorities should use a resolver that isn't serving stale data ๐ก๏ธ.
11. Privacy Considerations ๐ฆ
This document doesn't add any practical new privacy issues ๐ซง.
12. NAT Considerations ๐ธ
The method described here isn't affected by the use of NAT devices ๐ซ.
13. IANA Considerations ๐
This document has no IANA actions ๐.
14. References ๐
Here are the receipts, every single one ๐งพ.
14.1. Normative References
[RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987,
<https://www.rfc-editor.org/info/rfc1034>.
[RFC1035] Mockapetris, P., "Domain names - implementation and
specification", STD 13, RFC 1035, DOI 10.17487/RFC1035,
November 1987, <https://www.rfc-editor.org/info/rfc1035>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
Specification", RFC 2181, DOI 10.17487/RFC2181, July 1997,
<https://www.rfc-editor.org/info/rfc2181>.
[RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
NCACHE)", RFC 2308, DOI 10.17487/RFC2308, March 1998,
<https://www.rfc-editor.org/info/rfc2308>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
14.2. Informative References
[CloudStrife]
Borgolte, K., Fiebig, T., Hao, S., Kruegel, C., and G.
Vigna, "Cloud Strife: Mitigating the Security Risks of
Domain-Validated Certificates",
DOI 10.1145/3232755.3232859, ACM 2018 Applied Networking
Research Workshop, July 2018, <https://www.ndss-
symposium.org/wp-content/uploads/2018/02/ndss2018_06A-
4_Borgolte_paper.pdf>.
[DikeBreaks]
Moura, G.C.M., Heidemann, J., Mรผller, M., Schmidt, R. de
O., and M. Davids, "When the Dike Breaks: Dissecting DNS
Defenses During DDoS", DOI 10.1145/3278532.3278534,
ACM 2018 Internet Measurement Conference, October 2018,
<https://www.isi.edu/~johnh/PAPERS/Moura18b.pdf>.
[DITL] DNS-OARC, "DITL Traces and Analysis", January 2018,
<https://www.dns-oarc.net/oarc/data/ditl>.
[RFC6672] Rose, S. and W. Wijngaards, "DNAME Redirection in the
DNS", RFC 6672, DOI 10.17487/RFC6672, June 2012,
<https://www.rfc-editor.org/info/rfc6672>.
[RFC6891] Damas, J., Graff, M., and P. Vixie, "Extension Mechanisms
for DNS (EDNS(0))", STD 75, RFC 6891,
DOI 10.17487/RFC6891, April 2013,
<https://www.rfc-editor.org/info/rfc6891>.
[RFC8499] Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS
Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499,
January 2019, <https://www.rfc-editor.org/info/rfc8499>.
Acknowledgements ๐ซถ
The authors wish to thank Brian Carpenter, Vladimir Cunat, Robert Edmonds, Tony Finch, Bob Harold, Tatuya Jinmei, Matti Klock, Jason Moreau, Giovane Moura, Jean Roy, Mukund Sivaraman, Davey Song, Paul Vixie, Ralf Weber, and Paul Wouters for their review and feedback ๐. Paul Hoffman deserves special thanks for submitting a number of Pull Requests ๐.
Thank you also to the following members of the IESG for their final review: Roman Danyliw, Benjamin Kaduk, Suresh Krishnan, Mirja Kรผhlewind, and Adam Roach ๐ท.
Authors' Addresses ๐
David C Lawrence
Oracle
Email: tale@dd.org
Warren "Ace" Kumari
Google
1600 Amphitheatre Parkway
Mountain View, CA 94043
United States of America
Email: warren@kumari.net
Puneet Sood
Google
Email: puneets@google.com
๐ฆ where this page comes from
- ietf: rfc8767 2020-03
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms