Linux DNS 查询剖析(第二部分)
创始人
2024-03-01 23:58:44
0

Linux DNS 查询剖析 - 第一部分 中,我介绍了:

  • nsswitch
  • /etc/hosts
  • /etc/resolv.conf
  • pinghost 查询方式对比

并且发现大多数程序选择要查询的 DNS 服务器时会参考 /etc/resolv.conf 配置文件。

这种方式在 Linux 上比较普遍 1 。虽然我使用了特定的发行版 Ubuntu,但背后的原理与 Debian 甚至是那些基于 CentOS 的发行版有相通的地方;当然,与更低或更高的 Ubuntu 版本相比,差异还是存在的。

也就是说,接下来,你主机上的行为很可能与我描述的不一致。

在第二部分中,我将介绍 resolv.conf 的更新机制、systemctl restart networking 命令的运行机制 ,以及 dhclient 是如何参与其中。

1) 手动更新 /etc/resolv.conf

我们知道 /etc/resolv.conf (有极大的可能性)被用到,故你自然可以通过该文件增加一个 nameserver,那么主机也将会(与已有的 nameserver 一起)使用新加入的 nameserver 吧?

你可以尝试如下:

$ echo nameserver 10.10.10.10 >> /etc/resolv.conf

看上去新的 nameserver 已经加入:

# 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.3
search home
nameserver 10.10.10.10

但主机网络服务重启后问题出现了:

$ systemctl restart networking
$ 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.3
search home

我们的 10.10.10.10nameserver 不见了!

在上一篇文章中我们忽略了这一点,本文进行补充说明。

2) resolvconf

你在 /etc/resolv.conf 文件中看到 generated by resolvconf 词组了吧?这就是我们的线索。

如果深入研究 systemctl restart networking 命令,你会发现它做了很多事情,结束时调用了 /etc/network/if-up.d/000resolvconf 脚本。在该脚本中,可以发现一次对 resolvconf 命令的调用:

/sbin/resolvconf -a "${IFACE}.${ADDRFAM}"

稍微研究一下 man 手册,发现-a 参数允许我们:

Add or overwrite the record IFACE.PROG then run the update scripts
if updating is enabled.

(增加或覆盖 IFACE.PROG 记录,如果开启更新选项,则运行更新脚本)

故而也许我们可以直接调用该命令增加 namserver

echo 'nameserver 10.10.10.10' | /sbin/resolvconf -a enp0s8.inet

测试表明确实可以!

$ cat /etc/resolv.conf  | grep nameserver
nameserver 10.0.2.3
nameserver 10.10.10.10

是否已经找到答案,这就是 /etc/resolv.conf 更新的逻辑?调用 resolvconfnameserver 添加到某个地方的数据库,然后(“如果配置了更新”,先不管具体什么含义)更新 resolv.conf 文件。

并非如此。

$ systemctl restart networking
root@linuxdns1:/etc# 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.3
search home

呃!(网络服务重启后)新增的 nameserver 再次消失了。

可见,systemctl restart networking 不仅仅运行了 resolvconf,还在其它地方获取 nameserver 信息。具体是哪里呢?

3) ifup/ifdown

继续深入研究 systemctl restart networking,发现它完成了一系列工作:

cat /lib/systemd/system/networking.service
[...]
[Service]
Type=oneshot
EnvironmentFile=-/etc/default/networking
ExecStartPre=-/bin/sh -c '[ "$CONFIGURE_INTERFACES" != "no" ] && [ -n "$(ifquery --read-environment --list --exclude=lo)" ] && udevadm settle'
ExecStart=/sbin/ifup -a --read-environment
ExecStop=/sbin/ifdown -a --read-environment --exclude=lo
[...]

首先,网络服务的重启实质是运行一个 单触发 oneshot 的脚本,脚本包含如下命令:

/sbin/ifdown -a --read-environment --exclude=lo
/bin/sh -c '[ "$CONFIGURE_INTERFACES" != "no" ] && [ -n "$(ifquery --read-environment --list --exclude=lo)" ] && udevadm settle'
/sbin/ifup -a --read-environment

第一行使用 ifdown 关闭全部的网络接口,但 本地回环 local, lo 接口除外。 2

(LCTT 译注:其实这是因为很快就又启动了接口,间隔的时间没有超过 TCP 连接的超时时间,有人在评论中也做了类似回复)

第二行用于确认系统已经完成关闭网络接口相关的全部工作,以便下一步使用 ifup 启动接口。这也让我们了解到,网络服务实质运行的就是 ifdownifup

文档中没有找到 --read-environment 参数的说明,该参数为 systemctl 正常工作所需。很多人以文档不完善为由不喜欢 systemctl

很好。那么 ifup (和其成对出现的 ifdown) 到底做了哪些工作呢?长话短说,它运行了 /etc/network/if-pre-up.d//etc/network/if-up.d/ 目录下的全部脚本;期间,这些脚本也可能会调用另外的脚本,依此类推。

