DNS 查找有时需要 5 秒

Flu*_*lup 12 linux dns

我有一个运行 Debian Wheezy 的虚拟机,即使解析器立即回复,某些主机名查找也需要几秒钟才能完成。奇怪的是,查找getaddrinfo()会受到影响,但gethostbyname()不会。

我已经切换到 Google 解析器以排除本地解析器损坏的可能性,所以我/etc/resolv.conf看起来像:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8
Run Code Online (Sandbox Code Playgroud)

nsswitch.conf的线路:

hosts: files dns
Run Code Online (Sandbox Code Playgroud)

而我的/etc/hosts不包含任何异常。

如果我尝试telnet webserver 80,它会在获得名称解析之前挂起几秒钟。的ltrace输出[1]示出了悬挂在一个getaddrinfo()呼叫:

getaddrinfo("ifconfig.me", "telnet", { AI_CANONNAME, 0, SOCK_STREAM, 0, 0, NULL, '\000', NULL }, 0x7fffb4ffc160) = 0 <5.020621>
Run Code Online (Sandbox Code Playgroud)

然而,tcpdump显示名称服务器立即回复,并且只有在第二次回复时才telnet解锁。回复看起来相同:

05:52:58.609731 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:52:58.609786 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:52:58.612188 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)

[...five second pause...]

05:53:03.613811 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:53:03.616424 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)
05:53:03.616547 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:53:03.618907 IP 8.8.4.4.53 > 192.168.1.75.43017: 26090 0/1/0 (76)
Run Code Online (Sandbox Code Playgroud)

我检查了主机防火墙日志,端口 53 上没有任何内容被阻止。

是什么导致第一个 DNS 回复被忽略?

[1] 我已经添加了几行,ltrace.conf所以我可以看到addrinfo结构内部。

Kem*_*niu 14

第一个 DNS 回复不会被忽略。getaddrinfo()直到收到对第一个 AAAA 查询(ID:26090)的响应才返回。所以这里真正的问题是为什么你的机器没有立即收到 AAAA 查询的响应,而它已经收到了 A 查询的响应(ID:54755)。

getaddrinfo()和之间的区别之一gethostbyname()是前者同时支持IPv4和IPv6,而后者只支持IPv4。所以,当你调用getaddrinfo()ai_family设置为0( AF_UNSPEC),它不会返回,直到它得到的回应(或命中超时)为双方所提供的域名和AAAA查询。gethostbyname()只查询 A 记录。

很难远程确定是什么导致了您的问题,尤其是您已经切断了一些tcpdump输出。有些东西可能会选择性地过滤/丢弃您的 VM 和 Google 公共 DNS 解析器之间的 DNS 流量。我曾尝试使用 KVM Debian Wheezy VM 重现您的问题,但telnet ifconfig.me几乎立即打印了该Trying <IP_address_here>...行(这意味着到那时它已经解析了名称)。


Flu*_*lup 10

这是由位于 VMware 基础架构前面的瞻博网络防火墙上的限制性过度的规则集引起的。

我构建了一个测试解析器,以便我可以看到对话的双方,而 Kempniu 在他出色的回答中确定的丢失的数据包确实在沿途的某个地方被丢弃了。如该答案中所述,getaddrinfo()未指定地址家庭将在返回之前等待与所有受支持家庭相关的答案(或者,在我的情况下,超时)。

我运行网络的同事指出

Juniper 防火墙的默认行为是在收到与该会话匹配的 DNS 回复后立即关闭与 DNS 相关的会话。

所以防火墙看到了 IPv4 响应,注意到它回答了 VM 的查询,并关闭了该端口的入站路径。因此丢弃了以下 IPv6 回复数据包。我不知道为什么这两个数据包都第二次通过了,但是在防火墙上禁用此功能可以解决问题。

这是瞻博网络知识库的相关摘录:

以下是丢弃 DNS 回复数据包的场景:

  1. 当第一个 DNS 查询数据包到达防火墙并且配置了允许策略时,就会创建 DNS 流量会话。默认超时为 60 秒。
  2. 紧接在会话关闭之前,将传输一个新的 DNS 查询,并且由于它与现有会话匹配(因为源和目标端口/IP 对始终相同),因此由防火墙转发。请注意,会话超时不会根据任何新到达的数据包进行刷新。
  3. 创建的 DNS 会话在第一个 DNS 查询响应(回复)到达设备时过期,无论超时剩余多少。
  4. 当 DNS 回复通过防火墙时,会话将过期。
  5. 由于不存在会话,因此防火墙丢弃所有后续 DNS 回复。

如果您正在考虑为这个答案投票,请同时为 Kempniu 的答案投票。没有它,我仍然会努力寻找 VM 上的一些配置问题。