Chromium/Chrome does not cache DNS requests more than a minute indeed.
Interestingly enough, from bugs-chromium - Issue 164026 - DNS TTL not honored from Apr 21 2011
The only DNS cache in the system is in chrome and it does not honor
TTL. We need to either fix chrome and/or add an intermediate cache
that does handle TTL correctly.
Answer in the Dec 4 2012 ticket:
The HostCache currently assumes TTL=60s for all positive results. With
asynchronous DNS resolver, we plan to use TTL=max(60s,
server_reported_ttl), i.e., at least 60s. The rationale is to improve
the cache performance. (When a CDN NS provides TTL=10-20s, and it
takes 30s+ to fetch all subresources, we often have to re-query for the same hostname during one page load.)
Ticket closed on Oct 10 2013 as:
Chrome on CrOS uses asynchronous DNS resolver which honors TTL = max(60s, > server_reported_ttl)
I'm closing this as WontFix (obsolete/works as intended).
This has been a known issue for years; their internal DNS resolver ignores the TTL of DNS records, and only caches DNS requests for 1 minute.
Users have been requesting for years, a feature to change that default behavior, and Google never created one.
In the past, you could disable the internal DNS resolver in chrome://flags
, nowadays that functionally is not exposed anymore.
So summing it up, it is a feature, e.g. it does that by design.
(I initially wrote it could never be changed, which is not obviously not true. A really determined person can either recompile Chromium or hack Chrome binaries. ).
So, as an adenda: there is plenty of documented evidence Google engineers do not intend to respect the default TTL in received DNS answers in Chrome/ium.
From Negative Caching of DNS Queries (DNS NCACHE)
As with caching positive responses it is sensible for a resolver to
limit for how long it will cache a negative response...
While it is implied a resolver may/should impose a maximum limit on caching DNS answer, the 1-min limit on Google Chrome may be too low.
P.S. I actually discovered the answer for something that has been bugging me for years while retrieving Chrome stats to answer this question: Chrome: DNS requests with random DNS names: malware?
PPS From the code bellow, it is apparent negative answers are not cached (TTL=0).
From https://chromium.googlesource.com/chromium/src/net/dns/host_resolver_impl.cc
99 // Default TTL for successful resolutions with ProcTask.
100 const unsigned kCacheEntryTTLSeconds = 60;
101
102 // Default TTL for unsuccessful resolutions with ProcTask.
103 const unsigned kNegativeCacheEntryTTLSeconds = 0;
104
105 // Minimum TTL for successful resolutions with DnsTask.
106 const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds;
1518 // Called by ProcTask when it completes.
1519 void OnProcTaskComplete(base::TimeTicks start_time,
1520 int net_error,
1521 const AddressList& addr_list) {
1522 DCHECK(is_proc_running());
1523
1524 if (dns_task_error_ != OK) {
1525 base::TimeDelta duration = base::TimeTicks::Now() - start_time;
1526 if (net_error == OK) {
1527 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.FallbackSuccess", duration);
1528 if ((dns_task_error_ == ERR_NAME_NOT_RESOLVED) &&
1529 ResemblesNetBIOSName(key_.hostname)) {
1530 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_SUSPECT_NETBIOS);
1531 } else {
1532 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS);
1533 }
1534 base::UmaHistogramSparse("Net.DNS.DnsTask.Errors",
1535 std::abs(dns_task_error_));
1536 resolver_->OnDnsTaskResolve(dns_task_error_);
1537 } else {
1538 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.FallbackFail", duration);
1539 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
1540 }
1541 }
1542
1543 if (ContainsIcannNameCollisionIp(addr_list))
1544 net_error = ERR_ICANN_NAME_COLLISION;
1545
1546 base::TimeDelta ttl =
# always 0 seconds
1547 base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds);
1548 if (net_error == OK)
# always 60 seconds
1549 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
1550
1551 // Source unknown because the system resolver could have gotten it from a
1552 // hosts file, its own cache, a DNS lookup or somewhere else.
1553 // Don't store the |ttl| in cache since it's not obtained from the server.
1554 CompleteRequests(
1555 MakeCacheEntry(net_error, addr_list, HostCache::Entry::SOURCE_UNKNOWN),
1556 ttl);
1557 }