iptables -m length 拦截超大包的关键是依据各服务正常通信的合理长度上限精准设限,而非简单按大小判断危险性;需结合协议特征(如SSH≤1500、DNS UDP≤512)、连接状态(仅NEW)、分片控制(raw表丢弃-f)及先LOG后DROP验证,避免误伤合法大包。

直接用 iptables -m length 拦截超大包,关键不是“越大越危险”,而是看它是否超出该服务在正常通信中可能出现的合理长度上限。真实业务流量有明确的长度分布特征,异常大包往往出现在扫描探测、畸形构造或分片攻击场景中,而 length 模块能以极低开销快速筛出这类可疑数据。
先明确各服务端口的典型合法最大长度
不同协议和服务对单包长度容忍度差异很大,不能统一设限:
- SSH(22端口):标准握手和交互极少超过 1500 字节;若出现 >1500 字节的 TCP 包(非分片),大概率是填充探测或畸形协商,可设阈值 1501
- HTTPS/TLS(443端口):ClientHello 最大常见长度约 512 字节;完整证书链响应可能达 4096 字节,但客户端发起的请求包极少超过 2048 字节,建议按 2049–65535 拦截
- DNS(53端口):UDP 查询严格 ≤512 字节(RFC 1035);TCP DNS 查询/响应可更大,但常规业务很少超 4096 字节;对 UDP 流量可直接封禁 513+ 字节请求
- ICMP/ICMPv6:IPv4 Echo Request 通常 ≤84 字节;ICMPv6 Echo Request(type 128)推荐上限 1280 字节,超长者多为探测载荷
结合协议状态与标志位,避免误伤正常大包
仅靠长度会误拦合法大数据包(如 TLS 证书下发、大文件上传 ACK 确认)。必须叠加上下文条件:
- 只针对新建连接的首几个包做长度检查:
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -m length --length 1501:65535 -j DROP - 排除已建立连接的数据流(它们本就允许大段传输):
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT(这条规则应放在所有 length 规则之前) - 对 UDP 服务限制更严,因无连接状态:可加端口白名单,如放行 DNS 响应但拦截异常长请求:
iptables -A INPUT -p udp --dport 53 -m length --length :4096 -j ACCEPT,再接一条-j DROP拦截其余
区分分片与非分片,防止绕过
攻击者常利用 IP 分片规避检测——首片含协议头,后续片无 TCP/UDP 头,length 值仅为净载荷长度。因此:
- 若业务不依赖大分片,可在 raw 表直接丢弃所有分片:
iptables -t raw -A PREROUTING -f -j DROP - 若需保留首片检测能力,可单独匹配非分片大包:
iptables -A INPUT ! -f -p tcp --dport 443 -m length --length 2049:65535 -j DROP - 注意:启用此策略前,需确认内核未自动重组分片(
net.ipv4.ip_defrag_max_dist=0或禁用 nf_defrag_ipv4)
上线前务必记录验证,再切换为拦截
直接 DROP 可能影响业务,尤其对定制化或老旧设备。推荐三步走:
- 先记录疑似超长包:
iptables -I INPUT -m length --length 1501: -j LOG --log-prefix "BIGPKT-ALERT: " - 持续观察 24 小时,用
journalctl -k | grep BIGPKT或dmesg查看日志,确认无真实业务包落入该范围 - 确认无误后,将 LOG 替换为 DROP:
iptables -R INPUT 1 -m length --length 1501: -j DROP

















