解决 Debian 12 VPS 上 DNS 自动重置的问题:一次完整的排查记录
折腾了一晚上,终于把这个烦人的 DNS 问题给解决了。写篇博客记录一下,希望能帮到遇到同样问题的朋友。
问题描述
最近在 PureVoltage 买了一台 Debian 12 的 VPS,用来跑一些服务。但是遇到了一个很奇怪的问题:网络时不时就断开。
经过排查,发现问题出在 DNS 上。每次我手动把 DNS 改成 Google DNS(8.8.8.8),网络就恢复正常。但过一段时间,DNS 又会自动变回服务商提供的 DNS(103.xxx.xxx.xxx),然后网络又挂了。
这种「改了又变回去」的情况实在太烦人了,必须找到根本原因。
第一步:确定网络管理方式
Debian 12 有好几种网络管理方式,不同的方式解决方案也不同。我们需要先搞清楚系统用的是哪种:
# 检查 systemd-networkd
systemctl status systemd-networkd
# 检查 NetworkManager
systemctl status NetworkManager
# 检查传统 networking 服务
systemctl status networking
# 检查 systemd-resolved
systemctl status systemd-resolved
# 查看 resolv.conf 是怎么管理的
ls -l /etc/resolv.conf
在我的 VPS 上,结果显示:
systemd-networkd— active (running) ✓NetworkManager— not foundnetworking— not foundsystemd-resolved— active (running) ✓/etc/resolv.conf— 是一个指向/run/systemd/resolve/resolv.conf的软链接
这说明系统使用的是 systemd-networkd + systemd-resolved 的组合。
第二步:找到 DNS 配置的来源
知道了网络管理方式后,下一步是找到 DNS 配置具体是从哪里来的:
# 检查运行时网络配置
ls -la /run/systemd/network/
# 检查 netplan 配置
cat /etc/netplan/*.yaml
# 检查 cloud-init 配置
cat /etc/cloud/cloud.cfg.d/*.cfg
# 查看当前 DNS 状态
resolvectl status
关键发现来了!在 /run/systemd/network/ 目录下有个 10-netplan-eth0.network 文件,而 netplan 的配置是由 cloud-init 自动生成的。
查看 netplan 配置文件,发现了问题所在:
network:
version: 2
ethernets:
eth0:
addresses:
- 203.0.113.100/26
- 2001:db8::100/64
gateway4: 203.0.113.1
gateway6: 2001:db8::1
match:
macaddress: aa:bb:cc:dd:ee:ff
nameservers:
addresses:
- 1.1.1.1
- 103.247.36.36 # <- 服务商的 DNS
- 103.247.37.37 # <- 服务商的 DNS
原来是 cloud-init 在每次启动时都会重新生成网络配置,把 DNS 重置为服务商默认的设置。
第三步:永久解决问题
找到根本原因后,解决方案就很清晰了:
3.1 禁用 cloud-init 的网络管理
sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg << 'EOF'
network: {config: disabled}
EOF
这会告诉 cloud-init「别管网络配置了,我自己来」。
3.2 删除 cloud-init 生成的旧配置
sudo rm /etc/netplan/50-cloud-init.yaml
3.3 创建自定义的 netplan 配置
sudo tee /etc/netplan/99-custom.yaml << 'EOF'
network:
version: 2
ethernets:
eth0:
addresses:
- 203.0.113.100/26
- 2001:db8::100/64
routes:
- to: default
via: 203.0.113.1
- to: default
via: 2001:db8::1
match:
macaddress: aa:bb:cc:dd:ee:ff
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
set-name: eth0
EOF
注意几个变化:
- 把 DNS 改成了 Google DNS
- 使用
routes替代了已废弃的gateway4和gateway6
3.4 设置正确的文件权限并应用配置
sudo chmod 600 /etc/netplan/99-custom.yaml
sudo netplan generate
sudo netplan apply
3.5 验证结果
resolvectl status eth0
输出:
Link 2 (eth0)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
DNS Servers: 8.8.8.8 8.8.4.4
完美!现在只有 Google DNS 了,不会再自动变回去。
踩过的坑
在解决这个问题的过程中,我踩了几个坑,分享出来给大家避雷:
坑一:直接改 /etc/resolv.conf
这个文件是由 systemd-resolved 动态管理的(注意它是个软链接),直接改没用,很快就会被覆盖。
坑二:只创建新配置不删除旧配置
如果不删除 50-cloud-init.yaml,两个配置文件会同时生效,DNS 服务器会被合并而不是替换。我一开始就犯了这个错误,结果 DNS 列表变成了一长串。
坑三:忘记禁用 cloud-init
如果不禁用 cloud-init 的网络管理,下次重启它又会重新生成配置文件,之前的修改全白费。
总结
这次问题的根本原因是 cloud-init 持续管理网络配置,导致我们的手动修改总是被覆盖。
解决思路:
- 先诊断系统使用的网络管理方式
- 找到配置的实际来源
- 从源头解决问题,而不是在下游修修补补
这个思路其实适用于很多 Linux 问题的排查。与其反复改一个被别的服务管理的文件,不如找到那个「管理者」,要么让它按你的意思来,要么直接让它别管。
希望这篇文章对你有帮助!如果你也遇到了类似的问题,欢迎在评论区交流。
写于深夜,解决问题后的愉悦心情无以言表。去睡觉了,晚安! ![]()