网络诊断工具箱:从 ping 到抓包的分层排障

系统整理网络排障工具:分层排障方法论、ping/mtr/traceroute 连通性、dig 与 DNS 解析链路、ss/netstat/lsof 端口连接、tcpdump/tshark 抓包分析、curl/wrk 应用层调试、延迟丢包定位、带宽测量,以及典型故障的排障剧本与速查命令。

引言

“服务连不上"这五个字背后可能是 DNS 解析失败、端口没监听、防火墙拦截、TLS 握手失败、路由黑洞或应用层 500——没有分层方法,就只能在瞎猜里打转。本文给一套自上而下又自下而上的排障工具箱:先用 ping/mtr/traceroute 确认"路通不通”,用 dig 确认"名字能不能解析",用 ss/lsof 确认"端口开没开",用 tcpdump 确认"包到底发没发、回没回",最后用 curl 落到应用层。每一层都有对应的命令,按层排查就不会漏。

前置:curl 与 HTTP 调试实战、HTTP 状态码与请求语义速查。终端工作流见 终端与 Shell 生态进阶。


目录


1. 分层排障:从物理层到应用层

核心方法:把"连不上"分解成可独立验证的层,逐层证伪。

层问题工具
链路/物理网卡、网线、Wi-Fiip link、ethtool
网络/IP路由、可达性ping、mtr、ip route
传输/TCP端口、握手、连接ss、nc、tcpdump
名字/DNS解析dig、host、nslookup
应用/HTTP请求响应curl、wrk
TLS证书、握手openssl s_client、curl -v

第一个问题永远是:“从哪台机器、到哪台机器、用哪个协议、哪个端口”——不定义"源→目的→端口",任何工具都是乱枪打鸟。两种顺序:自下而上(链路 → IP → TCP → DNS → 应用,逐层确认)或自上而下(先 curl 看报错 → 按报错反推哪层)。

一张决策图:

curl 报 "Could not resolve host"  → DNS 层(第 3 节)
curl 报 "Connection refused"      → TCP 层,端口没监听(第 4 节)
curl 报 "Connection timed out"    → 路由/防火墙(第 2、5 节)
curl 报 TLS 错误                  → 证书/时间(第 6 节)
curl 卡住无响应                   → 抓包看包到没到(第 5 节)

记忆:排障先定义"源→目的→端口",再分层证伪——报错信息本身就指明了哪一层。


2. 连通性:ping、mtr 与 traceroute

ping 是最基础的 ICMP 探测:

ping -c 4 example.com          # 发 4 个包
ping -i 0.2 -c 100 host        # 间隔 0.2s 发 100 个
ping -s 1400 -M do host        # 探测 MTU(不分片)

ping 通了不代表服务可用:ICMP 可能被放行而 TCP 端口被封;ping 不通也不代表服务不可用(很多云环境禁 ICMP)。所以 ping 只用来判断"IP 层可达性",不是服务可用性。

mtr = ping + traceroute 的持续版,逐跳看丢包与延迟,是排障首选:

mtr -rwzc 100 example.com      # -r 报告 -w 宽输出 -z ASN -c 100 次
mtr -t -P 443 example.com      # TCP 模式(穿透只放行 443 的防火墙)

mtr 输出关键看两列:Loss%(丢包率)与 Avg(平均延迟)。中间跳丢包但后续跳不丢,通常是该跳路由器不响应 ICMP(限速),不是真丢包——只有"最后一跳丢包"才是真问题。

解读 mtr:
  第 3 跳 Loss 20%,第 4 跳起 Loss 0%  → 第 3 跳限速 ICMP,非真丢包
  最后一跳 Loss 5%                      → 真丢包,网络问题
  延迟逐跳 +5ms                         → 正常累积
  某跳延迟突然 +200ms                   → 该跳有拥塞/绕路

traceroute 显示路径:

traceroute -T -p 443 example.com    # TCP 模式(默认 UDP 常被拦)
traceroute -I example.com           # ICMP 模式

常见结论:路径在某一跳后中断 → 该处有防火墙/路由黑洞;路径绕远 → BGP 路由问题(找云厂商)。

记忆:ping 只证 IP 层可达(不通≠服务不可用)、mtr 逐跳看丢包延迟、中间跳丢包≠真丢包(限速 ICMP),只有末跳丢才是问题。


3. DNS 诊断:dig、host 与解析链路

DNS 是"连不上"的头号嫌疑。dig 是最完整的诊断工具:

