用 tcpdump 抓包 + Wireshark 复现一个 TCP RST 问题

应用日志里出现 "connection reset by peer",应用端代码看着没问题,
对端代码看着也没问题。这类问题 70% 是中间链路(LB / 防火墙 / 反代)
干的。抓包是唯一直接定位的办法。

1. 收集足够的现场信息

before 开抓之前,先列清楚四元组:

# 客户端
ss -tan state established '( dport = :8080 or sport = :8080 )'
# 服务端
ss -tan state established '( sport = :8080 )'

记下 src / dst IP + port。

2. tcpdump 命令

服务端:

sudo tcpdump -i any \
  -s 0 \
  -w /tmp/svr.pcap \
  'tcp port 8080'

客户端(如果可以同时抓):

sudo tcpdump -i eth0 -s 0 -w /tmp/cli.pcap 'host <server-ip> and tcp port 8080'
  • -s 0 不截断 payload(默认 96 字节,分析 HTTP / TLS 不够看)
  • -i any 在 Linux 上抓所有接口(不知道走哪个就用这个)
  • 写文件比直接终端打印好 100 倍 —— 终端文本格式会丢字段、丢顺序

跑出问题后 Ctrl-C 停。

3. 快速浏览

# 文本看一眼
tcpdump -r /tmp/svr.pcap -n -nn -c 20

# 只看 RST 包
tcpdump -r /tmp/svr.pcap -n 'tcp[tcpflags] & tcp-rst != 0'

# 看哪些会话有 RST
tshark -r /tmp/svr.pcap -Y 'tcp.flags.reset == 1' \
  -T fields -e tcp.stream -e ip.src -e ip.dst | sort -u

tcp.stream 是 Wireshark 给每个 TCP 会话的整数 ID。找到出问题的 stream 号
(比如 7):

tshark -r /tmp/svr.pcap -Y 'tcp.stream == 7' -V | less

4. 用 Wireshark 看

scp server:/tmp/svr.pcap .
wireshark svr.pcap

经验流程:

  1. Statistics → Conversations → TCP,看哪些会话异常短或有 RST
  2. 右键问题会话 Follow → TCP Stream:看应用层 payload,能判断 RST
    是发生在哪条请求 / 哪个字节边界
  3. Expert Information(左下角的⚠图标):Wireshark 自动标注的
    异常(previous segment lost, dup ACK, RST 等)

5. RST 的常见根因

现象 根因
服务端发的 RST,紧跟在 FIN 之后 应用没读完 socket 缓冲就 close(HTTP body 没消费)
客户端发的 RST,应用层没异常 客户端 OS RST:socket 被强制回收(fd 泄露后被 GC)
中间设备发的 RST,TTL 远小于真实端 防火墙 / 流量清洗设备主动断
握手后立刻 RST TCP wrappers / hostsdeny;或对端只接受 IPv4 而你发的 IPv6
大块上传中途 RST LB 的 buffer overflow / 限流;或 MTU 不匹配(Path MTU Black Hole)

6. MTU 问题的快速验证

如果怀疑 MTU:

# 强制最大 1500 - 28 = 1472 字节 payload,不允许分片
ping -M do -s 1472 <server>

# 二分缩小直到能通
ping -M do -s 1400 <server>

ping ... fragmentation needed 就是被某段链路要求分片但你设了 DF(不分片)。
通常出现在 PPPoE / VPN / 部分隧道场景。

7. 持续抓包(环形缓冲)

排查间歇性问题时,连续抓不停但不要把磁盘塞满:

sudo tcpdump -i any -s 0 \
  -w /tmp/sniff-%Y%m%d-%H%M%S.pcap \
  -G 600 \
  -W 24 \
  'tcp port 8080'

-G 600 每 10 分钟切新文件;-W 24 最多保留 24 个,循环覆盖。

踩过的坑

  • 抓包文件别忘了清理 —— -s 0 在繁忙服务上一小时能写 GB 级。
  • tshark -Y 是显示过滤器(capture 后筛选),-f 是 capture 过滤器
    (抓的时候用)。语法不一样,别混。-Y 'tcp.port == 8080' vs
    -f 'tcp port 8080'
  • TLS 流量看不到明文,配合 SSLKEYLOGFILE 让浏览器/curl 把会话 key 落地,
    Wireshark 用这个 key 文件就能解密(Edit → Preferences → Protocols → TLS)。
  • 抓本机环回流量在 Linux 上需要 -i lo-i any 偶尔会漏。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。