网络排查工具链
1. 概念与原理
服务器上排查网络问题,前端最常遇到的就是这几类:
- 浏览器报
ERR_CONNECTION_REFUSED/ERR_CONNECTION_TIMED_OUT - API 间歇性超时
- DNS 解析慢或不解析
- Nginx 反代到上游 502/504
- 服务起了但端口连不上
这一篇覆盖 curl、dig、nslookup、ss、netstat、tcpdump、nc、traceroute、mtr 九大工具,按"我要做什么"组织。
2. curl — HTTP 排查瑞士军刀
2.1 基本用法
curl https://example.com # GET,输出 body
curl -I https://example.com # 只看响应头(HEAD)
curl -i https://example.com # 响应头 + body
curl -v https://example.com # 详细过程(含 TLS 握手)
curl -L https://example.com # 跟随 301/302 跳转
curl -o file.html https://example.com # 保存到文件
curl -s https://example.com # 静默(脚本里用)
2.2 POST / PUT / DELETE
curl -X POST https://api/login \
-H "Content-Type: application/json" \
-d '{"user":"alice","pwd":"x"}'
# form-data
curl -X POST -F "file=@./data.json" -F "name=alice" https://api/upload
# 从文件读 body
curl -X POST -d @payload.json -H "Content-Type: application/json" https://api/x
2.3 调试代理 / DNS / IP
# 跳过 DNS,强制解析到指定 IP(测试灰度发布、调试 CDN 节点超有用)
curl --resolve example.com:443:1.2.3.4 https://example.com
# 指定 HTTP 代理
curl -x http://proxy:8080 https://example.com
# 指定 SOCKS5 代理
curl --socks5 127.0.0.1:1080 https://example.com
# 指定网卡
curl --interface eth1 https://example.com
# 强制 HTTP/2 / HTTP/3
curl --http2 https://example.com
curl --http3 https://example.com # 需要 curl 编译时含 HTTP/3 支持
2.4 性能分时分析(前端必学)
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\n请求发送: %{time_pretransfer}s\n首字节: %{time_starttransfer}s\n总时长: %{time_total}s\n" \
https://example.com
输出:
DNS: 0.012345s
TCP: 0.034567s
TLS: 0.089012s
请求发送: 0.090234s
首字节: 0.245678s
总时长: 0.250000s
含义:
time_namelookup— DNS 解析耗时time_connect— TCP 三次握手完成(含 DNS)time_appconnect— TLS 握手完成time_starttransfer— 收到首字节(TTFB,服务端处理 + 网络 RTT)time_total— 全部完成
排查"网站慢"时,先用这条命令分段定位慢在哪里:
- DNS 慢 → 换 DNS 或加缓存
- TCP 慢 → 网络丢包或服务器距离远
- TLS 慢 → 证书链长或 TLS 版本低
- TTFB 慢 → 服务端慢
保存为 ~/.curl-format 复用:
echo 'time_namelookup: %{time_namelookup}s\n... ' > ~/.curl-format
curl -w "@$HOME/.curl-format" -o /dev/null -s https://example.com
2.5 调试 HTTPS / 证书
# 看证书详情
curl -v https://example.com 2>&1 | grep -i "subject\|issuer\|expire"
# 强制不验证(测试用,绝不能在生产代码)
curl -k https://self-signed.example.com
# 指定 CA
curl --cacert /path/to/ca.crt https://example.com
# 看 TLS 版本
curl --tlsv1.2 -v https://example.com
3. DNS 工具
3.1 dig — 推荐
dig example.com # A 记录
dig example.com AAAA # IPv6
dig example.com MX # 邮件
dig example.com NS # 域名服务器
dig example.com CNAME # 别名
dig example.com TXT # SPF/验证 TXT
dig example.com ANY # 所有类型(很多 DNS 已不支持)
# 指定 DNS 服务器
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com
# 看完整解析过程(含递归路径)
dig +trace example.com
# 短输出
dig +short example.com
输出关键部分:
;; ANSWER SECTION:
example.com. 300 IN A 93.184.216.34
;; ^TTL
TTL 决定 DNS 缓存多久。CDN 切换流量、域名迁移前应把 TTL 调小(如 60 秒)。
3.2 nslookup — 兼容
nslookup example.com
nslookup example.com 8.8.8.8
老工具,输出格式不友好,能用 dig 就用 dig。
3.3 host
host example.com
host -t MX example.com
输出最简洁,脚本里用。
3.4 实战:DNS 污染 / 不一致
国内 DNS 经常返回不同结果。对比验证:
for dns in 114.114.114.114 223.5.5.5 8.8.8.8 1.1.1.1; do
echo "=== $dns ==="
dig @$dns +short example.com
done
DNS 解析超时(5s+)的常见原因:
- DNS 服务器 down,换
/etc/resolv.conf里的 nameserver - 网络限制(防火墙拦 53 端口 UDP)
- /etc/hosts 有错误条目
排查 systemd-resolved:
systemd-resolve --status
resolvectl query example.com # 新版命令
4. 端口与连接工具
4.1 ss — 替代 netstat
netstat 在新发行版被 deprecated,全面用 ss。
ss -tnlp # TCP / 数字端口 / Listen / 进程
# State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
# LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
ss -tunlp # TCP + UDP
ss -tn # 所有 TCP 连接(含 ESTABLISHED)
ss -tn state established # 只看已建立
ss -s # 总览统计
# 看某端口的连接数
ss -tn | grep :80 | wc -l
# 看某 IP 来的连接
ss -tn dst 1.2.3.4
ss -tn src 1.2.3.4
# 看处于 TIME_WAIT 的连接
ss -tn state time-wait | wc -l
netstat 兼容写法:
netstat -tnlp
netstat -anp | grep :3000
4.2 排查"端口被占用"
# 端口 3000 被谁占
ss -tnlp | grep :3000
# 或
lsof -i :3000
# 或
fuser 3000/tcp
fuser -k 3000/tcp # 直接杀掉占用进程
4.3 lsof — 万能
lsof -i # 所有网络连接
lsof -i :80 # 80 端口
lsof -i tcp:443 # 443 TCP
lsof -i @1.2.3.4 # 与某 IP 的连接
lsof -p <pid> # 进程打开的所有 fd(含文件、socket)
lsof -u nginx # 某用户打开的所有 fd
lsof +D /var/www # 谁在用这个目录(umount 前必查)
5. nc / ncat — 测试 TCP/UDP 连通
# 测试 TCP 端口通不通
nc -zv example.com 443
# Connection to example.com 443 port [tcp/https] succeeded!
# 测试 UDP(要服务端配合)
nc -zuv example.com 53
# 简易 TCP 监听(调试用)
nc -lk 8080 # 监听 8080,看任何客户端发什么过来
# 简易 HTTP 请求
echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc example.com 80
# 端口转发(临时用)
nc -lk 8080 -c "nc backend 9090"
nc -zv 是排查"连接被拒"最简的命令。Connection refused 表示对方机器拒绝(端口没监听或防火墙 reject),Connection timed out 表示包发出去没回应(防火墙 drop 或对方机器不可达)。这是排查思路的分水岭。
6. ping / traceroute / mtr
6.1 ping — 不只是测连通
ping example.com
ping -c 10 example.com # 发 10 个
ping -i 0.2 example.com # 200ms 间隔(需 root)
ping -s 1400 example.com # 包大小,测 MTU
ping -M do -s 1500 example.com # 不分片,测 MTU 上限
ping 包大量丢失 = 网络丢包,需进一步 traceroute / mtr 定位。但很多生产环境 ICMP 被防火墙禁,ping 不通不代表服务不通,要用 nc -zv 测 TCP。
6.2 traceroute — 看路径
traceroute example.com
traceroute -T -p 443 example.com # TCP traceroute,绕过 ICMP 封锁
输出每一跳的 IP 和延迟。某一跳后开始 * * * 表示该跳屏蔽了 ICMP(不一定有问题),延迟突增表示该跳网络拥堵。
6.3 mtr — traceroute + ping 合体
mtr example.com
mtr -r -c 100 example.com # 报告模式,跑 100 个包
mtr -T -P 443 example.com # TCP 模式
mtr 实时显示每一跳的丢包率和延迟,是排查"网站偶尔慢"最有用的工具。输出里某一跳 Loss% 持续高 = 该跳线路有问题,可以截图给运营商投诉。
7. tcpdump — 抓包
到了 tcpdump 这一层,说明前面工具都不够用,要看原始包了。
7.1 基本用法
# 抓 80 端口流量到屏幕
tcpdump -i any -nn port 80
# 抓 80 端口到文件,给 Wireshark 分析
tcpdump -i any -nn port 80 -w /tmp/cap.pcap
# 抓特定主机
tcpdump -i any -nn host 1.2.3.4
tcpdump -i any -nn host 1.2.3.4 and port 443
# 抓 HTTP 请求行
tcpdump -i any -nn -A 'port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
# 抓出方向、入方向
tcpdump -i any -nn 'src host 1.2.3.4'
tcpdump -i any -nn 'dst host 1.2.3.4'
# 抓 DNS
tcpdump -i any -nn port 53
常用参数:
-i any所有网卡,-i eth0指定网卡-nn不解析 DNS 和端口名(快很多)-w file.pcap保存-r file.pcap读文件-AASCII 显示 payload-X十六进制 + ASCII-c 100抓 100 个包就停
7.2 实战场景
前端到后端 502,要看到底是 Nginx 没发包还是后端没回:
# 在 Nginx 机器抓到后端的包
tcpdump -i any -nn -w /tmp/upstream.pcap host <backend-ip> and port 8080
# 触发问题,停止抓包,Wireshark 打开看
API 间歇超时,想看请求是否真的发出去了:
tcpdump -i any -nn -A host api.example.com and port 443
# 看到 ClientHello 发出但没收到 ServerHello = TLS 握手失败
7.3 安全注意
tcpdump 会抓到明文流量(HTTP 请求体、cookie)。生产环境抓包必须:
- 限定范围(特定 IP + 端口 + 时间)
- 抓完立即删除 pcap 文件
- 不能把 pcap 文件传到不受控环境
8. 路由与防火墙
8.1 看路由表
ip route show
# default via 192.168.1.1 dev eth0
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100
# 查到某 IP 走哪条路由
ip route get 1.2.3.4
8.2 防火墙
# iptables(老系统)
iptables -L -n -v # 看规则
iptables -L INPUT -n --line-numbers
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT # 临时开放端口
# firewalld(CentOS 7+)
firewall-cmd --list-all
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
# ufw(Ubuntu)
ufw status
ufw allow 8080/tcp
ufw enable
# nftables(新一代)
nft list ruleset
云服务器还有云厂商的安全组,机器上规则放开了不代表外网能访问。排查云上"端口连不上"先看:
- 云控制台安全组 / 网络 ACL
- 机器上防火墙
- 服务本身是否监听
0.0.0.0而非127.0.0.1
监听地址查错:
ss -tnlp | grep :3000
# LISTEN 0 128 127.0.0.1:3000 ← 只监听 localhost,外网连不上
# LISTEN 0 128 0.0.0.0:3000 ← 所有网卡,外网可达
# LISTEN 0 128 [::]:3000 ← IPv6 所有
Node 默认 app.listen(3000) 在不同版本绑不同地址,明确写:
app.listen(3000, '0.0.0.0')
9. 综合排障实战
9.1 案例:浏览器报 ERR_CONNECTION_REFUSED
# 1. 本地能 ping 通服务器吗
ping <server-ip>
# 2. 端口通吗
nc -zv <server-ip> 443
# refused → 服务没起或防火墙拒绝
# timeout → 防火墙 drop 或网络不通
# 3. SSH 到服务器,看服务起没起
ss -tnlp | grep :443
# 4. 起了但外网连不上 → 检查监听地址 + 防火墙 + 安全组
9.2 案例:API 间歇超时
# 1. 持续 ping 看丢包
mtr api.example.com
# 2. curl 分时分析定位慢在哪
curl -w "@curl-format" -o /dev/null -s https://api.example.com/health
# 3. 服务器端看连接数
ss -s
# 看 TIME_WAIT 数量是否异常
# 4. 看具体连接超时
tcpdump -i any -nn host api.example.com and port 443
# 看是否有 RST 或 TLS Alert
9.3 案例:Nginx 502 Bad Gateway
# 1. 看 Nginx 错误日志
tail -f /var/log/nginx/error.log
# connect() failed (111: Connection refused) while connecting to upstream
# 2. 上游服务还活着吗
systemctl status backend-app
ss -tnlp | grep :8080
# 3. 上游能 ping 通吗(Nginx 机器上)
nc -zv backend-ip 8080
10. 常见反模式
ping不通就以为服务挂了:ICMP 经常被禁,应该用nc -zvnetstat当首选:deprecated,统一用ss- tcpdump 抓全部:磁盘瞬间塞满,必须加过滤条件 +
-c限制包数 - curl 调试 HTTPS 用 -k 跳过验证:上线后忘记去掉,等于裸奔
- 服务监听 127.0.0.1 又问为啥外网连不上:先看 ss 输出的 Local Address
- 生产抓包不删 pcap:明文流量泄露
- traceroute 看到中间跳
* * *就以为有问题:很多机器禁 ICMP,是正常现象
11. 工具速查表
| 我想…… | 用什么 |
|---|---|
| 测一个 URL 通不通 + 看响应 | curl -v |
| 测一个 TCP 端口通不通 | nc -zv host port |
| 看 DNS 解析结果 | dig domain 或 dig @8.8.8.8 domain |
| 看本机监听了什么端口 | ss -tnlp |
| 看哪个进程占了端口 | ss -tnlp | grep :3000 或 lsof -i :3000 |
| 看网络路径 | mtr host |
| 抓包 | tcpdump -i any -nn -w file.pcap port 443 |
| 看 HTTP 性能分时 | curl -w "@curl-format" |
| 端口被占释放 | fuser -k 3000/tcp |
| 进程打开了哪些 socket | lsof -p <pid> |
12. 延伸阅读
- Wireshark 官方文档 — 抓包分析进阶
- curl 完整手册
- iproute2 (ss/ip) 文档
- The TCP/IP Guide — 协议层面深入
- Julia Evans 的网络工具图册 — 漫画版工具速查