https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者 | Zwischenzugs
譯者 | Andy Song (pinewall) ????共計翻譯:35 篇 貢獻時間:156 天
在 Linux DNS 查詢剖析(第一部分)[1]中,我們介紹了:
nsswitch/etc/hosts/etc/resolv.confping 與 host 查詢方式的對比而在 Linux DNS 查詢剖析(第二部分)[2],我們介紹了:
systemd 和對應的 networking 服務ifup 和 ifdowndhclientresolvconf剖析進展如下:

(大致)準確的關係圖
很可惜,故事還沒有結束,還有不少東西也會影響 DNS 查詢。在第三部分中,我將介紹 NetworkManager 和 dnsmasq,簡要說明它們如何影響 DNS 查詢。
1) NetworkManager
在第二部分已經提到,我們現在介紹的內容已經偏離 POSIX 標準,涉及的 DNS 解析管理部分在各個發行版上形式並不統一。
在我使用的發行版 (Ubuntu)中,有一個名為 NetworkManager[3] 的可用服務,它通常作為一些其它軟體包的依賴被安裝。它實際上是 RedHat 在 2004 年開發的一個服務,用於幫助你管理網路介面。
它與 DNS 查詢有什麼關係呢?讓我們安裝這個服務並找出答案:
$ apt-get install -y network-manager
對於 Ubuntu,在軟體包安裝後,你可以發現一個新的配置檔案:
$ cat /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifupdown,keyfile,ofono
dns=dnsmasq
[ifupdown]
managed=false
看到 dns=dnsmasq 了吧?這意味著 NetworkManager 將使用 dnsmasq 管理主機上的 DNS。
2) dnsmasq
dnsmasq 程式是我們很熟悉的程式:只是 /etc/resolv.conf 之上的又一個間接層。
理論上,dnsmasq 有多種用途,但主要被用作 DNS 快取伺服器,快取到其它 DNS 伺服器的請求。dnsmasq 在本地所有網路介面上監聽 53 埠(標準的 DNS 埠)。
那麼 dnsmasq 執行在哪裡呢?NetworkManager 的執行情況如下:
$ ps -ef | grep NetworkManager
root 15048 1 0 16:39 ? 00:00:00 /usr/sbin/NetworkManager --no-daemon
但並沒有找到 dnsmasq 相關的行程:
$ ps -ef | grep dnsmasq
$
令人迷惑的是,雖然 dnsmasq 被配置用於管理 DNS,但其實並沒有安裝在系統上!因而,你需要自己安裝它。
安裝之前,讓我們檢視一下 /etc/resolv.conf 檔案的內容:
$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.0.2.2
search home
可見,並沒有被 NetworkManager 修改。
如果安裝 dnsmasq:
$ apt-get install -y dnsmasq
然後啟動執行 dnsmasq:
$ ps -ef | grep dnsmasq
dnsmasq 15286 1 0 16:54 ? 00:00:00 /usr/sbin/dnsmasq -x /var/run/dnsmasq/dnsmasq.pid -u dnsmasq -r /var/run/dnsmasq/resolv.conf -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new --local-service --trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
然後,/etc/resolv.conf 檔案內容又改變了!
root@linuxdns1:~# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
search home
執行 netstat 命令,可以看出 dnsmasq 在所有網路介面上監聽 53 埠:
$ netstat -nlp4
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 15286/dnsmasq
tcp 0 0 10.0.2.15:53 0.0.0.0:* LISTEN 15286/dnsmasq
tcp 0 0 172.28.128.11:53 0.0.0.0:* LISTEN 15286/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1237/sshd
udp 0 0 127.0.0.1:53 0.0.0.0:* 15286/dnsmasq
udp 0 0 10.0.2.15:53 0.0.0.0:* 15286/dnsmasq
udp 0 0 172.28.128.11:53 0.0.0.0:* 15286/dnsmasq
udp 0 0 0.0.0.0:68 0.0.0.0:* 10758/dhclient
udp 0 0 0.0.0.0:68 0.0.0.0:* 10530/dhclient
udp 0 0 0.0.0.0:68 0.0.0.0:* 10185/dhclient
3) 分析 dnsmasq
在目前的情況下,所有的 DNS 查詢都會使用 127.0.0.1:53 這個 DNS 伺服器,下一步會發生什麼呢?
我再次檢視 /var/run 目錄,可以發現一個線索:resolvconf 目錄下 resolv.conf檔案中的配置也相應變更,變更為 dnsmasq 對應的 DNS 伺服器:
$ cat /var/run/resolvconf/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
search home
同時,出現了一個新的 dnsmasq 目錄,也包含一個 resolv.conf 檔案:
$ cat /run/dnsmasq/resolv.conf
nameserver 10.0.2.2
(LCTT 譯註:這裡依次提到了 /var/run 和 /run,使用 Ubuntu 16.04 LTS 驗證發現,/var/run 其實是指向 /run/ 的軟連結)
該檔案包含我們從 DHCP 獲取的 nameserver。
雖然可以推匯出這個結論,但如何檢視具體的呼叫邏輯呢?
4) 除錯 dnsmasq
我經常思考 dnsmasq (在整個過程中)的功能定位。幸運的是,如果你將 /etc/dnsmasq.conf 中的一行做如下調整,你可以獲取大量 dnsmasq 狀態的資訊:
#log-queries
修改為:
log-queries
然後重啟 dnsmasq。
接下來,只要執行一個簡單的命令:
$ ping -c1 bbc.co.uk
你就可以在 /var/log/syslog 中找到類似的內容(其中 [...] 表示行首內容與上一行相同):
Jul 3 19:56:07 ubuntu-xenial dnsmasq[15372]: query[A] bbc.co.uk from 127.0.0.1
[...] forwarded bbc.co.uk to 10.0.2.2
[...] reply bbc.co.uk is 151.101.192.81
[...] reply bbc.co.uk is 151.101.0.81
[...] reply bbc.co.uk is 151.101.64.81
[...] reply bbc.co.uk is 151.101.128.81
[...] query[PTR] 81.192.101.151.in-addr.arpa from 127.0.0.1
[...] forwarded 81.192.101.151.in-addr.arpa to 10.0.2.2
[...] reply 151.101.192.81 is NXDOMAIN
可以清晰看出 dnsmasq 收到的查詢、查詢被轉發到了哪裡以及收到的回覆。
如果查詢被快取命中(或者說,本地的查詢結果還在存活時間 TTL 內,並未過期),日誌顯示如下:
[...] query[A] bbc.co.uk from 127.0.0.1
[...] cached bbc.co.uk is 151.101.64.81
[...] cached bbc.co.uk is 151.101.128.81
[...] cached bbc.co.uk is 151.101.192.81
[...] cached bbc.co.uk is 151.101.0.81
[...] query[PTR] 81.64.101.151.in-addr.arpa from 127.0.0.1
如果你想瞭解快取中有哪些記錄,可以向 dnsmasq 行程 id 傳送 USR1 訊號,這樣 dnsmasq 會將快取記錄匯出並寫入到相同的日誌檔案中:
$ kill -SIGUSR1 $(cat /run/dnsmasq/dnsmasq.pid)
(LCTT 譯註:原文中命令執行報錯,已變更成最接近且符合作者意圖的命令)
匯出記錄對應如下輸出:
Jul 3 15:08:08 ubuntu-xenial dnsmasq[15697]: time 1530630488
[...] cache size 150, 0/5 cache insertions re-used unexpired cache entries.
[...] queries forwarded 2, queries answered locally 0
[...] queries for authoritative zones 0
[...] server 10.0.2.2#53: queries sent 2, retried or failed 0
[...] Host Address Flags Expires
[...] linuxdns1 172.28.128.8 4FRI H
[...] ip6-localhost ::1 6FRI H
[...] ip6-allhosts ff02::3 6FRI H
[...] ip6-localnet fe00:: 6FRI H
[...] ip6-mcastprefix ff00:: 6FRI H
[...] ip6-loopback : 6F I H
[...] ip6-allnodes ff02: 6FRI H
[...] bbc.co.uk 151.101.64.81 4F Tue Jul 3 15:11:41 2018
[...] bbc.co.uk 151.101.192.81 4F Tue Jul 3 15:11:41 2018
[...] bbc.co.uk 151.101.0.81 4F Tue Jul 3 15:11:41 2018
[...] bbc.co.uk 151.101.128.81 4F Tue Jul 3 15:11:41 2018
[...] 151.101.64.81 4 R NX Tue Jul 3 15:34:17 2018
[...] localhost 127.0.0.1 4FRI H
[...] <Root> 19036 8 2 SF I
[...] ip6-allrouters ff02::2 6FRI H
在上面的輸出中,我猜測(並不確認,? 代表我比較無根據的猜測)如下:
4 代表 IPv46 代表 IPv6H 代表從 /etc/hosts 中讀取 IP 地址I ? “永生”的 DNS 記錄 ? (例如,沒有設定存活時間數值 ?)F ?R ?S ?N ?X(LCTT 譯註:檢視 dnsmasq 的原始碼 cache.c[4] 可知,4 代表 IPV4,6 代表 IPV6,C 代表 CNAME,S 代表 DNSSEC,F 代表 FORWARD,R 代表 REVERSE,I 代表 IMMORTAL,N 代表 NEG,X 代表 NXDOMAIN,H 代表 HOSTS。更具體的含義需要檢視程式碼或相關檔案)
dnsmasq 的替代品
NetworkManager 配置中的 dns 欄位並不是隻能使用 dnsmasq,可選項包括 none,default,unbound 和 dnssec-triggered 等。使用 none 時,NetworkManager 不會改動 /etc/resolv.conf;使用 default 時,NetworkManager 會根據當前的活躍連線更新 resolv.conf;使用 unbound 時,NetworkManager 會與 unbound 服務通訊;dnssec-triggered與 DNS 安全相關,不在本文討論範圍。
第三部分總結
第三部分到此結束,其中我們介紹了 NetworkManager 服務及其 dns=dnsmasq 的配置。
下麵簡要羅列一下我們已經介紹過的全部內容:
nsswitch/etc/hosts/etc/resolv.conf/run/resolvconf/resolv.confsystemd 及對應的 networking 服務ifup 和 ifdowndhclientresolvconfNetworkManagerdnsmasqvia: https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者:ZWISCHENZUGS[6] 譯者:pinewall 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出
知識星球