iptables防分片攻击需用-m frag模块而非length,因length仅匹配总长、无法识别首片/后续片、不能检测非法标志或偏移;frag模块配合raw表可精准丢弃带tcp标志的非首片、限速碎片洪水,并须结合nf_defrag_ipv4自动重组与状态化filter规则。

iptables 本身没有 -m length 模块用于直接限制“特定长度报文”来防范分片攻击——这是常见误解。真正起作用的是 -m frag(处理分片特征)和内核层面的 nf_defrag_ipv4 行为,而 length 模块仅匹配**整个IP数据包总长度**(含IP头),对分片攻击防护意义有限,甚至可能误伤合法小包(如ICMP echo request)或漏掉关键风险。
为什么 length 模块不适合防分片攻击
分片攻击的核心风险不在“报文长度”,而在于:
- 非首片携带非法 TCP 标志位(如 SYN/FIN/RST)
- 分片偏移不按 8 字节对齐(违反 RFC 791)
- 首片过小(如 IP 总长
- 大量碎片洪水耗尽内存或绕过状态检测
这些特征 -m length 完全无法识别。它只能告诉你“这个分片片的 IP 总长是 X”,但无法区分它是首片还是后续片,也无法检查分片标志、偏移或四层字段。
真正有效的分片防护应使用 frag 模块
-m frag 是专为分片设计的匹配模块,必须配合 -f(即 --fragment)使用,只匹配非首片。典型安全用法包括:
- 丢弃非首片中带 TCP 标志的报文(非法):
iptables -t raw -A PREROUTING -f -m tcp --tcp-flags ALL ALL -j DROP - 丢弃非首片中带 SYN/FIN/RST/ACK 的报文:
iptables -t raw -A PREROUTING -f -m tcp --tcp-flags SYN,RST,FIN,ACK SYN -j DROP - 限制单 IP 每秒分片数量(防碎片洪水):
iptables -t raw -A PREROUTING -f -m hashlimit --hashlimit-above 5/sec --hashlimit-name frag_per_ip -j DROP
补充:首片合法性检查不能只靠 length
若真需控制首片大小(例如拒绝过小首片),应结合 -m length 与 ! -f(即“非分片”或“首片”):
- 拒绝总长小于 64 字节的首片(大概率异常):
iptables -t raw -A PREROUTING ! -f -m length --length 0:63 -j DROP - 但注意:正常 ICMPv4 echo request 最小为 28 字节(IP头20 + ICMP头8),所以阈值需按协议实际调整,不宜一刀切设为 60。
必须配合 raw 表和连接状态逻辑
所有分片过滤必须在 raw 表的 PREROUTING 链完成,因为:
- 它在 conntrack 之前执行,避免非法分片触发连接跟踪失败
- filter 表中应只基于
ESTABLISHED,RELATED放行,不单独处理-f - 确保
nf_defrag_ipv4未被禁用(默认启用),让内核自动重组后再交由 filter 表做状态检查











