DNS查询有时需要5秒钟


11

我有一台运行Debian Wheezy的VM,尽管解析程序会立即回复,但在该VM上完成一些主机名查找需要几秒钟。奇怪的是,与getaddrinfo()的查询会受到影响,但gethostbyname()没有受到影响。

我已改用Google解析器,以排除本地解析器损坏的可能性,因此我的/etc/resolv.conf样子如下:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

nsswitch.conf的行:

hosts: files dns

而且我/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>

但是,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)

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

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

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


VM的NIC设置如何?桥接?NAT?
slm

它被NAT了。我不确定NAT的确切应用位置(无论是ESX还是更上游的);我可以找出您是否认为这很重要。
2014年

我怀疑是这影响了NAT + VM。
slm

可能是-请在下面查看我对Kempniu答案的评论。
2014年

这是网络问题,但不是造成此问题的特别是NAT-请参阅下面的答案。
2014年

Answers:


13

第一个DNS回复不会被忽略。getaddrinfo()直到收到第一个AAAA查询(ID:26090)的响应后才返回。因此,这里的真正问题是,为什么您的计算机在收到A查询(ID:54755)的响应时却没有立即收到对AAAA查询的响应。

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

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


感谢您的详细回答。我没有从tcpdump中删除任何内容,只插入了一行以明确暂停位置。你肯定给了我一些东西。我没有意识到两个库调用之间的显着差异。
2014年

如果没有更多与DNS相关的数据包到达您的计算机,则可能是某种过滤其流量(不一定是故意的)。无论如何,如果您找到解决方案,请在这里分享吗?
Kempniu 2014年

1
我的确会。设置了测试解析器后,我可以得出结论,每次都会丢弃一个答复包(来自我的问题的一个答复包)。我怀疑VMware基础架构中或附近的某些功能正在执行此操作,因此我联系了负责该方面工作的同行。当我深入到它的底部时,我会回来并添加细节。再次感谢!
2014年

解决方案已添加到我自己的答案中。再次非常感谢您的帮助。
2014年

9

这是由于位于VMware基础架构前面的Juniper防火墙上的规则集限制过于严格所致。

我构建了一个测试解析器,以便可以看到对话的两面,而肯普纽(Kempniu)在他出色的回答中发现的丢失数据包的确确实丢失了。如该答复所述,getaddrinfo()没有指定地址的家庭将在返回之前(或就我而言,超时)等待与所有受支持家庭有关的答复。

我管理该网络的同事指出

Juniper防火墙上的默认行为是,一旦收到与该会话匹配的DNS回复,便立即关闭与DNS相关的会话。

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

这是Juniper KB的相关摘录:

这是丢弃DNS回复数据包的情况:

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

如果您想提高答案,也请提高Kempniu的答案。没有它,我仍然会在尝试在VM上发现一些配置问题的时候四处寻找。


1
我们在Debian 8.2上遇到了相同的症状。我们的原因是不同的,“解决方案”也不同(客户端)。我在博客中介绍了我们的特定问题和更普遍的问题:philippecloutier.com / ...我要感谢Flup和Kempniu,因为您的问题和答案使我走上了正确的轨道。
Philippe Cloutier
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.