Linux 网络排障:按接口、路由、DNS、端口与 HTTP 逐层检查

排查 Linux 网络连接时,可依次检查接口与地址、路由、名称解析、传输连接和应用响应,逐层缩小范围。一次 ping 的成功或失败,都不足以证明整个互联网连接或网站服务正常。先记录故障条件,再做有证据支持的单项更改。

地址和默认路由的含义,见IP 地址、DNS、端口与连接过程。若只有 SSH 失败,还应核对SSH 连接与文件传输(英语)中的主机、端口和密钥。配置练习以常规 Ubuntu 26.04 LTS 或 Rocky Linux 9 系列虚拟机为参考;容器、WSL 和其他版本可能不同。先按虚拟机环境准备(英语)核对版本并准备控制台恢复路径。

先记录故障范围和比较条件

记录从哪台计算机、访问哪个名称或地址、哪个端口、何时开始失败,以及完整错误。比较一个网站与多个网站、一个客户端与其他客户端,并在相关时分别检查 IPv4 与 IPv6。记录 VPN、代理和刚修改过的设置,避免把不同条件下的结果当成同一问题。远程服务器重启网络前,应先有控制台或另一条管理通道。

检查接口、地址与路由

ip -brief link
ip -brief address
ip route
ip -6 route

接口标志中的 UP 表示管理上已启用,不代表能到达目的地;应结合 LOWER_UP 等链路信息、预期地址与适用路由判断。虚拟机还要检查虚拟网卡是否连接,NAT 或桥接模式是否符合预期。不要假设接口一定叫 eth0,应使用输出中的实际名称。

解析出目标的实际 IPv4 地址后,用 ip route get ACTUAL_IPV4_ADDRESS 查看所选接口、下一跳和源地址;先把占位文字换成真实地址。IPv6 则要检查对应地址族的路由。Network is unreachable 更直接指向路由问题,而非 DNS。查到一条路由也不表示下一跳或目标一定响应。

把 ping 当作一项可达性线索

ping -c 3 127.0.0.1
ping -c 3 example.com

第一条向回环地址发送互联网控制报文协议(ICMP)的 Echo 请求,第二条先解析名称,再向目标发送请求。-c 3 限制请求数量。目标或中间设备可能过滤 ICMP,即使网页可访问,ping 仍可能失败;反过来,收到回应也不能验证网站端口、证书或 HTTP 响应。只对获准的实验目标发少量请求。

区分名称解析失败与连接失败

getent ahosts example.com
curl -I -v --connect-timeout 5 --max-time 15 https://example.com/
printf "exit=%s\n" "$?"

getent 没有返回地址时,先检查系统名称服务配置;它可使用 DNS 以外的配置来源。curl 的 -v 详细输出有助于分辨地址选择、连接、TLS 握手和 HTTP 响应。-I 请求响应头;5 秒连接超时与 15 秒整体上限分别限制连接阶段和整个传输。最后一行立即读取上一条命令的退出状态,不要在中间插入其他命令。

curl 常见退出状态为:6 表示目标主机名称解析失败,7 表示连接失败,28 表示超时,60 表示对端证书无法通过信任验证。代理名称解析失败另有状态 5,应结合原始错误区分。证书问题未必能通过修改 DNS 或开放防火墙解决,也不应把关闭验证的 -k 当成修复。

默认 curl 收到 HTTP 404 或 500 后,若传输成功,仍可能返回 0。需要把 HTTP 错误算作失败时,可用 --fail,或在支持的版本上用 --fail-with-body,并分别阅读 HTTP 状态码与进程退出状态。服务器若仅拒绝 HEAD,应以 GET 或浏览器进一步确认。详细输出可能含 Cookie、头部及内部地址,分享前应遮盖。

在服务端检查监听地址和端口

ss -lnt
ss -lnu
sudo ss -lntp

ss -lnt 查看本机监听的 TCP 套接字,ss -lnu 查看相应 UDP 套接字;数字形式的端口便于比较。sudo ss -lntp 还请求显示相关进程信息,所需权限与系统配置有关。这里查询的是运行命令的服务器,不是远程目标的端口清单。

仅监听 127.0.0.1:8080 时,只能从本机直接连接。0.0.0.0:8080 覆盖 IPv4 接口;[::]:8080 是否同时接收 IPv4,要看套接字和系统设置。存在监听也不保证远程可达,仍需考虑过滤规则与路径。UDP 没有与 TCP 完全相同的连接监听语义,仅看到绑定套接字不能证明请求与响应正常。

按证据只修改一项设置

观察结果 优先检查
本地请求也失败 服务状态、配置和监听端口
本地成功,远程失败 绑定地址、主机防火墙、云安全规则
能连接,但证书验证失败 服务器名称、证书链、系统时间
收到 HTTP 错误响应 Web/应用日志与请求路径

更改前记录原值,一次只改一项,再从相同客户端向同一地址和端口重试。无效时先恢复原值,再检验另一个假设。这样可以保留比较条件,减少排障时引入第二个故障的机会。

若要在不依赖外部网站的情况下区分 HTTP 错误和连接失败,先确认实验虚拟机已安装 python3 与 curl;缺少时按发行版包管理方式安装。在一个终端运行下列服务器并保持运行。这里只将临时目录通过回环地址提供给本机实验,不用于生产服务;若 18080 已占用,应在服务器与请求中一起改成其他空闲端口。

lab=$(mktemp -d "$HOME/linux-http-check.XXXXXX") &&
python3 -m http.server 18080 --bind 127.0.0.1 --directory "$lab"

mktemp 创建独立空目录,只有创建成功才启动服务。看到启动信息后,在同一虚拟机的另一终端运行:

curl --fail --show-error --connect-timeout 2 --max-time 5 http://127.0.0.1:18080/missing-file
printf "exit=%s\n" "$?"

预期收到 HTTP 404,并由 --fail 使 curl 返回 22:说明本次 TCP 连接和 HTTP 响应已完成,但请求文件不存在。用服务器终端的 Ctrl+C 停止服务后,再从请求终端原样重试。若已没有监听者,通常返回连接失败 7;若等到超时,可能是 28。要立即读取状态,并确认没有其他程序接管相同端口。

实验结束后,在原服务器终端可用 rmdir -- "$lab" 删除此次创建的目录;仅在它仍为空时才会删除,不要改用递归删除。两个终端的变量不自动共享,所以不要在请求终端假设 $lab 已设置。

官方参考

curl 官方选项与退出状态手册解释详细输出、超时及 HTTP 错误处理;Linux 内核网络参数文档说明 IPv6 套接字与 IPv4 映射条件。命令含义可查 ip-route(8) 手册、ss(8) 手册及 ping(8) 手册;临时服务器选项见 Python http.server 官方文档。