想通过这篇文章介绍下主流的 Linux 发行版的 DNS 配置相关知识,和怎么手动修改 DNS 并持久化配置。这里我以 Debian 和 Ubuntu 为例大概说一下原理,为什么偶尔发现手动修改 DNS 后又被覆写或还原,怎么检查和解决。
起初是因为瓦工内网提供了 DNS 解锁 ChatGPT 的,但偶尔还是看到瓦工群里有人问只能网页访问 ChatGPT,手机 App 还是被阻止访问。帮一两个群友看过之后发现情况都类似,是因为访问 ChatGPT 并没有走瓦工解锁的 DNS。我自己常用 Ubuntu,所以知道 Ubuntu 镜像中的设置是有一点缺陷的。
太长不看版,强制修改DNS记录并设为只读
Linux 的 DNS 查询最终是需要读取 /etc/resolv.conf 的,所以可以强制修改并锁定。
删除原 DNS 记录:
rm /etc/resolv.conf
写入新 DNS 记录:
bash -c 'echo -e "nameserver 172.31.255.2
nameserver 8.8.8.8
nameserver 1.1.1.1" > /etc/resolv.conf'
把 DNS 记录设为只读:
chattr i /etc/resolv.conf
解除 DNS 的只读属性(设为只读后如果需要修改/删除时才使用):
chattr -i /etc/resolv.conf
文件增加只读属性后,每次需要修改/删除时需要先解除只读属性,修改完成后需要再次设为只读,以防被覆盖。
Ubuntu
瓦工的 Ubuntu 镜像中,默认 DNS 解析是交给 systed-resolved 来管理的,如果使用 ls -l /etc/resolv.conf 来查看,可以发现这个文件其实是 systemd-resolved 自己生成的配置文件的软链接,类似于 Win 上的快捷方式,因此直接编辑 /etc/resolv.conf 后每当服务或者机器重启,该配置会被 systemd-resovled 重新生成并覆盖。
查看 DNS 设置和使用情况
先查询访问 ChatGPT 时返回的结果是什么:
resolvectl query chatgpt.com
结果示例:
chatgpt.com: 104.18.32.47 -- link: eth0
172.64.155.209 -- link: eth0
2606 : 4700 : 4400 :: 6812 : 202f -- link: eth0
2606 : 4700 : 4400 :: ac40 : 9bd1 -- link: eth0
像这种结果返回的就是 ChatGPT 的真实 IP,而非瓦工自家的解锁 DNS IP,也就是说,访问 ChatGPT 并没有走瓦工的代理,如果自己机器的 IP 又被阻止了,也就无法使用了。
我们希望的结果应该如下:
chatgpt.com: 172.31.255.2 -- link: eth0
172.31.255.2 就是瓦工用来解锁的内网 DNS IP,也就是瓦工自己的代理。
修改 DNS 设置
使用编辑器打开 /etc/systemd/resolved.conf,找到 DNS、FallbackDNS 和 DNSStubListener 三个选项,删掉前面的 # 注释符,并指定主 DNS 为瓦工内网 DNS IP,备用 DNS 指定为 Google 和 Cloudflare 的 IP,并取消 systemd-resolved 监听和充当本地 DNS,也就是让本机的 DNS 统一走上面设置的主 DNS 和备用 DNS
... 其他配置 ...
[Resolve]
... 其他配置 ...
DNS=172.31.255.2
FallbackDNS=8.8.8.8 1.1.1.1
DNSStubListener=no
... 其他配置 ...
保存并重启服务:
命令:
systemctl restart systemd-resolved
之后就会优先使用瓦工内网的解锁 DNS 了,可以再次使用 resolvectl query chatgpt.com 来验证。
Debian
瓦工的 Debian 镜像则使用了 DHClient 来管理,对于 Debian 用户通常来说不会有问题,因为你的机器会使用 DHCP 的方式自动获取到。这里我们可以通过查看 /etc/resolv.conf 来看,默认 172.31.255.2 的内网 DNS 是在第一行的。
而 /etc/resolv.conf 默认由 DHClient 来管理,可以在 /var/lib/dhcp/dhclient.eth0.leases 查看瓦工提供的默认配置。
但我们仍希望能够明确配置,让系统优先使用内网解锁 DNS,另外对于希望手动更改 /etc/resolv.conf 而苦于配置被覆盖的用户来说,也需要修改 DHClient 的配置。理论上我们不应该去修改 /var/ 目录中的配置,而是在 /etc/ 中统一对配置进行管理,因此稍后我们会修改 /etc/dhcp/dhclient.conf
查看 DNS 使用情况
由于瓦工 Debian 默认没有提供 systemd-resovled 这样的组件,首先需要安装 dnsutils 工具:
apt install dnsutils
查询访问 chatgpt.com 时的 DNS 结果:
nslookup chatgpt.com
结果示例:
Server: 172.31.255.2
Address: 172.31.255.2#53
Name: chatgpt.com
Address: 172.31.255.2
如果这里不是 172.31.255.2 则说明默认没有使用内网 DNS,或者内网 DNS 解析失败了而使用了备用 DNS。
修改 DHClient 配置
刚刚也讲了,瓦工默认的 DNS 设置其实已经是正确的。和接下来要做的事是一样的。不过对于希望手动修改其他 DNS,且不会被覆盖的用户来说是有用的。
使用编辑器打开 /etc/dhcp/dhclient.conf,并找到 #prepend domain-name-servers 127.0.0.1 这行,取消 # 注释并更改 IP 为 172.31.255.2,然后保存,或者你可以直接复制 prepend domain-name-servers 172.31.255.2; 直接粘贴,来确保只使用内网 DNS,而为了保险起见,还是建议使用 prepend domain-name-servers 172.31.255.2 8.8.8.8 1.1.1.1;这样系统的 DNS 请求会根据顺序进行,只有前者失败才会请求后面的 DNS。如果你希望修改为其他的 DNS,可以自行更换。
示例:
... 其他配置 ...
prepend domain-name-servers 172.31.255.2 8.8.8.8 1.1.1.1;
... 其他配置 ...
之后重新加载 DHClient 配置并重新获取/覆写 DNS 记录到 /etc/resolv.conf:
dhclient -r
dhclient
如果发现 /etc/resolv.conf 的配置和 /etc/dhcp/dhclient.conf 中的配置不同,可以先删除 /var/lib/dhcp/ 中自动获取的旧的 DHClient 租约配置,可以理解为配置的缓存。然后重新使用上面的命令重载 DHClient 配置并生成 /etc/resolv.conf
rm -r /var/lib/dhcp/dhclient*
之后可以使用前面介绍的 nslookup chatgpt.com 来重新验证你的 DNS 设置是否正确生效。nslookup 命令对于其他 Linux 发行版同样有效,如果系统没有 systemd-resolved 的都可以通过 nslookup 来查看 DNS 解析情况。
总结
其实主要就是介绍怎么持久化手动修改的 DNS 记录,让手动配置的 DNS 不会被覆盖,大概说了一下原理。
另外说一下,对于非 Debian/Ubuntu 的发行版,默认的包管理器可能不是 apt,有可能是 dnf 或者 pacman 。另外如果你的发行版没有使用 systemd-resolved,或者 dhclient,也可能是使用 NetworkManager 这种常见于桌面环境的发行版的网络管理器。为了使修改 /etc/resolv.conf 可以生效,还是需要先了解自己的系统上,resolv.conf 是否被某个服务接管了才行。
欢迎评论区指正,同样如果有没讲清楚的地方也欢迎评论区提问和补充,我会根据情况继续完善这篇文章。

好文bd
好帖,解iPhone的gpt吗?
有使用 openresolv 的小伙伴也可以参考这个