Linux DNS 查詢剖析(第三部分)
![](https://linuxstory.org/wp-content/uploads/2024/06/213042p0w0wwdwhmh0w6wx-800x400.jpeg)
在 Linux DNS 查詢剖析(第一部分)中,我們介紹了:
nsswitch
/etc/hosts
/etc/resolv.conf
ping
與host
查詢方式的對比
而在 Linux DNS 查詢剖析(第二部分),我們介紹了:
systemd
和對應的networking
服務ifup
和ifdown
dhclient
resolvconf
剖析進展如下:
(大致)準確的關係圖
很可惜,故事還沒有結束,還有不少東西也會影響 DNS 查詢。在第三部分中,我將介紹 NetworkManager
和 dnsmasq
,簡要說明它們如何影響 DNS 查詢。
1) NetworkManager
在第二部分已經提到,我們現在介紹的內容已經偏離 POSIX 標準,涉及的 DNS 解析管理部分在各個發行版上形式並不統一。
在我使用的發行版 (Ubuntu)中,有一個名為 NetworkManager 的 可用 服務,它通常作為一些其它軟體包的依賴被安裝。它實際上是 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
代表 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.conf
systemd
及對應的networking
服務ifup
和ifdown
dhclient
resolvconf
NetworkManager
dnsmasq
via: https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者:ZWISCHENZUGS 譯者:pinewall 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive