歡迎光臨
每天分享高質量文章

Linux DNS 查詢剖析(第三部分) | Linux 中國

在第三部分中,我將介紹 NetworkManager 和 dnsmasq,簡要說明它們如何影響 DNS 查詢。
— Zwischenzugs


致謝
編譯自 | 
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.conf
◈ ping 與 host 查詢方式的對比

而在 Linux DNS 查詢剖析(第二部分)[2],我們介紹了:

◈ systemd 和對應的 networking 服務
◈ ifup 和 ifdown
◈ dhclient
◈ resolvconf

剖析進展如下:

(大致)準確的關係圖

很可惜,故事還沒有結束,還有不少東西也會影響 DNS 查詢。在第三部分中,我將介紹 NetworkManager 和 dnsmasq,簡要說明它們如何影響 DNS 查詢。

1) NetworkManager

在第二部分已經提到,我們現在介紹的內容已經偏離 POSIX 標準,涉及的 DNS 解析管理部分在各個發行版上形式並不統一。

在我使用的發行版 (Ubuntu)中,有一個名為 NetworkManager[3] 的可用available服務,它通常作為一些其它軟體包的依賴被安裝。它實際上是 RedHat 在 2004 年開發的一個服務,用於幫助你管理網路介面。

它與 DNS 查詢有什麼關係呢?讓我們安裝這個服務並找出答案:

  1. $ apt-get install -y network-manager

對於 Ubuntu,在軟體包安裝後,你可以發現一個新的配置檔案:

  1. $ cat /etc/NetworkManager/NetworkManager.conf

  2. [main]

  3. plugins=ifupdown,keyfile,ofono

  4. dns=dnsmasq

  5. [ifupdown]

  6. managed=false

看到 dns=dnsmasq 了吧?這意味著 NetworkManager 將使用 dnsmasq 管理主機上的 DNS。

2) dnsmasq

dnsmasq 程式是我們很熟悉的程式:只是 /etc/resolv.conf 之上的又一個間接層。

理論上,dnsmasq 有多種用途,但主要被用作 DNS 快取伺服器,快取到其它 DNS 伺服器的請求。dnsmasq 在本地所有網路介面上監聽 53 埠(標準的 DNS 埠)。

那麼 dnsmasq 執行在哪裡呢?NetworkManager 的執行情況如下:

  1. $ ps -ef | grep NetworkManager

  2. root     15048     1  0 16:39 ?        00:00:00 /usr/sbin/NetworkManager --no-daemon

但並沒有找到 dnsmasq 相關的行程:

  1. $ ps -ef | grep dnsmasq

  2. $

令人迷惑的是,雖然 dnsmasq 被配置用於管理 DNS,但其實並沒有安裝在系統上!因而,你需要自己安裝它。

安裝之前,讓我們檢視一下 /etc/resolv.conf 檔案的內容:

  1. $ cat /etc/resolv.conf

  2. # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)

  3. #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

  4. nameserver 10.0.2.2

  5. search home

可見,並沒有被 NetworkManager 修改。

如果安裝 dnsmasq

  1. $ apt-get install -y dnsmasq

然後啟動執行 dnsmasq

  1. ps -ef | grep dnsmasq

  2. 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 檔案內容又改變了!

  1. root@linuxdns1:~# cat /etc/resolv.conf

  2. # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)

  3. #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

  4. nameserver 127.0.0.1

  5. search home

執行 netstat 命令,可以看出 dnsmasq 在所有網路介面上監聽 53 埠:

  1. $ netstat -nlp4

  2. Active Internet connections (only servers)

  3. Proto Recv-Q Send-Q Local Address     Foreign Address State   PID/Program name

  4. tcp        0      0 127.0.0.1:53      0.0.0.0:*       LISTEN  15286/dnsmasq 

  5. tcp        0      0 10.0.2.15:53      0.0.0.0:*       LISTEN  15286/dnsmasq

  6. tcp        0      0 172.28.128.11:53  0.0.0.0:*       LISTEN  15286/dnsmasq

  7. tcp        0      0 0.0.0.0:22        0.0.0.0:*       LISTEN  1237/sshd

  8. udp        0      0 127.0.0.1:53      0.0.0.0:*               15286/dnsmasq

  9. udp        0      0 10.0.2.15:53      0.0.0.0:*               15286/dnsmasq  

  10. udp        0      0 172.28.128.11:53  0.0.0.0:*               15286/dnsmasq  

  11. udp        0      0 0.0.0.0:68        0.0.0.0:*               10758/dhclient

  12. udp        0      0 0.0.0.0:68        0.0.0.0:*               10530/dhclient

  13. 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 伺服器:

  1. $ cat /var/run/resolvconf/resolv.conf

  2. # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)

  3. #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

  4. nameserver 127.0.0.1

  5. search home

同時,出現了一個新的 dnsmasq 目錄,也包含一個 resolv.conf 檔案:

  1. $ cat /run/dnsmasq/resolv.conf

  2. 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 狀態的資訊:

  1. #log-queries

