跳到主要内容

网络排查工具链

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+)的常见原因:

  1. DNS 服务器 down,换 /etc/resolv.conf 里的 nameserver
  2. 网络限制(防火墙拦 53 端口 UDP)
  3. /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 读文件
  • -A ASCII 显示 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

云服务器还有云厂商的安全组,机器上规则放开了不代表外网能访问。排查云上"端口连不上"先看:

  1. 云控制台安全组 / 网络 ACL
  2. 机器上防火墙
  3. 服务本身是否监听 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 -zv
  • netstat 当首选: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 domaindig @8.8.8.8 domain
看本机监听了什么端口ss -tnlp
看哪个进程占了端口ss -tnlp | grep :3000lsof -i :3000
看网络路径mtr host
抓包tcpdump -i any -nn -w file.pcap port 443
看 HTTP 性能分时curl -w "@curl-format"
端口被占释放fuser -k 3000/tcp
进程打开了哪些 socketlsof -p &lt;pid>

12. 延伸阅读