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 |
标志位与写法
| 标志 | 数值 | 含义 | 常用写法 |
|---|---|---|---|
| FIN | 0x01 | 本端不再发送数据 | tcp[tcpflags] = tcp-fin |
| SYN | 0x02 | 请求建立连接 | tcp[tcpflags] = tcp-syn |
| RST | 0x04 | 强制复位连接 | tcp[tcpflags] & tcp-rst != 0 |
| PSH | 0x08 | 请求对方尽快上交数据 | tcp[tcpflags] & tcp-push != 0 |
| ACK | 0x10 | 确认号字段有效 | tcp[tcpflags] = tcp-ack |
| SYN 与 ACK | 0x12 | 建连应答 | tcp[tcpflags] = tcp-syn|tcp-ack |
| FIN 与 ACK | 0x11 | 关闭确认 | 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 与建连应答两个计数放在一起看:比值接近一说明应答正常,差距明显则说明存在未被应答的请求,接下来再按目的端口拆分就能定位到具体服务。