3. 抓包工具入门:tcpdump基础用法、Wireshark基础用法、如何抓取超时相关的包
说到排查连接超时,我最先想到的工具就是抓包。你想想看,网络问题说白了就是包丢了、包慢了、包错了。没有抓包数据,你就是在黑暗中摸索。我个人习惯是:先tcpdump留证据,再Wireshark慢慢分析。这一章我们就来搞定这两把刀。
核心原则:抓包不是为了看热闹,而是为了还原“那一刻网络到底发生了什么”。超时场景下,我们要重点看:SYN是否发出、SYN-ACK是否回来、谁发了RST、重传间隔是否异常。
3.1 tcpdump:命令行下的网络显微镜
tcpdump是Linux环境下的标配。我刚开始用的时候也记不住参数,后来总结了一套“三板斧”,够用了。
3.1.1 基础语法
# 最简抓包:抓eth0网卡所有流量
tcpdump -i eth0
# 指定端口和协议,避免被海量数据淹没
tcpdump -i eth0 tcp port 80
# 保存到文件,方便后续分析
tcpdump -i eth0 -w capture.pcap
# 读取pcap文件
tcpdump -r capture.pcap
嗯,这里要注意:-w 保存的是二进制文件,别用cat看,会乱码。用 -r 读回来。
3.1.2 超时场景必用参数
| 参数 | 作用 | 超时排查中的用法 |
|---|---|---|
-n |
不解析域名 | 避免DNS查询拖慢抓包,直接显示IP |
-v |
显示详细信息 | 看TTL、窗口大小、时间戳 |
-S |
显示绝对序列号 | 对比重传时序列号是否一致 |
tcp[tcpflags] |
过滤特定标志位 | 只抓SYN、RST、FIN包 |
我的习惯:抓超时问题时,我一般这样组合:tcpdump -i eth0 -n -S tcp port 8080 -w timeout.pcap。既保留原始信息,又避免域名解析干扰。
3.1.3 过滤表达式实战
抓包最怕的是数据太多。你需要学会“精准打击”。
# 只抓SYN包(三次握手第一步)
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'
# 只抓RST包(连接被重置)
tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0'
# 抓从客户端到服务器的包
tcpdump -i eth0 src host 192.168.1.100 and dst port 443
# 抓重传包(序列号相同)
tcpdump -i eth0 'tcp[4:2] == 0' # 简化版,实际需要结合窗口
我曾经在排查一个“间歇性超时”问题时,就是靠 tcpdump 'tcp[tcpflags] & tcp-rst != 0' 抓到了对端主动发的RST包,才发现是防火墙策略过期了。没有这个过滤,你会在几千个包里翻到崩溃。
3.2 Wireshark:图形化的协议解码器
tcpdump负责“采集”,Wireshark负责“分析”。我个人觉得Wireshark最大的价值在于:它帮你把二进制流翻译成了人能看懂的语言。
3.2.1 打开pcap文件
把tcpdump抓的 .pcap 文件拖进Wireshark就行。或者用命令行:
wireshark -r timeout.pcap
3.2.2 超时排查必用的Wireshark功能
- Follow TCP Stream:右键一个TCP包 → Follow → TCP Stream。能还原整个会话的对话内容,一眼看出哪一步卡住了。
- Expert Info:Analyze → Expert Info。Wireshark会自动标记异常:重传、重复ACK、零窗口等。超时场景下,这里会有一堆红色/黄色警告。
- Time列:默认显示的是相对时间。我建议改成“Seconds Since Beginning of Capture”,方便看每个包的时间间隔。
避坑指南:我曾经在分析一个慢连接问题时,盯着Wireshark看了半小时没发现问题。后来才发现,我忘了开启“Allow subdissector to reassemble TCP streams”。导致HTTP请求被切成了好几段,根本看不出完整延迟。记得在 Edit → Preferences → Protocols → TCP 里勾上这个选项。
3.2.3 过滤语法(Display Filter)
Wireshark的过滤语法比tcpdump更直观。我常用的几个:
| 过滤表达式 | 含义 |
|---|---|
tcp.analysis.retransmission |
显示所有重传包 |
tcp.analysis.fast_retransmission |
快速重传(通常意味着丢包) |
tcp.analysis.zero_window |
接收端窗口为0(对方处理不过来) |
tcp.flags.reset == 1 |
所有RST包 |
tcp.time_delta > 1 |
包间隔超过1秒(超时嫌疑) |
3.3 如何抓取超时相关的包
理论说完了,我们来点实战。假设你的应用报“连接超时”,你怎么抓包?
3.3.1 抓包时机:提前启动 vs 事后分析
超时问题分两种:持续超时和间歇超时。
- 持续超时:每次都超时。好办,直接启动抓包,然后发起一次请求,看完整交互。
- 间歇超时:偶尔超时。这个麻烦。我建议用
tcpdump -G 60 -W 10按分钟轮转保存,每个文件1分钟,保留10个文件。等超时复现后,看对应时间段的文件。
# 轮转抓包:每60秒生成一个新文件,最多保留10个
tcpdump -i eth0 -G 60 -W 10 -w timeout_%Y%m%d_%H%M%S.pcap tcp port 443
3.3.2 超时场景的抓包策略
| 超时类型 | 抓包策略 | 重点关注 |
|---|---|---|
| 连接建立超时 | 抓客户端到服务端SYN包 | SYN是否发出?SYN-ACK是否回来? |
| 数据传输超时 | 抓双向流量 | 是否有重传?窗口是否为零? |
| 连接关闭超时 | 抓FIN/ACK交互 | FIN是否被对端确认?TIME_WAIT是否堆积? |
我的经验:抓连接建立超时,我一般会在客户端和服务端同时抓包。客户端抓到的SYN如果没收到SYN-ACK,可能是中间设备丢了包;服务端如果没收到SYN,那就是网络问题。两边一对比,问题在哪一段就清楚了。
3.3.3 实战案例:抓一个“连接超时”
假设客户端IP是 10.0.0.1,服务端IP是 10.0.0.2,端口 8080。
步骤1:在客户端启动抓包
tcpdump -i eth0 -n -S host 10.0.0.2 and port 8080 -w client.pcap
步骤2:复现超时
发起请求,等待超时。
步骤3:停止抓包,用Wireshark分析
打开 client.pcap,使用过滤 tcp.analysis.retransmission。你会看到类似这样的场景:
- 第1个包:客户端发SYN
- 第3秒:客户端重传SYN(第一次超时重传)
- 第6秒:客户端重传SYN(第二次)
- 第12秒:客户端重传SYN(第三次)
- 第24秒:客户端放弃,返回超时
这说明服务端根本没回SYN-ACK。要么服务端挂了,要么中间防火墙把SYN丢了。
3.4 本章知识体系
下面这张图总结了抓包工具在超时排查中的定位和流程。
3.5 本章小结
抓包是网络排查的“眼睛”。tcpdump负责在问题发生时留下现场证据,Wireshark负责把证据翻译成我们能理解的时序图。超时场景下,你只需要记住三件事:
- 抓什么:SYN、RST、重传包、窗口更新包
- 怎么抓:持续超时直接抓,间歇超时轮转抓
- 怎么看:Follow Stream看对话,Expert Info看异常,Time列看间隔