dig example.com                 # 默认 A 记录
dig example.com +short          # 只出结果
dig example.com AAAA            # IPv6
dig example.com MX              # 邮件
dig @8.8.8.8 example.com        # 指定 DNS 服务器
dig +trace example.com          # 从根开始逐级追踪
dig +norecurse @a.gtld-servers.net example.com   # 问权威

关键字段:

字段含义
status: NOERROR解析成功
status: NXDOMAIN域名不存在
status: SERVFAIL服务器解析失败(上游问题)
ANSWER SECTION结果记录
TTL缓存存活时间
flags: qr rd ra响应、递归、可用递归

排查顺序:先 dig +short 看有无结果;没有则 dig @8.8.8.8 换个 DNS 对比(有则本地 DNS 问题,没有则域名/权威问题);有结果但连不上说明不是 DNS,去 TCP 层;怀疑缓存用 dig +trace 看真实解析链;内网域名检查 search domain 与 /etc/hosts。

/etc/hosts 优先级:/etc/nsswitch.conf 决定查询顺序,通常 files dns——hosts 文件优先于 DNS,本地调试常改这里。

cat /etc/resolv.conf            # 看用了哪些 DNS 服务器
cat /etc/nsswitch.conf | grep hosts   # 看解析顺序
getent hosts example.com        # 按系统实际顺序解析(比 dig 更贴近应用行为)

getent 比 dig 更准:dig 只问 DNS,getent hosts 走完整的 nsswitch 链路(含 hosts 文件、mDNS)——应用实际用的就是 getent 的路径。

记忆:连不上先查 DNS——dig +short 看结果、@8.8.8.8 对比、+trace 追链路;getent hosts 才反映应用的真实解析路径。


4. 端口与连接:ss、netstat 与 lsof

确认"服务到底有没有在听":

ss -tlnp                    # TCP 监听端口 + 进程(-t TCP -l listen -n 数字 -p 进程)
ss -tlnp 'sport = :8080'    # 只看 8080
ss -tanp                    # 所有 TCP 连接(含 ESTABLISHED)
ss -s                       # 汇总统计

ss 已取代 netstat(更快、信息更全)。netstat 仍可用但需 net-tools 包:

netstat -tlnp               # 同 ss -tlnp
netstat -an | grep 8080

常见状态解读:

状态含义
LISTEN在监听(服务已起)
ESTABLISHED已连接
TIME_WAIT主动关闭后等待(正常,量大说明短连接多)
CLOSE_WAIT被动关闭未处理(应用 bug:没 close)
SYN_RECV收到 SYN 未完成握手(可能 SYN flood 或半开)
FIN_WAIT2等对端 FIN

CLOSE_WAIT 堆积是经典事故:说明应用收到 FIN 后没调用 close()——连接泄漏。TIME_WAIT 堆积则是短连接过多,可调内核参数或改用连接池。

# 统计各状态连接数
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

lsof 查"哪个进程占了端口":

lsof -i :8080               # 谁在用 8080
lsof -i -P -n | grep LISTEN # 所有监听
lsof -p 12345               # 某进程打开的所有文件/连接

nc(netcat)测端口连通性(比 telnet 更可靠):

nc -zv host 443             # 测 TCP 443 通不通
nc -zvu host 53             # 测 UDP 53
nc -l 8080                  # 本地监听测试

判断"连不上"是网络还是服务:nc -zv 通 → 服务在,问题在应用层;不通 → 端口没监听或被防火墙拦。

记忆:ss -tlnp 看监听、ss -tanp 看连接——CLOSE_WAIT 堆积是应用没 close 的 bug,TIME_WAIT 多是短连接太多。


5. 抓包:tcpdump 与 tshark

抓包是"看真相"的终极手段——日志会说谎,包不会。

sudo tcpdump -i eth0 -nn port 443                    # 抓 443
sudo tcpdump -i any -nn host 10.0.0.5 and port 8080  # 指定主机+端口
sudo tcpdump -i eth0 -nn -w /tmp/cap.pcap port 443   # 写文件供分析
sudo tcpdump -i eth0 -nn -A port 80 | grep -i host   # 看 ASCII 内容
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'  # 只看 SYN

关键参数:

参数含义
-i any所有网卡
-nn不解析主机名/端口名(快、准)
-w file写 pcap 文件
-r file读 pcap 文件
-c N抓 N 个包后停
-s 0抓完整包(不截断)
-A / -XASCII / hex+ASCII 显示

BPF 过滤表达式(抓包前过滤,省资源):

host 10.0.0.5                 # 某主机
net 10.0.0.0/24               # 某网段
port 443                      # 某端口
src port 53 or dst port 53    # DNS
tcp and not port 22           # 排除 SSH
tcp[tcpflags] & (tcp-syn) != 0  # 只看 SYN

