iptables 的 -m length 无法精准防御分片溢出攻击,因其仅匹配单个分片长度而非重组后总长;应结合 raw 表拦截非法分片、conntrack 状态控制及禁用自动重组来实现可靠防护。

iptables 本身不提供 -m length 模块直接匹配分片报文的“总重组后长度”,更不能靠单个分片的 IP 头长度字段(如 ip_len)精准识别溢出攻击。关键误区在于:攻击者常利用 IP 分片绕过基于首片长度或 payload 长度的简单检测,而 -m length 只能匹配当前分片的 IP 总长度字段(即该分片自身在 wire 上的字节数),它不反映原始未分片包的真实载荷大小,也无法触发重组后检查。
真正有效的拦截,必须结合分片行为特征、连接状态逻辑与内核处理机制,而非依赖单一 length 匹配。
以下是在实战中可靠、可落地的配置思路:
明确分片报文的长度陷阱
- 每个分片的 IP 头中
Total Length字段只表示 该分片自身 的字节数(含 IP 头 + 分片数据),不是原始包长度。 - 后续分片(
More Fragments=1或Fragment Offset>0)通常很短(如 8–24 字节纯 IP 头+偏移),-m length --length 20:60这类规则极易误放或误杀。 - 攻击者可构造大量极小分片(如 offset=0, len=28)拼接超长恶意 payload,但每个分片都“合法”通过 length 检查。
所以:不要用 -m length 做主防御手段,它无法替代分片语义分析。
用 raw 表提前拦截可疑分片组合
raw 表在 conntrack 之前执行,是唯一能对原始分片做策略干预的位置:
# 1. 丢弃非法 TCP 标志位的非首片(RFC 793 明确禁止) iptables -t raw -A PREROUTING -f -m tcp --tcp-flags ALL FIN,SYN,RST,PSH,ACK,URG -j DROP # 2. 丢弃分片偏移非 8 字节整数倍的分片(违反 RFC 791,大概率是畸形或攻击) iptables -t raw -A PREROUTING -f -m frag --fragid 0 --fragoff ! 0:8 -j DROP # 3. 限制单 IP 每秒分片数量(防碎片洪水) iptables -t raw -A PREROUTING -f -m hashlimit \ --hashlimit-above 5/sec \ --hashlimit-burst 10 \ --hashlimit-mode srcip \ --hashlimit-name frag_per_ip \ -j DROP
这些规则直击分片攻击的常见手法:伪造标志位、构造非法偏移、耗尽内存重组缓冲区。
在 filter 表中拒绝“无状态”的分片访问
确保 filter 表不因 -f 单独放行而绕过连接跟踪:
# ✅ 正确:只允许已建立或相关连接(RELATED 已涵盖合法后续片) iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # ✅ 正确:NEW 连接仅检查首片(有完整四层头) iptables -A INPUT -p tcp --dport 80 --syn -m conntrack --ctstate NEW -j ACCEPT # ❌ 错误:禁止这种写法(会放行任意分片,绕过状态检查) # iptables -A INPUT -f -j ACCEPT
若某服务确实需接收大包(如 NFS、SMB),应在应用层启用 TCP Segmentation Offload (TSO) 或 Generic Receive Offload (GRO),并配合内核参数调优(如 net.ipv4.ipfrag_high_thresh),而非在 iptables 中放宽分片过滤。
补充:禁用自动重组以获得完全控制权
当部署 IDS/IPS 或需深度检测时,关闭内核自动重组更安全:
# 临时禁用 IPv4 分片重组(需 root) echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu # 或永久生效(写入 /etc/sysctl.conf): # net.ipv4.ip_no_pmtu_disc = 1 # net.netfilter.nf_conntrack_frag6_timeout = 0
此时所有分片均保持原始形态进入 raw/filter 表,避免 nf_defrag_ipv4 模块“悄悄重组”带来的检测盲区。
不复杂但容易忽略


















