为什么 Chromium 缓存 DNS 的时间不会超过一分钟?

为什么 Chromium 缓存 DNS 的时间不会超过一分钟?

我使用 Chromium,但遇到 DNS 未在我预期的时间内缓存的问题。以 example.com 域为例。根据 DNS 设置,该域名应再缓存 26151 秒:

$ dig example.com

;; ANSWER SECTION:
example.com.        26151   IN  A   93.184.216.34

然而,当我在 Chromium 中打开 example.com 并打开 chrome://net-internals/#dns 时,IP在一分钟内就被忘记了!

在此输入图像描述

为什么 Chromium 不遵守域 DNS 设置的 TTL?我怎样才能强制它缓存 DNS 数据直到它们过期?

答案1

Chromium/Chrome 缓存 DNS 请求的时间确实不会超过一分钟。

有趣的是,从bugs-chromium - 问题 164026 - 自 2011 年 4 月 21 日起不支持 DNS TTL

系统中唯一的 DNS 缓存位于 Chrome 中,并且不支持 TTL。我们需要修复 chrome 和/或添加一个能够正确处理 TTL 的中间缓存。

2012 年 12 月 4 日票证中的答案:

HostCache 目前假定所有正面结果的 TTL=60 秒。对于异步DNS解析器,我们计划使用TTL=max(60s, server_reported_ttl),即至少60s。其基本原理是为了提高缓存性能。 (当CDN NS提供TTL=10-20s时,需要30s+才能获取所有子资源,我们经常需要在一页加载期间重新查询相同的主机名。)

门票于 2013 年 10 月 10 日截止:

CrOS 上的 Chrome 使用异步 DNS 解析器,该解析器遵循 TTL = max(60s, > server_reported_ttl)

我将其关闭为 WontFix(已过时/按预期工作)。

这多年来一直是一个众所周知的问题;他们的内部 DNS 解析器忽略 DNS 记录的 TTL,并且仅缓存 DNS 请求 1 分钟。

多年来,用户一直在要求一项改变默认行为的功能,但谷歌从未创建过这样的功能。

过去,您可以禁用 中的内部 DNS 解析器chrome://flags,现在该功能不再公开。

总而言之,它是一个功能,例如,它是通过设计实现的。

(我最初写的是它永远不会改变,这显然不是真的。一个真正有决心的人可以重新编译 Chromium 或破解 Chrome 二进制文件。)。

所以,作为附录:有很多有记录的证据表明 Google 工程师不打算尊重 Chrome/ium 中收到的 DNS 答案中的默认 TTL。

DNS 查询的负缓存 (DNS NCACHE)

与缓存肯定响应一样,解析器限制缓存否定响应的时间是明智的......

虽然暗示解析器可能/应该对缓存 DNS 答案施加最大限制,但 Google Chrome 上的 1 分钟限制可能太低。

PS:在检索 Chrome 统计数据来回答这个问题时,我实际上发现了多年来困扰我的问题的答案:Chrome:带有随机 DNS 名称的 DNS 请求:恶意软件?

PPS 从下面的代码中,显然答案是否定的没有被缓存(TTL=0)。

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   }

相关内容