tcpdump 可通过 bpf 表达式精准过滤 tcp 标志位,如 syn、ack、fin、rst 等,利用 tcp[tcpflags] 自动定位标志字节,结合按位与(&)操作匹配置位状态,支持组合条件与端口/方向限制,高效诊断连接建立、中断及异常行为。

tcpdump 可以直接通过 BPF 表达式过滤 TCP 标志位,比如 SYN、ACK、FIN、RST 等,这是诊断连接建立、异常中断或扫描行为的关键手段。它不依赖应用层解析,纯靠 TCP 头部的 12 字节控制字段(含 6 个标志位)做匹配,准确且高效。
用 tcp[13] 提取 TCP 标志字节
TCP 头部中,第 13 个字节(索引从 0 开始,即 tcp[13])存放 6 个标志位:URG、ACK、PSH、RST、SYN、FIN(从高位到低位,bit7–bit2)。每个标志对应一个比特值:
- SYN → 0x02(二进制 00000010)
- ACK → 0x10(二进制 00010000)
- FIN → 0x01(二进制 00000001)
- RST → 0x04(二进制 00000100)
- PSH → 0x08(二进制 00001000)
- URG → 0x20(二进制 00100000)
注意:tcp[13] 是原始字节值,不是布尔真假;要判断某标志是否置位,必须用按位与(&)操作。
常见标志位过滤写法
以下写法均需加单引号包裹整个表达式,防止 shell 解析特殊字符:
- 只抓 SYN 包(三次握手第一步):tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] == tcp-syn'
- 抓所有含 ACK 的包(含数据确认和纯 ACK):tcpdump -i eth0 'tcp[tcpflags] & tcp-ack != 0'
- 抓 FIN+ACK 组合(正常断开):tcpdump -i eth0 'tcp[tcpflags] & (tcp-fin|tcp-ack) == (tcp-fin|tcp-ack)'
- 抓 RST 包(异常重置):tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0'
- 排除 SYN 和 RST(只看数据传输阶段):tcpdump -i eth0 'tcp and not (tcp[tcpflags] & (tcp-syn|tcp-rst) != 0)'
说明:tcp-syn 等是 tcpdump 内置符号常量,比硬写 0x02 更安全可读;== 表示**完全匹配该组合**,!= 0 表示**只要该位被置位就命中**。
为什么不能直接写 tcp[13] == 0x02?
因为 TCP 头部长度可变(含选项),标志位所在偏移不一定总在字节 13。虽然大多数情况是,但若存在 TCP 选项(如时间戳、SACK),头部会变长,tcp[13] 可能指向错误位置。而 tcp[tcpflags] 是 tcpdump 封装好的逻辑偏移计算,自动跳过选项区定位到正确的标志字节,更健壮。
结合端口和方向提升准确性
单独过滤标志位容易混入无关流量。建议叠加协议、端口或方向限制:
- 只看目标端口 3306 的 SYN 连接请求:tcpdump -i eth0 'dst port 3306 and tcp[tcpflags] & tcp-syn != 0'
- 监控某 IP 发起的 RST 异常:tcpdump -i eth0 'src host 10.0.1.5 and tcp[tcpflags] & tcp-rst != 0'
- 抓本机对外发出的 FIN 包(主动关闭):tcpdump -i eth0 'src host 192.168.1.100 and tcp[tcpflags] & tcp-fin != 0'
务必加上 -n(禁 DNS 解析)和 -nn(禁端口名转换),避免干扰输出和性能延迟。











