Linux
反向查找超時 0.0.0.0
在嵌入式 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中找到說明。