iptables通过--tcp-flags直接匹配TCP标志位,不依赖状态跟踪,以mask和check位级比对实现高效过滤,如--tcp-flags ALL SYN匹配合法SYN包,--tcp-flags SYN,FIN SYN,FIN拦截非法组合,配合DROP可静默防御Xmas/Null等隐蔽扫描。

tcp-flags 匹配语法与核心逻辑
命令格式为:iptables -A CHAIN -p tcp --tcp-flags [mask] [check] -j TARGET
mask 是待检测的标志位集合(必须为 1 或 0 的位),check 是在 mask 范围内要求值为 1 的标志位列表。
匹配成功条件:mask 中所有为 1 的位,其实际值必须与 check 完全一致(即:mask & 实际flags == mask & check)。
常用标志缩写:SYN、ACK、FIN、RST、PSH、URG(共 6 个标准位;ECN/CWR/ECE 等扩展位 iptables 默认不识别)。
- 只匹配 SYN 包(三次握手第一次):
--tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN - 匹配 SYN+ACK(第二次握手):
--tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK - 匹配纯 ACK(非握手/数据传输确认):
--tcp-flags ACK,SYN ACK(mask 含 ACK 和 SYN,但只强制 ACK=1、SYN=0) - 拦截非法组合(如 SYN+FIN):
--tcp-flags SYN,FIN SYN,FIN -j DROP
典型防护场景与规则示例
利用标志位组合可快速识别异常行为,无需依赖连接状态表。
-
防 SYN Flood:仅放行初始 SYN,后续包必须带 ACK
→iptables -A INPUT -p tcp --dport 80 --tcp-flags ALL SYN -j ACCEPT
→ 再加一条默认 DROP 规则阻断无 SYN 的入向连接请求 -
阻断非法 FIN/RST 扫描:禁止外部主动发 FIN 或 RST 关闭连接(正常应由客户端发起)
→iptables -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK FIN -j DROP
→iptables -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK RST -j DROP -
限制非 Established 连接的 ACK:防止伪造 ACK 绕过防火墙
→ 先放行合法握手包(SYN / SYN+ACK / FIN+ACK),再用--tcp-flags ACK,SYN ACK匹配纯 ACK,并结合 `-m state ! --state ESTABLISHED,RELATED -j DROP` 增强判断
注意事项与常见误区
tcp-flags 是位掩码匹配,不是字符串模糊匹配,大小写敏感且顺序无关,但拼写必须准确。
- mask 中未列出的标志位(如只写
SYN,ACK)会被忽略,不影响匹配结果 - 不能用
--tcp-flags ALL替代完整列表——ALL 是 iptables 内部宏,等价于SYN,ACK,FIN,RST,URG,PSH,但部分旧版本不支持,建议显式写出 - 不处理 IP 分片:若 TCP 头被分片,iptables 可能无法解析标志位(需配合
-f或启用 conntrack 重组) - 与 conntrack 状态规则混用时,注意链顺序——tcp-flags 规则应在 state 规则之前,避免已 DROP 的包进入状态跟踪
调试与验证方法
用 tcpdump 抓包确认实际标志位,再比对规则是否命中:
- 抓取 SYN 包:
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn' - 查看规则计数:
iptables -L INPUT -v -n | grep tcp-flags - 添加日志规则辅助分析:
-j LOG --log-prefix "TCP-FLAGS-DROP: "















