本文记录了一次完整的Linux网络故障排查过程,问题现象:服务器能通IP却无法解析域名。通过层层递进的排查,最终定位并解决了由iptables规则冲突导致的systemd-resolved服务异常。
问题背景
我的Ubuntu服务器突然陷入了网络"孤岛"状态。一个常规的 sudo apt update
操作,却返回了满屏的错误,所有软件源都提示"暂时不能解析域名"。
root@私人ubuntu:~# apt update
忽略:1 https://mirrors.tencent.com/docker-ce/linux/ubuntu noble InRelease
错误:2 https://mirrors.tencent.com/docker-ce/linux/ubuntu noble InRelease
暂时不能解析域名"mirrors.tencent.com"
忽略:3 http://security.ubuntu.com/ubuntu noble-security InRelease
错误:4 http://security.ubuntu.com/ubuntu noble-security InRelease
暂时不能解析域名"security.ubuntu.com"
... (大量类似错误)
W: 无法下载 https://mirrors.tencent.com/... 暂时不能解析域名"mirrors.tencent.com"
W: 部分索引文件下载失败。如果忽略它们,那将转而使用旧的索引文件。
这个问题几乎瘫痪了所有依赖网络的服务。ping
命令的反馈也证实了问题的严重性:
root@私人ubuntu:~# ping mirrors.tencent.com
ping: mirrors.tencent.com: 域名解析出现暂时性错误
矛盾现象:
✅ 底层网络似乎是通的,ping 119.29.29.29
(一个公网IP) 响应正常。
❌ 但任何涉及域名解析的操作都会失败。
✅ systemd-resolved
服务状态显示 active (running)
。
❌ 系统就是无法将 mirrors.tencent.com
转换成IP地址。
排查之路:层层递进
面对这个棘手的问题,我没有急于采用"绕过式"的临时方案,而是进行了一系列由浅入深的系统性诊断。
第一步:基础状态检查
首先,确认负责DNS解析的核心服务 systemd-resolved
是否在正常工作。
root@私人ubuntu:~# systemctl status systemd-resolved
● systemd-resolved.service - Network Name Resolution
Loaded: loaded (/usr/lib/systemd/system/systemd-resolved.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-08-27 17:32:38 CST; 4min 28s ago
...
Main PID: 630 (systemd-resolve)
Status: "Processing requests..."
...
8月 28 14:37:06 私人ubuntu systemd-resolved[630]: Got packet on unexpected (i.e. non-localhost) IP range, ignoring.
分析:
Active: active (running)
: 服务进程本身是健康的,没有崩溃。- 日志中反复出现
Got packet on unexpected (i.e. non-localhost) IP range, ignoring.
。这是一个关键的异常信号,虽然服务在运行,但它似乎在拒绝处理某些请求。
第二步:验证底层网络与上游DNS
接下来,我们需要确定问题是出在DNS解析环节,还是整个服务器的网络连接都已中断。
# 测试到公网IP的连通性
root@私人ubuntu:~# ping -c 4 119.29.29.29
PING 119.29.29.29 (119.29.29.29) 56(84) bytes of data.
64 bytes from 119.29.29.29: icmp_seq=1 ttl=51 time=33.5 ms
64 bytes from 119.29.29.29: icmp_seq=2 ttl=51 time=33.7 ms
...
--- 119.29.29.29 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
分析: ping
公网IP成功,这证明服务器的物理网络、路由、防火墙出站策略都是通的。问题范围被精确地缩小到了域名解析本身。
为了进一步隔离故障点,我决定绕过本地的 systemd-resolved
,直接向公网DNS服务器发起一次域名查询。
# 使用dig工具,指定@119.29.29.29作为解析服务器
root@私人ubuntu:~# dig @119.29.29.29 mirrors.tencent.com
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22775
...
;; ANSWER SECTION:
mirrors.tencent.com. 600 IN CNAME mirrors.tencent.com.cdn.dnsv1.com.cn.
...
gyw4zcu4.sched.dma-dk.tdnsdl1.cn. 60 IN A 112.26.87.174
...
分析: 这是一个决定性的发现!dig
命令成功返回了IP地址。这证明:
- 我们的服务器可以与上游DNS服务器在53端口正常通信。
- 上游DNS服务器工作正常。
- 故障点100%被锁定在了本地的
systemd-resolved
服务上。
第三步:防火墙嫌疑排查
既然 systemd-resolved
是"中间人",会不会是防火墙 ufw
拦截了它发出的请求的响应包?
root@私人ubuntu:~# sudo ufw status
状态:激活
至 动作 来自
- -- --
443 ALLOW Anywhere
... (大量其他规则)
分析: 防火墙处于激活状态,这是一个重要的嫌疑点。尽管 conntrack
规则理应自动处理响应流量,但在复杂的网络环境下可能会失效。为了彻底排除这种可能,我添加了一条明确允许DNS响应(源端口为53的UDP包)进入的规则:
root@私人ubuntu:~# sudo ufw allow in proto udp from any port 53 to any comment 'Allow incoming DNS replies'
规则已添加
规则已添加(v6)
在执行后再次测试 ping mirrors.tencent.com
,问题依旧。这排除了防火墙 INPUT
链拦截这个常见原因,将调查推向了更深的层次。
第四步:诊断性绕过操作
为了再次确认故障点,我执行了一个临时性的"绕过"操作,让系统直接使用上游DNS,而不是通过 127.0.0.53
这个本地存根。
# 临时绕过本地127.0.0.53解析器
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
执行后,DNS解析立即恢复了正常。这再次印证了 systemd-resolved
的本地存根服务是问题的核心。但这只是一个治标不治本的"创可贴",它回避了"为什么 127.0.0.53
会失效"这个根本问题。为了根治,我将配置恢复 (sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
),继续深入。
真正的突破点,发生在我决定深入分析 systemd-resolved
的内部工作日志和实际的网络数据包之后。
关键发现:被"污染"的本地回环流量
通过开启 systemd-resolved
的调试模式和使用 tcpdump
抓包,我发现了决定性的证据。
第一步:开启 systemd-resolved
调试模式
# 1. 创建调试配置目录
sudo mkdir -p /etc/systemd/system/systemd-resolved.service.d/
# 2. 创建调试配置文件
sudo nano /etc/systemd/system/systemd-resolved.service.d/10-debug.conf
# 3. 在文件中写入以下内容并保存
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
# 4. 重载配置并重启服务
sudo systemctl daemon-reload
sudo systemctl restart systemd-resolved
第二步:联调 tcpdump
和 journalctl
我在两个终端窗口同时执行监控:
# 终端1: 抓取物理网卡enp6s18上的DNS流量
sudo tcpdump -i enp6s18 -n port 53
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp6s18, link-type EN10MB (Ethernet), snapshot length 262144 bytes
(此处一片寂静...)
# 终端2: 实时查看systemd-resolved调试日志
journalctl -u systemd-resolved -f
第三步:触发问题并分析
在终端2,我执行 ping mirrors.tencent.com
,然后观察两个窗口。
惊人的结果:
tcpdump
没有任何输出。这说明DNS查询请求从未离开服务器,问题完全出在系统内部。journalctl
输出了海量日志,但关键信息是这两行:8月28日01:43:04 私人ubuntu systemd-resolved[28290]: Received dns UDP packet of size 52, ifindex=0, ttl=64, fragsize=0, sender=192.x.x.x, destination=127.0.0.53 8月28日01:43:04 私人ubuntu systemd-resolved[28290]: Got packet on unexpected (i.e. non-localhost) IP range, ignoring.
分析:systemd-resolved
在其本地地址 127.0.0.53
上收到了一个DNS查询。但这个查询的源IP (sender) 竟然是服务器的局域网IP 192.x.x.x
,而不是它所期望的本地回环地址 127.0.0.1
。出于安全机制,systemd-resolved
认为这是一个来源异常的请求,并直接将其忽略 (ignoring)。
为了更直观地理解这个问题,请看下面的流量路径对比图:
根本原因: 系统中存在一个过于宽泛的 iptables
NAT规则,它错误地对发往本地回环地址的流量进行了源地址转换(SNAT/MASQUERADE),导致 systemd-resolved
拒绝处理这些被"污染"的请求。
终极解决方案
通过 sudo iptables -t nat -S
,我定位到元凶是宝塔面板(BT Panel)创建的 POSTROUTING_BT
链中的一条 MASQUERADE
规则。修复方案是在这条规则生效前,为本地回环流量添加一条"豁免"规则。
第一步:检查目标 iptables
链
root@私人ubuntu:~# sudo iptables -t nat -L POSTROUTING_BT --line-numbers
Chain POSTROUTING_BT (1 references)
num target prot opt source destination
1 MASQUERADE all -- anywhere anywhere
确认 MASQUERADE
规则存在且在第一位。
第二步:插入豁免规则
# 在POSTROUTING_BT链的顶端插入一条规则:
# 如果数据包的出口是lo(本地回环接口),就RETURN(停止处理)
root@私人ubuntu:~# sudo iptables -t nat -I POSTROUTING_BT 1 -o lo -j RETURN
第三步:验证修复
# 再次检查规则,确认豁免规则已在第一位
root@私人ubuntu:~# sudo iptables -t nat -L POSTROUTING_BT --line-numbers
Chain POSTROUTING_BT (1 references)
num target prot opt source destination
1 RETURN all -- anywhere anywhere -o lo
2 MASQUERADE all -- anywhere anywhere
# 最终测试
root@私人ubuntu:~# ping mirrors.tencent.com
PING mirrors.tencent.com (2409:8c1e:a920:3008:3e::4) 56 data bytes
64 bytes from 2409:8c1e:a920:3008:3e::4: icmp_seq=1 ttl=55 time=39.9 ms
...
--- mirrors.tencent.com ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19214ms
rtt min/avg/max/mdev = 39.543/41.263/56.354/3.578 ms
DNS解析立即恢复正常!
经验总结
- 别放过异常日志:最初
systemd-resolved
状态中Got packet on unexpected ... IP range
这条日志就是关键线索,但很容易被忽略。 - 联调是王道:单一工具可能无法揭示真相。
journalctl
(内部视角)和tcpdump
(外部视角)的结合,是定位复杂网络问题的利器。 - 警惕自动化工具的"副作用":宝塔面板等工具在提供便利的同时,其对系统底层的修改(如
iptables
)可能与系统默认行为冲突,成为难以排查的"深水炸弹"。 - 理解比修复更重要:通过这次排查,我不仅修复了问题,更深入理解了Ubuntu的网络解析流程、
systemd-resolved
的安全机制以及iptables
NAT 的工作原理。
致谢:感谢开源社区和各大技术论坛的知识分享。希望这篇详尽的排错记录,能够帮助每一位被"域名解析暂时性失败"困扰的Linux用户,节省数小时甚至数天的宝贵时间!