Linux DNS 查询剖析(第三部分)
在 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