其中一件工作就是运行了 dhclient,但我还不完全确定具体的机理,也许 udev 参与其中。

4) dhclient

dhclient 是一个程序,用于与 DHCP 服务器协商对应网络接口应该使用的 IP 地址的详细信息。同时,它也可以获取可用的 DNS 服务器并将其替换到 /etc/resolv.conf 中。

让我们开始跟踪并模拟它的行为,但仅在我实验虚拟机的 enp0s3 接口上。事先已经删除 /etc/resolv.conf 文件中的 nameserver 配置:

$ sed -i '/nameserver.*/d' /run/resolvconf/resolv.conf
$ cat /etc/resolv.conf | grep nameserver
$ dhclient -r enp0s3 && dhclient -v enp0s3
Killed old client process
Internet Systems Consortium DHCP Client 4.3.3
Copyright 2004-2015 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/enp0s8/08:00:27:1c:85:19
Sending on   LPF/enp0s8/08:00:27:1c:85:19
Sending on   Socket/fallback
DHCPDISCOVER on enp0s8 to 255.255.255.255 port 67 interval 3 (xid=0xf2f2513e)
DHCPREQUEST of 172.28.128.3 on enp0s8 to 255.255.255.255 port 67 (xid=0x3e51f2f2)
DHCPOFFER of 172.28.128.3 from 172.28.128.2
DHCPACK of 172.28.128.3 from 172.28.128.2
bound to 172.28.128.3 -- renewal in 519 seconds.

$ cat /etc/resolv.conf | grep nameserver
nameserver 10.0.2.3

可见这就是 nameserver 的来源。

但稍等一下,命令中的 /run/resolvconf/resolv.conf 是哪个文件,不应该是 /etc/resolv.conf 吗?

事实上,/etc/resolv.conf 并不一定只是一个普通文本文件。

在我的虚拟机上,它是一个软链接,指向位于 /run/resolvconf 目录下的“真实文件”。这也暗示了我们,该文件是在系统启动时生成的;同时,这也是该文件注释告诉我们不要直接修改该文件的原因。

(LCTT 译注:在 CentOS 7 中,没有 resolvconf 命令,/etc/resolv.conf 也不是软链接)

假如上面命令中 sed 命令直接处理 /etc/resolv.conf 文件,效果是不同的,会有警告消息告知待操作的文件不能是软链接(sed -i 无法很好的处理软链接,它只会创建一个新文件)。

(LCTT 译注:CentOS 7 测试时,sed -i 命令操作软链接并没有警告,但确实创建了新文件取代软链接)

如果你继续深入查看配置文件 /etc/dhcp/dhclient.confsupersede 部分,你会发现 dhclient 可以覆盖 DHCP 提供的 DNS 服务器。

linux-dns-2 (2)

(大致)准确的关系图


第二部分的结束语

第二部分到此结束。信不信由你,这是一个某种程度上简化的流程版本,但我尽量保留重要和值得了解的部分,让你不会感到无趣。大部分内容都是围绕实际脚本的运行展开的。

但我们的工作还没有结束,在第三部分,我们会介绍这些之上的更多层次。

让我们简要列出我们已经介绍过的内容:

  • nsswitch
  • /etc/hosts
  • /etc/resolv.conf
  • /run/resolvconf/resolv.conf
  • systemd 和网络服务
  • ifupifdown
  • dhclient
  • resolvconf

  1. 事实上,这是相对于 POSIX 标准的,故不限于 Linux (我从上一篇文章的一条极好的回复中了解到这一点)
  2. 我不明白为何这没有导致我例子中的 vagrant 会话中断 (有谁明白吗?)。

via: https://zwischenzugs.com/2018/06/18/anatomy-of-a-linux-dns-lookup-part-ii/

作者:ZWISCHENZUGS
译者:pinewall
校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

DNS

相关内容

DNS、ICMP协议、NA...
目录 DNS 使用dig工具分析DNS过程  当在浏览器输入ur...
2025-06-01 17:57:52
【sqlmap渗透进阶】D...
目录 注入说明 利用条件 注意事项 源码分析 DNS-domain...
2025-05-30 07:54:44
Chrome 浏览器获取网...
解析阶段详细流程说明 步骤说明①浏览器输入:http...
2025-05-28 07:01:35
如何在CentOS系统上部...
作为Linux系统中广泛使用的DNS服务软件,BIND(Berke...
2025-05-25 13:47:28
Linux系统下如何调整D...
文章标题:域名解析记录变更时,TTL值调整的重要性及其对DNS缓存...
2025-04-18 22:46:29
不同命名空间中Kubern...
在Kubernetes中,不同命名空间中服务的DNS名称的格式是 ...
2025-01-09 11:31:18

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
从 Yum 更新中排除特定/某... 作为系统更新的一部分,你也许需要在基于 Red Hat 系统中由于应用依赖排除一些软件包。如果是,如...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...
如何检查你的 Linux 系统... 不知道在使用哪个初始化系统?以下是方法。每个主流 Linux 发行版(包括 Ubuntu、Fedor...