tcpdump 抓包分析实战:过滤表达式与典型故障定位套路
线上网络问题最难缠的是“感觉”太多、证据太少:应用说网络慢,网络说链路没问题,中间全是猜测。抓包的价值就是把争论变成证据——包有没有发出、对端回没回、慢在哪一段,pcap 里都写着。本文以 tcpdump 为主线,讲清抓包姿势与 BPF 过滤表达式,给出五个高频故障场景的抓法与读法,最后说明与 Wireshark 的配合和抓包的边界。适用环境为任意主流 Linux 发行版,需要 root 或 sudo 权限。
前置条件
- 一台有 sudo 权限的目标主机,且已想清要抓的是链路的哪一段;
- 已安装 tcpdump,可选装 Wireshark 在本地图形化分析 pcap;
- 明确要抓的对象:对端 IP、端口、协议至少知道一项,全量抓包只会淹没在噪声里;
- 清楚变更窗口与留痕要求:抓包文件可能含业务明文,先确认合规口径再动手。
一、抓包的基本姿势:先落盘,再分析
生产排障不要把输出直接刷屏:会丢包,也没法复盘。规范做法是先写 pcap 文件再分析。几个关键参数要养成习惯:-i 指定网卡(不确定时可用 any,但链路层信息会不完整);-s0 表示不截断包长,截断的包在 Wireshark 里会带截断标记,分析应用层时容易误判;-B 调大内核缓冲区,高流量下默认缓冲容易溢出丢包,抓完看统计里的 dropped by kernel 就知道丢没丢;-C 与 -W 做文件轮转,防止长抓写满磁盘。
# 基本姿势:在 eth0 上抓与 192.0.2.10 之间的全部流量,落盘并按 100MB 轮转,保留 5 个文件
tcpdump -i eth0 -s0 -B 4096 -nn host 192.0.2.10 -w /tmp/cap.pcap -C 100 -W 5
# 只抓一小段时间验证过滤条件是否正确,用 -c 控制包数后自动退出
tcpdump -i eth0 -nn -c 20 host 192.0.2.10 and port 443
# 读回已保存的 pcap 文件
tcpdump -nn -r /tmp/cap.pcap 'tcp and port 443'
还有一个细节:-nn 要默认带上,分别禁止把 IP 解析成主机名、把端口号解析成服务名。不加的话 tcpdump 会不断发起反向 DNS 查询,既拖慢输出,又往抓包里混入无关的 DNS 流量干扰判断。
二、BPF 过滤表达式速查
过滤表达式由 BPF 语法构成,在内核层执行,不命中的包不会拷贝到用户态,所以捕获过滤比抓完再筛效率高得多。组织方式就三类:限定词(host、net、port、portrange)、协议(tcp、udp、icmp、arp),再用 and、or、not 组合。表达式要用引号包住,避免 shell 解释括号等特殊字符。
# 按主机、网段、端口过滤
tcpdump -i eth0 -nn 'host 192.0.2.10'
tcpdump -i eth0 -nn 'net 192.0.2.0/24'
tcpdump -i eth0 -nn 'port 53 or port 443'
tcpdump -i eth0 -nn 'portrange 8000-9000'
# 方向限定:只看发往对端的,或只看来自对端的
tcpdump -i eth0 -nn 'dst host 192.0.2.10 and tcp dst port 443'
tcpdump -i eth0 -nn 'src host 192.0.2.10'
# 组合表达式:括号必须转义或使用引号整体包裹
tcpdump -i eth0 -nn 'tcp and (port 80 or port 443) and not host 192.0.2.99'
# 按 TCP 标志位过滤:只抓 SYN 包(tcp[13] 是标志位字节,2 为 SYN 位)
tcpdump -i eth0 -nn 'tcp[13] & 2 != 0'
# 只抓带 PSH+ACK 的数据包,看应用层数据的发送节奏
tcpdump -i eth0 -nn 'tcp[13] & 24 == 24 and host 192.0.2.10'
记不住标志位也没关系,日常排障 90% 的场景只需要 host、port、协议三件套,标志位过滤只在只统计握手、只找 RST 这类定向分析时才需要。
三、场景一:TCP 三次握手异常
连接建立不了,先看握手断在哪一步。正常流程是 SYN → SYN+ACK → ACK。在客户端和服务端各抓一份对照时间线:只有 SYN 且按 1、2、4、8 秒节奏重传,说明 SYN 没到服务端或回程不通,查防火墙、路由、安全组;服务端回了 SYN+ACK 却收不到 ACK 并在重传,问题在回程或客户端侧;一上来就收到 RST,通常是端口无进程监听或被防火墙拒绝。跨机器对比记得加 -tttt 打时间戳并先对齐时钟,否则会得出反结论。
# 只抓握手与 RST:SYN 置位或 RST 置位的包
tcpdump -i eth0 -nn -tttt 'host 192.0.2.10 and tcp and (tcp[13] & 2 != 0 or tcp[13] & 4 != 0)'
四、场景二:重传与乱序导致"连接在但很慢"
连接能建立、数据也能过,但慢得离谱,十有八九是丢包重传。判断重传靠序列号:同一批数据发了两次,或 ACK 长时间不推进、出现重复 ACK。命令行下用 -A/-X 只能看个大概,准确定位建议交给 Wireshark 专家信息(Expert Information),它会直接标出各类重传与重复 ACK。命令行侧可以用 tshark 统计:
# 用 tshark 在命令行统计重传(需安装 wireshark-cli 或 tshark 包)
tshark -r /tmp/cap.pcap -Y 'tcp.analysis.retransmission' -q -z io,stat,0
# 只把重传包的时间戳和序号打出来,观察重传发生的密集程度
tshark -r /tmp/cap.pcap -Y 'tcp.analysis.retransmission' \
-T fields -e frame.time_epoch -e ip.src -e tcp.seq
读法上注意区分真重传和抓包位置造成的假象:发送端抓包时,网卡 TSO/GRO 卸载会让单包远超 MTU,看起来像乱序,其实是卸载合并。分析乱序前先确认抓包点,必要时在对端或镜像口复核。
五、场景三:DNS 解析慢
应用日志里接口超时,直接调 IP 又很快,问题常在 DNS。先抓 53 端口看请求与响应的间隔:数秒才回且中间能看到应用重发同一查询,说明 DNS 响应慢或第一个服务器不可达在等超时切换;响应是 SERVFAIL,则是解析端配置或上游问题。再对照 /etc/resolv.conf 的 nameserver 顺序与 timeout,多数偶尔慢 5 秒都是第一个 DNS 不可达、每次先等满超时再切第二个造成的。
# 抓 DNS 交互,带毫秒级时间戳看请求与响应的间隔
tcpdump -i eth0 -nn -ttt -l port 53 | head -50
# 只看某个域名的查询(DNS 报文里域名字符串可粗略匹配,精确分析建议用 tshark)
tshark -i eth0 -Y 'dns.qry.name contains "example.com"' -T fields -e dns.qry.name -e dns.flags.response
六、场景四:HTTP 请求卡住
请求迟迟不返回,抓包能定界卡在哪一层:请求包没发出,是客户端自身问题(如连接池耗尽);请求到了、服务端 ACK 了但迟迟不回应用数据,是服务端处理慢,转去看应用日志;服务端发了数据但客户端迟迟不 ACK 或出现零窗口(Zero Window),是客户端消费太慢。加 -A 可直接看 HTTP 明文,确认请求行与响应状态码。
# 看 HTTP 明文交互,确认请求是否发出、响应码是什么
tcpdump -i eth0 -nn -A -l 'host 192.0.2.10 and port 80' | grep -E '^(GET|POST|HTTP|Host:)'
# 只抓零窗口通告,定位接收端处理不过来的证据
tshark -r /tmp/cap.pcap -Y 'tcp.analysis.zero_window' -T fields -e frame.time_relative -e ip.src
七、场景五:端口不通的定界
"端口不通"是最常见的报障描述,定界逻辑是在链路的两个点各抓一份做对比:客户端抓不到 SYN 发出,问题在客户端本机(应用没发起连接、本地防火墙拦截);客户端发了 SYN、服务端抓不到,问题在中间链路(防火墙、安全组、路由);服务端回了 SYN+ACK、客户端抓不到,问题在回程路径;服务端收到 SYN 直接回 RST,或毫无回应且 netstat 显示无监听,先查服务进程本身。这套两点对照法的本质是沿路径逐点确认包的进出。
八、与 Wireshark 的配合
推荐分工:服务器上用 tcpdump 只负责抓全、抓准,pcap 拉回本地用 Wireshark 深度分析。Wireshark 最有价值的三个功能是:Follow TCP Stream(拼完整条连接的双向数据)、专家信息(自动标注重传、乱序、零窗口等异常)、IO 图表(看流量突发与停顿的分布)。注意其显示过滤器与 BPF 语法完全不同,如筛选重传是 tcp.analysis.retransmission,别混用。装了 tshark 也可直接做字段级统计,适合脚本化巡检。
九、抓包的注意事项与边界
第一是性能:高流量网卡上不带过滤全量抓包会显著吃 CPU,还可能反过来造成业务丢包,务必带过滤、控制时长、抓完立即停。第二是合规与隐私:pcap 里可能含账号、令牌等明文敏感信息,要按敏感数据管理,分析完及时销毁。第三是能力边界:TLS 加密后只能看到握手元数据(SNI、证书、时序、包长),看不到业务内容,应用层细节得靠日志或端点解密。
验证
- 抓包无异常丢弃:结束时 tcpdump 输出的 dropped by kernel 为 0(或占比极低),说明包是完整的;
- 过滤命中目标流量:用
tcpdump -r 文件读回时,前几行应全是目标主机与端口的交互,没有大量无关流量; - 定界结论能被第二抓包点复核:在链路另一点抓包,两边时间线能对齐并支撑同一个结论。
常见问题
- 抓不到任何包。先确认网卡选对:流量可能走 bond 口或另一块网卡,用
tcpdump -D列接口,必要时抓 any 复核;其次检查过滤是否过严,先放宽到只按主机抓再收紧。 - 抓的包大量显示截断。多半是忘了加
-s0:老版本默认 snaplen 较小,应用层内容不完整时 Wireshark 会报包被截断,重新抓时补上。 - 明明有流量却报 permission denied 或需要 root。抓包需要 CAP_NET_RAW 等能力,普通用户用 sudo;容器内抓包还要确认网络命名空间与能力配置。
- pcap 打开后时间对不上。跨机器对比时两边时钟没同步。分析时以相对时间差(同机内的请求-响应间隔)为主,绝对时间仅作参考,并先用 chronyc 对齐两边时间。
小结
tcpdump 的用法可压缩成一条主线:带过滤、先落盘、看统计确认没丢包,再按场景读时间线。握手异常看标志位和重传节奏,重传交给序列号分析,DNS 慢看请求响应间隔,HTTP 卡住按发没发、回没回、谁不 ACK 逐层定界,端口不通用两点对照沿路径确认。掌握这套套路,多数网络争议都能从互相猜测变成包里写着。同时记住它的性能代价、隐私边界和加密流量只能看元数据的限制。






