AXW0 2018-09-02
编译自: https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者: Zwischenzugs
译者: Andy Song
在 Linux DNS 查询剖析(第一部分) 中,我们介绍了:
而在 Linux DNS 查询剖析(第二部分) ,我们介绍了:
剖析进展如下:
(大致)准确的关系图
很可惜,故事还没有结束,还有不少东西也会影响 DNS 查询。在第三部分中,我将介绍 NetworkManager 和 dnsmasq,简要说明它们如何影响 DNS 查询。
在第二部分已经提到,我们现在介绍的内容已经偏离 POSIX 标准,涉及的 DNS 解析管理部分在各个发行版上形式并不统一。
在我使用的发行版 (Ubuntu)中,有一个名为 NetworkManager 的 可用(available)服务,它通常作为一些其它软件包的依赖被安装。它实际上是 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。
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
在目前的情况下,所有的 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。
虽然可以推导出这个结论,但如何查看具体的调用逻辑呢?
我经常思考 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 收到的查询、查询被转发到了哪里以及收到的回复。
如果查询被缓存命中(或者说,本地的查询结果还在 存活时间(time-to-live) 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
在上面的输出中,我猜测(并不确认,? 代表我比较无根据的猜测)如下:
(LCTT 译注:查看 dnsmasq 的源代码 cache.c 可知,4 代表 IPV4,6 代表 IPV6,C 代表 CNAME,S 代表 DNSSEC,F 代表 FORWARD,R 代表 REVERSE,I 代表 IMMORTAL,N 代表 NEG,X 代表 NXDOMAIN,H 代表 HOSTS。更具体的含义需要查看代码或相关文档)
NetworkManager 配置中的 dns 字段并不是只能使用 dnsmasq,可选项包括 none,default,unbound 和 dnssec-triggered 等。使用 none 时,NetworkManager 不会改动 /etc/resolv.conf;使用 default 时,NetworkManager 会根据当前的 活跃连接(active connections)更新 resolv.conf;使用 unbound 时,NetworkManager 会与 unbound 服务通信;dnssec-triggered 与 DNS 安全相关,不在本文讨论范围。
第三部分到此结束,其中我们介绍了 NetworkManager 服务及其 dns=dnsmasq 的配置。
下面简要罗列一下我们已经介绍过的全部内容:
via: https://zwischenzugs.com/2018/07/06/anatomy-of-a-linux-dns-lookup-part-iii/
作者: ZWISCHENZUGS 译者: pinewall 校对: wxy
本文由 LCTT 原创编译, Linux中国 荣誉推出