三大经典抓包结论:

1. 只看到 SYN、没有 SYN-ACK   → 对端没响应/被防火墙丢(连接超时)
2. 看到 SYN、回 RST           → 对端端口没监听(连接拒绝)
3. 看到 SYN、SYN-ACK,无 ACK  → 客户端没完成握手(客户端侧问题)

tshark(Wireshark 命令行版)做深度分析:

tshark -r cap.pcap -Y 'http.request' -T fields -e http.host -e http.request.uri
tshark -r cap.pcap -z io,phs          # 协议分层统计
tshark -r cap.pcap -Y 'tcp.analysis.retransmission'   # 只看重传

抓包权限与性能:需要 CAP_NET_RAW(root 或 capability);高流量下 -w 直接落盘比 -A 打印快得多;生产抓包务必加过滤 + 限包数 + 落盘,别把磁盘写满。

记忆:抓包看真相——SYN 无响应是超时、回 RST 是端口没开、无 ACK 是客户端问题;生产抓包必加过滤、限包数、落盘。


6. HTTP 调试:curl 与 wrk

curl 是应用层的瑞士军刀,-v 看全流程:

curl -v https://example.com                 # 完整握手 + 请求响应
curl -v --trace-time https://example.com    # 带时间戳
curl -o /dev/null -s -w 'dns=%{time_namelookup} conn=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.com

-w 的时间分解是定位"慢在哪层"的关键:

time_namelookup    DNS 耗时
time_connect       TCP 握手耗时(= connect - namelookup)
time_appconnect    TLS 握手耗时(= appconnect - connect)
time_starttransfer 首字节 TTFB(= starttransfer - appconnect,含服务处理)
time_total         总耗时

诊断套路:DNS 占比高 → 查 DNS;connect 高 → 网络/路由;appconnect 高 → TLS/证书;TTFB 高 → 服务端处理慢。常用附加参数:curl -k(跳过证书校验,仅调试)、curl --resolve example.com:443:1.2.3.4(强制指定 IP,绕过 DNS 排障神器)、curl -x http://proxy:8080(走代理)、curl --http2 -v(强制 HTTP/2)。

TLS 诊断用 openssl:

openssl s_client -connect example.com:443 -servername example.com
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

看证书有效期、链、SNI 是否正确——证书过期是"突然连不上"的高频原因。

wrk 做压测:

wrk -t4 -c100 -d30s https://example.com    # 4 线程 100 连接 30 秒
wrk -t4 -c100 -d30s --latency https://example.com   # 带延迟分布

看 Requests/sec、延迟分位(p50/p99)——注意压测机自身的网络与 CPU 别成瓶颈。

记忆:curl -w 的时间分解定位慢在哪层(DNS/TCP/TLS/TTFB);–resolve 绕过 DNS、openssl s_client 查证书、wrk 看吞吐延迟分布。


7. 延迟与丢包定位

延迟高 vs 丢包是两类问题:

延迟高 → 路径绕远、拥塞、处理慢
丢包   → 链路质量、拥塞丢包、缓冲区溢出

定位流程:

1. mtr 逐跳:定位延迟/丢包出现在哪一跳
2. 末跳丢包 → 目标侧或最后一段链路
3. 中间跳丢包但后续正常 → ICMP 限速,忽略
4. 延迟抖动大 → 拥塞,看是否有队列/带宽瓶颈
5. 应用延迟高但网络正常 → 回到应用层(curl -w TTFB)

TCP 层面的延迟线索(tshark):tcp.analysis.retransmission 是重传(丢包信号)、tcp.analysis.zero_window 是零窗口(接收方处理不过来)、-z io,stat,1 看每秒流量。重传 = 丢包;零窗口 = 应用读得慢(接收缓冲满);窗口小 = 带宽延迟积利用不足。

延迟的物理下限:光速。跨太平洋单程约 60–80ms,任何"跨洋 RTT < 100ms"的承诺都要怀疑。CDN/边缘节点就是把内容搬到离用户近的地方。

记忆:mtr 定位延迟/丢包在哪一跳(中间跳丢包多为限速)、tshark 看重传/零窗口——重传是丢包、零窗口是应用读得慢,延迟有光速下限。


8. 带宽与吞吐测量

带宽测量:

iperf3 -s                      # 服务端
iperf3 -c server -t 30         # 客户端,30 秒
iperf3 -c server -u -b 100M    # UDP 100Mbps
iperf3 -c server -P 4          # 4 条并行流

