Linux

反向查找超時 0.0.0.0

  • August 27, 2019

在嵌入式 Linux 設備上,我正在執行一個應用程序,該應用程序堅持0.0.0.0在啟動時對 IP 地址進行反向查找。這最終會呼叫gethostbyaddr.

有時gethostbyaddr呼叫會立即完成(失敗),但有時我會看到 5 或 10 秒的延遲(DNS 超時?)。我還不能確定在哪些情況下會發生延遲。

一些提示:

  • 通過在早期初始化腳本之一中執行它,在啟動時禁用 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 秒超時後重試幾乎立即得到響應。

可能是網路沒有完全啟動(因此 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中找到說明。

引用自:https://unix.stackexchange.com/questions/537502