反向查找 0.0.0.0 超时

反向查找 0.0.0.0 超时

在嵌入式 Linux 设备上,我正在运行一个应用程序,该应用程序坚持0.0.0.0在启动时对 IP 地址进行反向查找。这最终会调用gethostbyaddr.

有时gethostbyaddr调用会立即完成(失败),但有时我看到延迟(DNS超时?)5秒或10秒。我还不能确定在哪些情况下会发生延迟。

一些提示:

  • 通过在早期初始化脚本之一中运行以下命令,在启动时禁用 IP6 支持:

    echo 1 >/proc/sys/net/ipv6/conf/all/disable_ipv6
    echo 1 >/proc/sys/net/ipv6/conf/default/disable_ipv6
    echo 1 >/proc/sys/net/ipv6/conf/lo/disable_ipv6
    

    (我认为)应该放弃这个:https://www.netroby.com/view/3695

  • 我没有使用 Avahi / MDNS,它应该放弃这个:https://bugs.launchpad.net/ubuntu/+source/nss-mdns/+bug/94940

  • 设备未运行本地 DNS 服务

  • DHCP 或静态 IP 配置都会出现此问题。使用 DHCP 时,我的 DSL 路由器将自己通告为 DNS 服务器。但是当使用静态 IP 配置时,我使用 8.8.8.8 作为 DNS 服务器(因此这应该丢弃 DSL 路由器端有问题的 DNS 服务器)

对这里可能发生的事情有什么想法吗?


更新:

目前相关行/etc/nsswitch.conf是:

hosts: files dns

我设法使用简化的测试应用程序重现该问题。这是发生超时时 strace 输出的片段:

291   23:34:30 connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = 0 <0.000077>
291   23:34:30 gettimeofday({tv_sec=1514849670, tv_usec=139862}, NULL) = 0 <0.000032>
291   23:34:30 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}]) <0.000049>
291   23:34:30 send(6, "\r\231\1\0\0\1\0\0\0\0\0\0\0010\0010\0010\0010\7in-addr\4arp"..., 38, MSG_NOSIGNAL) = 38 <0.000128>
291   23:34:30 poll([{fd=6, events=POLLIN}], 1, 5000) = 0 (Timeout) <5.005152>
291   23:34:35 gettimeofday({tv_sec=1514849675, tv_usec=147536}, NULL) = 0 <0.000088>
291   23:34:35 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}]) <0.000086>
291   23:34:35 send(6, "\r\231\1\0\0\1\0\0\0\0\0\0\0010\0010\0010\0010\7in-addr\4arp"..., 38, MSG_NOSIGNAL) = 38 <0.000206>
291   23:34:35 poll([{fd=6, events=POLLIN}], 1, 5000) = 1 ([{fd=6, revents=POLLIN}]) <0.045356>
291   23:34:35 ioctl(6, FIONREAD, [106]) = 0 <0.000087>
291   23:34:35 recvfrom(6, "\r\231\201\203\0\1\0\0\0\1\0\0\0010\0010\0010\0010\7in-addr\4arp"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [28->16]) = 106 <0.000096>

第一个 DNS 请求没有得到响应,然后在 5 秒超时后重试,几乎立即得到响应。

答案1

网络可能未完全启动(因此 DNS 请求丢失),或者可能只是随机数据包丢失(这种情况确实会发生,尤其是在 WiFi 上)。前者你可以通过等待一段时间来启动应用程序来处理;后者几乎是不可避免的。

不过,一些可能对您有帮助的方法:

  • 修复应用程序。我怀疑这不是一个选择,否则你已经这样做了。

  • 将 0.0.0.0 的条目放入 中/etc/hosts。然后它应该通过“文件”来解决,这基本上是即时的。当然,这需要给 0.0.0.0 一个名称,这可能会也可能不会改变应用程序的行为。如果这对您有用,那么这是最简单的选择。

  • 如果您不需要盒子上的 DNS,请通过将其从 中删除来完全禁用它/etc/nsswitch.conf

  • 运行本地 DNS 缓存,可将其配置为对 0.0.0.in-addr.arpa 具有权威性。然后它可以快速返回 NXDOMAIN 为 0.0.0.0。有几个旨在提供本地缓存的程序可以做到这一点。例如,dnsmasq 相当流行。还有其他的,例如 Unbound,具体取决于您需要的功能。

  • 至少使用 glibc,您可以通过放入类似的内容来更改超时和重试行options timeout:2 attempts:4/etc/resolv.conf。如果减少超时,您可能需要增加尝试次数,因为有时 DNS 服务器可能需要一段时间才能解析它(但一旦解析完成,它应该会快速从缓存中做出响应)。

  • 您可以编写自己的 NSS 模块来快速hosts查找 0.0.0.0 失败。至少对于 glibc,你可以在glibc 手册第 29 节

相关内容