iptables无法用--tcp-flags过滤GRE或ICMP的“非标准标志”,因二者均无TCP类状态字段;防御应聚焦封禁协议号47、限制可信源与包长、限速ICMP请求,并辅以模块禁用和日志监控。

iptables 不能像过滤 TCP 那样用 --tcp-flags 检查 GRE 或 ICMP 的“非标准标志”,因为 GRE 没有标志位概念,ICMP 也没有类似 TCP 的状态字段。防御重点不是识别“异常报文结构”,而是控制行为、来源和上下文。
封禁协议号是最直接有效的 GRE 防御
GRE 协议号为 47,若业务中完全不使用 GRE 隧道(如无 IPsec over GRE、无企业级 MPLS 封装需求),最稳妥的方式是全局禁止:
iptables -A INPUT -p gre -j DROPiptables -A FORWARD -p gre -j DROP
这条规则会丢弃所有进入和转发的 GRE 包,无需解析内容,零误判,且内核处理开销极低。配合云安全组或边界防火墙同步关闭协议号 47,效果更彻底。
限制 GRE 流量来源与长度做基础筛查
若必须保留部分 GRE(例如只允许某台出口路由器发起隧道),可组合源地址与包长过滤:
- 仅允许可信设备发来的 GRE:
iptables -A INPUT -p gre -s 192.168.10.1 -j ACCEPT,再加一条-j DROP拒绝其余所有 - 拦截明显畸形的短包(合法 GRE 至少含 20 字节 IP 头 + 4 字节 GRE 头 = 24 字节,实际常 ≥28):
iptables -A INPUT -p gre -m length --length 0:24 -j DROP
注意:不要依赖 u32 或 iprange 去匹配 GRE 头部 Flags/Version 字段——这些字段无“非法组合”定义,且攻击者可轻易构造符合 RFC 的 GRE 包绕过检测。
针对 ICMP 隧道:聚焦载荷长度与频率异常
ICMP 隧道(如 PingTunnel、icmpsh)依赖扩展载荷传输数据,正常 ping 默认 32–64 字节,而隧道包常达数百甚至上千字节:
- 限制单个 ICMP 请求载荷上限:
iptables -A INPUT -p icmp --icmp-type echo-request -m length --length 65:65535 -j DROP - 对 ICMP 请求限速防探测:
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 3/minute --limit-burst 3 -j ACCEPT,之后接-j DROP
该策略不影响日常连通性检测,但能大幅增加 ICMP 隧道建立成本。需注意:Windows 默认 ping 载荷为 32 字节,Linux 为 56 字节,建议阈值设为 65 字节以上较稳妥。
补充手段:禁用内核模块 + 日志监控
单纯 iptables 规则无法替代纵深防御:
- 卸载 GRE 内核模块(永久生效需修改
/etc/modprobe.d/blacklist.conf):rmmod ip_gre;确认无残留:lsmod | grep gre - 开启 GRE/ICMP 日志便于溯源:
iptables -A INPUT -p gre -j LOG --log-prefix "GRE_BLOCKED: ",再接 DROP - 定期检查异常连接:
conntrack -p gre查看是否出现大量瞬时、单向、无响应的 GRE 条目
真正有效的防御不在“识别非标报文”,而在缩小暴露面、收紧通信上下文、叠加日志与模块级控制。

















