iptables不支持按TCP选项字段值过滤,仅能通过--tcp-option N检测选项类型是否存在,无法校验其长度、取值或结构;需eBPF、Suricata或用户态代理等替代方案实现字段级匹配。

iptables 本身不支持直接解析或匹配 TCP 头部的**具体选项字段值**(比如 MSS=1460、Timestamp 值、SACK 块内容等),-m tcp --tcp-option 模块仅能检测某个 TCP 选项**是否存在**(即选项类型是否出现在 TCP Option 字段中),不能校验其长度、取值或结构。所谓“直接过滤特定 TCP 头选项字段”,在标准 iptables 中并不可行。
为什么不能按字段值过滤?
Linux 内核 netfilter 的 xt_tcp 模块只提供以下能力:
-
--tcp-option N:检查 TCP 选项列表中是否包含类型为
N的选项(如--tcp-option 2检测 MSS,--tcp-option 8检测 Timestamp) - 它不读取该选项的后续字节,无法判断 MSS 是 1460 还是 0,也无法识别 Timestamp 的 echo reply 是否异常
- 没有类似
--tcp-opt-value或--tcp-opt-len的参数
哪些 TCP 选项可被识别并用于基础拦截?
常见可检测的选项类型(RFC 793 / RFC 7323)及对应用途:
-
--tcp-option 2:MSS —— 正常握手必含,但极小(如 1)、极大(如 65535)或重复出现可提示扫描(需结合其他工具分析) -
--tcp-option 3:WScale —— 通常只在 SYN 包中出现,若在非 SYN 包中出现,属异常 -
--tcp-option 4:SACK Permitted —— 应仅出现在 SYN 或 SYN+ACK;若在纯 ACK 或数据包中出现,可能为畸形 -
--tcp-option 8:Timestamp —— 广泛使用,但若在无 WScale 的连接中频繁携带异常 timestamp 值,可能关联反射攻击 -
--tcp-option 15:User Timeout —— 现代内核才支持,非常规,出现即可疑
示例规则(仅检测存在性):
iptables -I INPUT -p tcp --tcp-option 15 -j DROPiptables -I INPUT -p tcp ! --syn --tcp-option 3 -j REJECT --reject-with tcp-reset
真正需要字段级过滤时怎么办?
若业务场景确需基于 TCP Option 值做策略(如拦截 MSS=1 的恶意 SYN、拒绝带伪造 Timestamp Echo 的 ACK),应转向更底层或更高层方案:
- eBPF + tc 或 xdp:用 C 编写 eBPF 程序,在内核收包早期解析完整 TCP header 和 options,提取并比对字段值,再决定 drop/pass。适合高性能网关
-
用户态代理前置:如用
tcprelay或自研 TCP 代理监听端口,完成全包解析与选项校验后,再转发给真实服务 -
IDS/IPS 集成:Suricata 支持
tcp.option规则(如content:"|02 04|"; depth:2;匹配 MSS 选项头),可联动 iptables 封禁源 IP -
日志+离线分析:用
iptables -j LOG --log-tcp-options记录含选项的包,再用脚本解析/var/log/kern.log提取异常值,自动封禁 IP
实用建议:用好现有能力防典型滥用
虽然不能“按值过滤”,但组合已有模块可有效防御多数 TCP Option 滥用:
- 先用
--tcp-flags拒绝非法标志组合(如 SYN+FIN),避免畸形包进入选项解析逻辑 - 对新连接(
--syn)限制允许的选项组合:iptables -A INPUT -p tcp --syn --tcp-option 2 --tcp-option 3 -j ACCEPT,其余 SYN 包 DROP - 启用内核防护:
echo 1 > /proc/sys/net/ipv4/tcp_invalid_ratelimit降低 INVALID 状态包日志频率,配合conntrack --ctstate INVALID -j DROP - 记录带选项的可疑包供审计:
iptables -I INPUT -p tcp --dport 80 -m state --state NEW -j LOG --log-tcp-options --log-prefix "TCP-OPT-NEW: "


















