[discuss] don't asynchronously re-resolve negative A/AAAA DNS cache entries
Categories
(Core :: Networking: DNS, enhancement, P2)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox154 | --- | fixed |
People
(Reporter: mail, Assigned: kershaw)
References
(Depends on 1 open bug, Blocks 1 open bug)
Details
(Whiteboard: [necko-triaged])
Attachments
(1 file)
Firefox asynchronously re-resolves negative A/AAAA DNS cache entries on every use, which generates a large volume of redundant DoH queries.
Mechanism
On a cache hit, nsHostResolver::FromCache() returns the cached negative answer (UNKNOWN_HOST) immediately, but also calls ConditionallyRefreshRecord(), which kicks off a fresh background NameLookup() for any negative record:
- FromCache: https://github.com/mozilla-firefox/firefox/blob/3853f3f0a8a97c9c3a9497ed6d0af7dc7cf6c51c/netwerk/dns/nsHostResolver.cpp#L672-L695
- ConditionallyRefreshRecord (note the "|| rec->negative" clause): https://github.com/mozilla-firefox/firefox/blob/3853f3f0a8a97c9c3a9497ed6d0af7dc7cf6c51c/netwerk/dns/nsHostResolver.cpp#L1222-L1248
Refresh-on-use is gated by RefreshForNegativeResponse(). AddrHostRecord (A/AAAA) inherits the base implementation returning true, so it refreshes on every use:
- base (true): https://github.com/mozilla-firefox/firefox/blob/3853f3f0a8a97c9c3a9497ed6d0af7dc7cf6c51c/netwerk/dns/nsHostRecord.h#L165
TypeHostRecord (HTTPS RR) overrides it to false, so HTTPS negatives respect their TTL and are NOT re-resolved on use: - override (false): https://github.com/mozilla-firefox/firefox/blob/3853f3f0a8a97c9c3a9497ed6d0af7dc7cf6c51c/netwerk/dns/nsHostRecord.cpp#L523
The refresh is asynchronous: Happy Eyeballs / the connection state machine gets the cached negative immediately, so this does NOT add connection establishment latency. The cost is redundant DoH queries.
Impact
Sample profile, loading cnn.com and nytimes.com with DoH https://share.firefox.dev/4vyr9wz.
- AAAA negatives: 1078 lookups across 209 hosts (avg 5.2/host). Worst case www.nytimes.com re-resolved 326 times in 42 s, gaps 0.0-0.3 s. Hosts whose SOA-derived negative TTL was thousands of seconds (e.g. simage2.pubmatic.com, ~3598 s) were still re-queried seconds apart.
- HTTPS (type) negatives, same trace: 322 lookups across 259 hosts (avg 1.2/host, max 2) - because RefreshForNegativeResponse() is false.
Same code path, same TTL plumbing; the only difference is the refresh-on-use flag. The overwhelming majority of these AAAA negatives are IPv4-only hosts (A succeeds, AAAA is NODATA), so the repeated AAAA queries are pure waste.
Origin
Inherited from bug 709976 (2011), which added the grace-period async refresh for entries near expiration and folded negatives into the same path. The rationale was latency (avoid blocking on getaddrinfo for frequently-used names), when the negative lifetime was a fixed 60 s guess with no authoritative basis. The negative case has not been revisited since.
Related: bug 1936492 / bug 1945051 (network.dns.only_refresh_on_fresh_connection, default true) is a separate lever already reducing reload/retry DNS refreshes, traded off against TRR lookup time.
Why this is contrary to the RFCs
- RFC 1034 s3.6 / RFC 1035 s3.2.1: a TTL is how long an RR may be cached "before the source of the information should again be consulted", i.e. consult again after the TTL expires, not on every use. https://www.rfc-editor.org/rfc/rfc1034#section-3.6 https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1
- RFC 2308 (DNS NCACHE): negative answers carry a TTL via the authority-section SOA, min(SOA MINIMUM, SOA RR TTL), and may be cached and served until it expires; the stated purpose is to reduce repeated queries / server load for data that does not exist. Refresh-on-use defeats this.
https://www.rfc-editor.org/rfc/rfc2308 - RFC 8767 (serve-stale): the only sanctioned "serve + background refresh" applies to data past its TTL (stale), not within it. Firefox's positive
grace-period refresh matches this; refreshing a still-valid negative does not. https://www.rfc-editor.org/rfc/rfc8767
Proposed direction (discuss)
Stop refreshing negative addr entries while they are still within their (now SOA-derived, per bug 2049173) TTL, bringing A/AAAA in line with HTTPS negatives and with positive records. Conservative variant: suppress refresh-on-use only for negatives that carried an authoritative SOA TTL, keeping the eager re-check for the fixed-fallback (no-SOA) case (e.g. native resolution).
Depends on bug 2049173 (honor SOA-derived negative TTL), which provides the authoritative TTL this change relies on.
Comment 1•3 months ago
|
||
I don't think this necessarily needs to depend on bug 2049173.
Re-resolving negative entries on each lookup seems very wasteful, so it makes sense to avoid it.
There are a few things we need to keep working though.
- We still need to re-resolve the negative DNS entries when nsIDNSService::RESOLVE_REFRESH_CACHE/RESOLVE_BYPASS_CACHE is passed (I think this happens on a force refresh)
- We also need to make sure the TRRServiceChannel does do lookup if there's a negative entry. We might need a new flag for this one. Otherwise if we resolve the DNS entry for TRR early at process startup / network change, we end up with at least 60s of TRR not working.
Overall this seems like a good improvement.
| Assignee | ||
Updated•3 months ago
|
| Assignee | ||
Comment 2•3 months ago
|
||
Updated•3 months ago
|
Updated•2 months ago
|
Description
•