iperf3 的结果才是"链路真实带宽"——比用 curl 下大文件准(排除磁盘/应用影响)。

注意:单条 TCP 流的吞吐受**带宽延迟积(BDP)**限制:

吞吐上限 ≈ 窗口大小 / RTT
例:窗口 64KB、RTT 100ms → 64KB/0.1s ≈ 5.2Mbps(远低于链路带宽)
解决:调大窗口(net.ipv4.tcp_rmem/wmem)或开 BBR 拥塞控制

所以"千兆链路单流只跑 5Mbps"是正常的——需要并行流或调窗口。

测速别用错工具:链路带宽用 iperf3、HTTP 吞吐用 wrk/ab、下载速度用 curl + 大文件、磁盘 vs 网络瓶颈用 dd + 管道。

本地带宽验证:ip -s link 看网卡计数(RX/TX bytes、errors、dropped)——errors/dropped 非零说明链路或缓冲有问题;ethtool eth0 | grep -i speed 看协商速率。

记忆:iperf3 测链路带宽、单流吞吐受 BDP 限制(窗口/RTT)、网卡 errors/dropped 非零是链路信号。


9. 典型故障的排障剧本

剧本 A:服务连不上——curl -v 看报错类型;Could not resolve 查 DNS(dig/getent);Connection refused 用 ss -tlnp 看服务起没起;Connection timed out 用 mtr 看路径、nc -zv 测端口;TLS 错误用 openssl s_client 看证书/时间;卡住无响应用 tcpdump 看包到没到、有没有回。

剧本 B:服务变慢——curl -w 时间分解定位 DNS/TCP/TLS/TTFB 哪层慢;TTFB 高是应用层(查日志、DB、下游);connect 高用 mtr 看网络路径;偶发慢用 tcpdump/tshark 看重传、零窗口;全站慢查负载均衡/网关/DNS。

剧本 C:间歇性失败——先确认"间歇"的规律(时间点?特定客户端?特定后端?);ss -s 看连接状态分布(TIME_WAIT/CLOSE_WAIT 堆积?);抓包对比"成功"与"失败"请求的差异;多后端时用 curl --resolve 逐个直连测试;最后查负载均衡健康检查与超时配置。

剧本 D:DNS 相关——getent hosts 看应用实际解析结果;dig @8.8.8.8 对比判断是否本地 DNS 问题;dig +trace 查权威链路;检查 /etc/resolv.conf、search domain、/etc/hosts;容器环境检查容器 DNS(127.0.0.11 / CoreDNS)。

通用原则:先复现、再缩小范围、后定位;每次只改一个变量;记录时间点(便于对齐多机日志)。

记忆:排障剧本=复现→缩小→定位——先看报错类型定层,再逐层证伪;多后端逐个直连、成功/失败对比抓包、每次只改一个变量。


10. 速查表与一句话记忆

全篇速查:

层命令看什么
IP 可达ping、mtr -rwzc 100丢包率、逐跳延迟
路径traceroute -T -p 443在哪跳中断
DNSdig +short、dig @8.8.8.8、getent hosts解析结果、真实链路
监听ss -tlnp端口开没开、哪个进程
连接ss -tanp、ss -s状态分布、CLOSE_WAIT
端口通断nc -zv host 443通不通
抓包tcpdump -i any -nn port XSYN/RST/重传
深度分析tshark -Y、-z io,phs重传、零窗口
HTTPcurl -v -w各阶段耗时
TLSopenssl s_client证书、链、时间
带宽iperf3 -c链路真实带宽
压测wrk -t4 -c100 -d30s --latencyQPS、延迟分位

一句话记忆:网络排障先定义"源→目的→端口",再分层证伪——ping/mtr 证 IP 层(中间跳丢包多为 ICMP 限速,只有末跳丢才是问题)、dig/getent 证 DNS(getent 才反映应用真实路径)、ss -tlnp 证监听(CLOSE_WAIT 堆积是应用没 close 的 bug)、nc -zv 证端口、tcpdump 看真相(SYN 无响应是超时、回 RST 是端口没开、无 ACK 是客户端问题)、curl -w 时间分解定位应用层慢在哪(DNS/TCP/TLS/TTFB);报错信息本身就指明哪一层——先复现、再缩小、后定位,每次只改一个变量。


延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「others」更多文章

  1. Git 内部原理:对象、引用与 packfile 的底层机制
  2. 列式数据格式:Parquet、ORC 与 Arrow 的原理与选型
  3. 状态机设计:从状态转移表到分层状态图