首页/网络/抓包与流量分析速查/tcpdump tcpflags 标志位过滤

tcpdump tcpflags 标志位过滤

用 tcp[tcpflags] 读取 TCP 标志字节,与 tcp-syn/tcp-ack/tcp-fin/tcp-rst/tcp-push 等名字按位运算,精确抓取某类标志组合的包。

tcpflags 在做什么

TCP 头部第 13 字节存放标志位,BPF 里写成 tcp[tcpflags],也可以用数字下标 tcp[13];与 tcp-syn、tcp-ack、tcp-fin、tcp-rst、tcp-push、tcp-urg 这些名字做按位运算,就能精确抓取某种标志组合的报文。关键在于两种比较的区别:用不等于零是「包含该位」,用等于值是「恰好等于」。这个区别直接决定统计结果对不对,也是这一组写法里最容易出错的地方。

基本信息

包含写法tcp[tcpflags] & tcp-syn != 0
精确写法tcp[tcpflags] = tcp-syn
组合写法多个标志名用竖线连接,如 tcp-syn|tcp-ack
位置等价tcp[tcpflags] 与 tcp[13] 等价
标志名tcp-fin tcp-syn tcp-rst tcp-push tcp-ack tcp-urg tcp-ece tcp-cwr

标志位与写法

标志数值含义常用写法
FIN0x01本端不再发送数据tcp[tcpflags] = tcp-fin
SYN0x02请求建立连接tcp[tcpflags] = tcp-syn
RST0x04强制复位连接tcp[tcpflags] & tcp-rst != 0
PSH0x08请求对方尽快上交数据tcp[tcpflags] & tcp-push != 0
ACK0x10确认号字段有效tcp[tcpflags] = tcp-ack
SYN 与 ACK0x12建连应答tcp[tcpflags] = tcp-syn|tcp-ack
FIN 与 ACK0x11关闭确认tcp[tcpflags] = tcp-fin|tcp-ack

典型使用场景

  • 统计建连请求量:只看纯 SYN,结果不会被应答报文放大
  • 抓复位报文:定位连接被重置的源头与时机
  • 观察关闭流程:只看 FIN 与 FIN-ACK 组合,判断是谁先发起关闭
  • 过滤保活与心跳:只抓纯 ACK 能快速看到无数据的连接活动
  • 排查重复报文:结合上重传的序列号特征,只看带 PSH 的数据报文
  • 用单一标志组合描述扫描行为:大量纯 SYN 加极少 ACK

常用示例

常用示例
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'                 # 出现过 SYN 的报文
tcpdump -i eth0 -nn 'tcp[tcpflags] = tcp-syn'                     # 只有纯 SYN
tcpdump -i eth0 -nn 'tcp[tcpflags] = tcp-syn|tcp-ack'             # 建连应答
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'                # 复位报文
tcpdump -i eth0 -nn 'tcp[tcpflags] = tcp-fin|tcp-ack'             # 关闭确认
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-push != 0 and port 443'  # 带数据推送的报文
抓纯 ACK 是观察空闲连接的常用办法:tcp[tcpflags] = tcp-ack 得到的是只带确认、不带数据的报文,对应保活与心跳行为,能看出连接是空转还是真的在传数据。
用等于号写组合时必须把所有置位的标志都写全,漏写一个就什么都匹配不到。例如 SYN-ACK 必须写 tcp-syn|tcp-ack,只写 tcp-syn 会永远抓不到它。

组合统计

组合统计
tcpdump -nn -r a.pcap 'tcp[tcpflags] = tcp-syn' | wc -l          # 建连请求数
tcpdump -nn -r a.pcap 'tcp[tcpflags] = tcp-syn|tcp-ack' | wc -l  # 应答数
tcpdump -nn -r a.pcap 'tcp[tcpflags] & tcp-rst != 0' | wc -l     # 复位数
tcpdump -nn -r a.pcap 'tcp[tcpflags] & tcp-fin != 0' | wc -l     # 关闭相关报文数

判读要点

  • 纯 SYN 数量远多于 SYN-ACK 数量时,重点查哪些请求没有得到应答
  • RST 数量上升时先看它出现在建连阶段还是传输阶段,两者原因完全不同
  • FIN 很多而数据很少,通常意味着连接建立后几乎没传数据就被关闭
  • 只在少数地址上出现大量纯 SYN,多半是客户端连接风暴而非整体链路问题
  • 纯 ACK 持续出现而数据很少,是保活与心跳流量的典型形态
  • PSH 与 ACK 组合的报文携带数据,统计吞吐时只看这类报文更准确

写表达式的三个习惯

  • 先用包含写法把相关报文抓全,看清楚之后再换成精确写法做统计
  • 组合标志按从高位到低位顺序写,拼接错误时更容易对照发现
  • 写完先用少量计数确认命中量级,量级与预期不符说明漏写或错写了标志
  • 把常用组合存成命令模板,避免每次重新拼接标志名时遗漏某一位

常见组合与用途

组合含义用途
仅 SYN建连请求统计连接尝试次数
SYN 加 ACK建连应答与请求配对判断应答率
仅 ACK纯确认,不带数据观察保活与心跳
ACK 加 PSH确认并推送数据统计真正承载业务的报文
FIN 加 ACK关闭确认判断关闭流程是否正常
RST 加 ACK复位并确认端口未监听或被策略拒绝的典型形态
统计连接成败时把纯 SYN 与建连应答两个计数放在一起看:比值接近一说明应答正常,差距明显则说明存在未被应答的请求,接下来再按目的端口拆分就能定位到具体服务。

易错点

  • 把包含写法与精确写法混用会让统计结果偏差,数某类报文必须用等于号写法
  • 组合标志漏写其中一位就完全匹配不到,写完后用小样本验证一次
  • tcp[tcpflags] 由解析器按实际头部长度定位,不要自己用固定偏移算第七字节
  • 标志位只描述当前这一包,判断整个连接过程要把同一个流里的报文串起来看
  • 只看标志位不看序列号与载荷长度,会把保活类纯 ACK 误判成业务流量

数据来源与参考

  • man 8 pcap-filter(tcp[tcpflags] 示例)
  • RFC 793(TCP 头部)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