------------------------------------------------------------------
author: hjjdebug
date: 2023年 11月 09日 星期四 14:01:11 CST
description: Ubuntu 20.04 DNS解析原理, 解决resolv.conf被覆盖问题
------------------------------------------------------------------
问题:
开机后不能上网, ping baidu.com 不能ping 通,
错误为:
ping: baidu.com: 域名解析暂时失败
修改 /etc/resolv.conf 文件,添加
nameserver 8.8.8.8
再ping baidu.com, 可以ping 通, 可以正常上网.
但是,当重新启动机器后, /etc/resolv.conf 文件被覆盖为旧的文件,
要想上网, 还需要重新修改文件内容.
解决问题的方法很简单,只需要看第7步即可.即修改/etc/systemd/resolved.conf,添加DNS=8.8.8.8
想了解其工作原理,可阅读本博客! 关注以下内容:
1. 域名解析服务是什么? systemd-resolved.service
2. 它起了什么作用? 它将127.0.0.53的请求转发给后端服务请求
3. 后端服务请求服务器是哪个文件? /run/systemd/resolve/resolv.conf
4. 该文件是如何生成的, 开机时由 /etc/systemd/resolved.conf 形成
5. 域名解析的过程? 参考步骤8, 由127.0.0.53转发给后端server
6. 域名解析工具resolvectl 的使用
这里记录一下我解决问题的过程:
解决问题的思路:
1. 查寻 /etc/resolv.conf, 是一个文件链接.
$ls -l /etc/resolv.conf
resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
在 /run/systemd/resolve 目录, 有2个文件, 它们每次开机时都会重新生成(看文件时间)
-rw-r--r-- 1 systemd-resolve systemd-resolve 584 11月 9 11:13 resolv.conf
-rw-r--r-- 1 systemd-resolve systemd-resolve 717 11月 9 11:13 stub-resolv.conf
所以不能直接修改这两个文件, 因为它们会开机重新生成. 旧内容被覆盖.
而且你用vim 打开 /etc/resolv.conf 文件, 也可以看到如下提示:
This file is managed by man:systemd-resolved(8). Do not edit.
可见该文件是由systemd-resolved 服务来管理,不要编辑.
2. 查询域名解析服务名称
$ systemctl status |grep resolv
├─systemd-resolved.service
└─1254 /lib/systemd/systemd-resolved
3. 查询域名解析服务状态
$ systemctl status systemd-resolved
● systemd-resolved.service - Network Name Resolution
Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; ven>
Active: active (running) since Thu 2023-11-09 11:13:47 CST; 11min ago
Docs: man:systemd-resolved.service(8)
https://www.freedesktop.org/wiki/Software/systemd/resolved
https://www.freedesktop.org/wiki/Software/systemd/writing-network->
https://www.freedesktop.org/wiki/Software/systemd/writing-resolver>
Main PID: 1254 (systemd-resolve)
Status: "Processing requests..."
Tasks: 1 (limit: 9103)
Memory: 8.6M
CGroup: /system.slice/systemd-resolved.service
└─1254 /lib/systemd/systemd-resolved
4. 查找服务配置文件.
用lsof -p 1254 只能查看它当前打开的文件,并不能判定它的配置文件是谁.
用fswatch 监视 /etc/systemd 目录, -t 是打印时间, -x 是打印事件
$fswatch -t -x /etc/systemd
然后执行 停止,启动 systemd-resolved 服务
$ sudo systemctl stop systemd-resolved
$ sudo systemctl start systemd-resolved
监视到如下事件:
2023年11月09日 星期四 11时34分22秒 /etc/systemd/resolved.conf PlatformSpecific
说明它访问了 /etc/systemd/resolved.conf 文件, 这也仅仅表示打开服务会访问这个文件,
通过查找网络资源, 确认还是要手工修改/etc/systemd/resolved.conf 这个文件
5. 编辑服务配置文件 /etc/systemd/resolved.conf
打开这个文件, 看到是一个空文件, 由若干行但都被# 号注释着, 把第一行DNS 的注释号去掉,
写成:
DNS=8.8.8.8
这个文件改动后, 开机会依照它重新生成 /run/systemd/resolve/resolv.conf 文件
6. 验证
重启机器,看到/run/systemd/resolve 目录下新生成的文件
-rw-r--r-- 1 systemd-resolve systemd-resolve 584 11月 9 12:42 resolv.conf
-rw-r--r-- 1 systemd-resolve systemd-resolve 717 11月 9 12:42 stub-resolv.conf
查看内容: stub-resolv.conf 没有改变
resolv.conf 内容已经添加了:
nameserver 8.8.8.8
7. 结论: 其实只要一步修改
修改 /etc/systemd/resolved.conf, 添加DNS=8.8.8.8
验证: 开机后,ping baidu.com 可以ping 通
8. systemd-resolved 服务起到了什么作用?
在没有systemd-resolved 服务的机器上,域名是这样解析的
1.从dns缓存里查找域名与ip的映射关系
2.从/etc/hosts里查找域名与ip的映射关系
3. 从/etc/resolv.conf里查找dns server,并发起解析请求
/etc/resolv.conf的内容一般如下:
nameserver 8.8.8.8
在有systemd-resolved 服务的机器上,域名还是这样解析的
1.从dns缓存里查找域名与ip的映射关系
2.从/etc/hosts里查找域名与ip的映射关系
3. 从/etc/resolv.conf里查找dns server,并发起解析请求
但是, 此时/etc/resolv.conf 的内容如下:
nameserver 127.0.0.53
options edns0 trust-ad
使得本地解析请求全部发到127.0.0.53
然后systemd-resolved再根据/run/systemd/resolve/resolv.conf里面的dns server去发起请求
/run/systemd/resolve/resolv.conf记录的就是真正的后端dns server
9. 域名解析工具 resolvectl
$ ls -l systemd-resolve
lrwxrwxrwx 1 root root 10 3月 2 2023 systemd-resolve -> resolvectl*
systemd-resolve 就是resolvectl 的软链接.
resolvectl 是 systemd 包中的工具:
$ which resolvectl
/bin/resolvectl
$dpkg -S /usr/bin/resolvectl
systemd: /usr/bin/resolvectl
resolvectl 的使用方法:
$ resolvectl -h
$ resolvectl status
$ resolvectl query baidu.com
$ resolvectl query www.baidu.com
$ resolvectl flush-caches
$ resolvectl statistics
----------------------------------------------------------------------------------------
补充: centos7 下也有/etc/resolv.conf 被重置问题. 解决方法
---------------------------------------------------------------------------------------
1. 查看 /etc/resolv.conf 文件
$ cat /etc/resolv.conf
# Generated by NetworkManager
可见它是由NetworkManager 来生成的.
$ systemctl status |grep -i network
发现
├─NetworkManager.service
│ └─954 /usr/sbin/NetworkManager --no-daemon
2. 编辑NetworkManager 的配置文件
vim /etc/NetworkManager/NetworkManager.conf
在 [main]下添加dns=8.8.8.8, 如下示例
[main]
dns=8.8.8.8
3. 重启网络服务验证.
$ systemctl restart NetworkManager.service
$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 8.8.8.8
发现 /etc/resolv.conf 已经添加了 nameserver ,问题解决!