tcpdump 无法按 tcp 序列号实时过滤,必须先全量抓包(-s 0 -vvv),再用 tshark 或 awk 离线提取;因 bpf 不支持可靠解析可变偏移的 seq 字段,强行用 tcp[4:4] 会因字节序、tcp 选项长度变化而失效。

直接说结论:tcpdump 本身**无法按 TCP 序列号(seq)值或范围过滤**,它不支持 tcp[12:4] == 0x12345678 这类原始偏移解析的实时过滤(即使语法上能写,实际在多数内核+libpcap组合下不可靠或不生效)。想精准定位某段序列号的重传,必须分两步:先全量或宽泛捕获 → 再用 tshark 或 tcpdump -r + awk 等工具离线提取。
为什么不能直接用 tcpdump -r xxx.pcap 'tcp seq 123456789'?
因为 tcpdump 的 BPF 过滤器工作在链路层/网络层,只支持协议类型、端口、IP、TCP 标志位(如 tcp[tcpflags] & tcp-rst != 0)等有限字段;TCP 头部的 seq、ack 是 32 位整数,位于 TCP 头偏移 4 字节处,BPF 不提供安全、跨平台的字节提取和数值比较能力。强行用 tcp[4:4] == 0x... 会因字节序、TCP 选项长度可变(导致 seq 偏移不是固定 4)、内核版本差异而频繁失效。
抓包阶段:必须保留完整 TCP 头和载荷
重传分析依赖原始序列号、时间戳、SACK 信息等,所以抓包时不能截断:
- 务必加
-s 0(或足够大的值如-s 65535),否则[|tcp]截断会导致序列号不可见 - 推荐用
-vvv获取详细 TCP 头信息(含seq、ack、win、options) - 指定接口(如
-i eth0)比-i any更稳定,避免虚拟接口干扰 - 示例命令:
sudo tcpdump -i eth0 -s 0 -vvv -w retrans_capture.pcap tcp and port 8080
分析阶段:用 tshark 精确匹配 seq 范围
tshark(Wireshark 命令行版)支持完整的 TCP 字段解析和数值比较,是唯一可靠方案:
- 查某个确切
seq值:tshark -r retrans_capture.pcap -Y "tcp.seq == 3739719434" - 查
seq在某区间内(如 3739719000 ~ 3739719500):tshark -r retrans_capture.pcap -Y "tcp.seq >= 3739719000 && tcp.seq - 同时筛选重传标志:
tshark -r retrans_capture.pcap -Y "tcp.analysis.retransmission && tcp.seq >= 123456789" - 输出简洁格式(含时间、源/目的、seq、标志):
tshark -r retrans_capture.pcap -Y "tcp.analysis.retransmission" -T fields -e frame.time_epoch -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e tcp.seq -e tcp.flags
如果只有 tcpdump,用 awk 提取 seq 并过滤
当无法安装 tshark 时,可用 tcpdump -r -nn -vvv 输出文本,再用 awk 解析(注意:依赖输出格式稳定,不同 tcpdump 版本可能微调):
- 先确认输出中
seq字段位置:tcpdump -r retrans_capture.pcap -nn -vvv -c 1 | grep -o "seq [^,]*" - 提取并过滤(假设输出形如
seq 123456789:123456890):tcpdump -r retrans_capture.pcap -nn -vvv | awk '/seq [0-9]+:/ {split($NF, a, "[: ]"); if (a[2] >= 123456789 && a[2] - 该方式易受 TCP 选项、SACK、时间戳等干扰,仅作临时应急,不可用于精确取证
真正棘手的点在于:TCP 重传报文的序列号往往和原始报文一致,但你很难仅凭 seq 判断是否重传——必须结合 tcp.analysis.retransmission 这类语义标记,而这只有 tshark 能稳定提供。别在 tcpdump 的 BPF 里硬刚 seq 过滤,那是条死路。