修改為:

  1. log-queries

然後重啟 dnsmasq

接下來,只要執行一個簡單的命令:

  1. $ ping -c1 bbc.co.uk

你就可以在 /var/log/syslog 中找到類似的內容(其中 [...] 表示行首內容與上一行相同):

  1. Jul  3 19:56:07 ubuntu-xenial dnsmasq[15372]: query[A] bbc.co.uk from 127.0.0.1

  2. [...] forwarded bbc.co.uk to 10.0.2.2

  3. [...] reply bbc.co.uk is 151.101.192.81

  4. [...] reply bbc.co.uk is 151.101.0.81

  5. [...] reply bbc.co.uk is 151.101.64.81

  6. [...] reply bbc.co.uk is 151.101.128.81

  7. [...] query[PTR] 81.192.101.151.in-addr.arpa from 127.0.0.1

  8. [...] forwarded 81.192.101.151.in-addr.arpa to 10.0.2.2

  9. [...] reply 151.101.192.81 is NXDOMAIN

可以清晰看出 dnsmasq 收到的查詢、查詢被轉發到了哪裡以及收到的回覆。

如果查詢被快取命中(或者說,本地的查詢結果還在存活時間time-to-live TTL 內,並未過期),日誌顯示如下:

  1. [...] query[A] bbc.co.uk from 127.0.0.1

  2. [...] cached bbc.co.uk is 151.101.64.81

  3. [...] cached bbc.co.uk is 151.101.128.81

  4. [...] cached bbc.co.uk is 151.101.192.81

  5. [...] cached bbc.co.uk is 151.101.0.81

  6. [...] query[PTR] 81.64.101.151.in-addr.arpa from 127.0.0.1

如果你想瞭解快取中有哪些記錄,可以向 dnsmasq 行程 id 傳送 USR1 訊號,這樣 dnsmasq 會將快取記錄匯出並寫入到相同的日誌檔案中:

  1. $ kill -SIGUSR1 $(cat /run/dnsmasq/dnsmasq.pid)

(LCTT 譯註:原文中命令執行報錯,已變更成最接近且符合作者意圖的命令)

匯出記錄對應如下輸出:

  1. Jul  3 15:08:08 ubuntu-xenial dnsmasq[15697]: time 1530630488

  2. [...] cache size 150, 0/5 cache insertions re-used unexpired cache entries.

  3. [...] queries forwarded 2, queries answered locally 0

  4. [...] queries for authoritative zones 0

  5. [...] server 10.0.2.2#53: queries sent 2, retried or failed 0

  6. [...] Host             Address         Flags      Expires

  7. [...] linuxdns1        172.28.128.8    4FRI   H

  8. [...] ip6-localhost    ::1             6FRI   H

  9. [...] ip6-allhosts     ff02::3         6FRI   H

  10. [...] ip6-localnet     fe00::          6FRI   H

  11. [...] ip6-mcastprefix  ff00::          6FRI   H

  12. [...] ip6-loopback     :               6F I   H

  13. [...] ip6-allnodes     ff02:           6FRI   H

  14. [...] bbc.co.uk        151.101.64.81   4F         Tue Jul  3 15:11:41 2018

  15. [...] bbc.co.uk        151.101.192.81  4F         Tue Jul  3 15:11:41 2018

  16. [...] bbc.co.uk        151.101.0.81    4F         Tue Jul  3 15:11:41 2018

  17. [...] bbc.co.uk        151.101.128.81  4F         Tue Jul  3 15:11:41 2018

  18. [...]                  151.101.64.81   4 R  NX    Tue Jul  3 15:34:17 2018

  19. [...] localhost        127.0.0.1       4FRI   H

  20. [...] <Root>           19036   8   2   SF I

  21. [...] ip6-allrouters   ff02::2         6FRI   H

在上面的輸出中,我猜測(並不確認,? 代表我比較無根據的猜測)如下:

◈ 4 代表 IPv4
◈ 6 代表 IPv6
◈ H 代表從 /etc/hosts 中讀取 IP 地址
◈ I ? “永生”的 DNS 記錄 ? (例如,沒有設定存活時間數值 ?)
◈ F ?
◈ R ?
◈ S ?
◈ N ?
◈ X

(LCTT 譯註:檢視 dnsmasq 的原始碼 cache.c[4] 可知,4 代表 IPV46 代表 IPV6C 代表 CNAMES 代表 DNSSECF 代表 FORWARDR 代表 REVERSEI 代表 IMMORTALN 代表 NEGX 代表 NXDOMAINH 代表 HOSTS。更具體的含義需要檢視程式碼或相關檔案)

dnsmasq 的替代品

NetworkManager 配置中的 dns 欄位並不是隻能使用 dnsmasq,可選項包括 nonedefaultunbound 和 dnssec-triggered 等。使用 none 時,NetworkManager 不會改動 /etc/resolv.conf;使用 default 時,NetworkManager 會根據當前的活躍連線active connections更新 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[6] 譯者:pinewall 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

贊(0)

分享創造快樂