iptables recent模块是内核级轻量ip时间窗口计数器,不支持ip信誉评分或动态扩容,仅能通过--set/--update/--rcheck等参数实现基于频次的渐进式封禁(如60秒5次即封),需配合connlimit、日志分析脚本等达成完整防护。

Iptables 的 recent 模块本身不支持“IP信誉度”或“动态扩容”这类高级语义,它只是一个轻量级、无状态的 IP 地址时间窗口计数器。所谓“基于IP信誉度的自动化防火墙动态扩容”,实际是对 recent 的常见误读或概念包装——recent 无法评分、无法学习、无法联动外部系统,也不具备自动伸缩规则表的能力。
但你可以用 recent 搭配其他机制,模拟出接近“动态响应”的行为。关键在于:把“信誉度”映射为可检测的行为特征(如连接频次、失败次数、请求间隔),再通过多阶段规则链实现分级处置。以下是真正可行、生产环境验证过的做法:
✅ 明确目标:用 recent 实现“行为驱动的渐进式封禁”
不是给 IP 打分,而是根据其最近一段时间内的异常行为强度,决定是否临时限速、临时拒绝、或长期拉黑。
1. 分阶段标记异常行为(用不同 --name 隔离逻辑)
# 阶段1:60秒内 SSH 新连接 ≥ 5 次 → 记入 "ssh-suspicious" -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --set --name ssh-suspicious --rsource -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --update --seconds 60 --hitcount 5 --name ssh-suspicious --rsource \ -j DROP # 阶段2:600秒内 SSH 新连接 ≥ 20 次 → 记入 "ssh-blocked"(更长周期+更高阈值) -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --set --name ssh-blocked --rsource -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --update --seconds 600 --hitcount 20 --name ssh-blocked --rsource \ -j DROP
✅ 说明:两个独立
--name列表互不干扰,实现“轻度异常先警告(实际是静默限流),重度异常直接拦截”。
2. 结合 connlimit 做并发控制(防扫描型暴力)
# 单 IP 同时最多 3 个 SSH 连接(防爆破工具维持大量连接) -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j REJECT --reject-with tcp-reset
3. 自动“降级”与“恢复”(靠时间窗口自然过期)
recent 不需要手动清理 —— 只要不匹配 --update 或 --rcheck,超时后条目自动失效。
例如 --seconds 60 的列表,某 IP 在第 0 秒触发一次,之后 60 秒内无新包,则第 61 秒起该 IP 不再命中 --update 规则,等同于“信誉恢复”。
⚠️ 注意:
recent条目默认最大容量为 100(内核参数net.netfilter.nf_conntrack_max无关,recent用独立哈希表),超限时旧条目被轮替。如需更大容量,需加载模块时指定:modprobe xt_recent ip_list_tot=5000
4. 真正的“动态扩容”要靠外部脚本(非 iptables 原生能力)
若你真需要“IP信誉库联动”或“自动扩容规则”,必须用脚本监听日志 + 调用 iptables -A/-D:
- 用
fail2ban监控/var/log/secure,识别密码失败; - 成功后执行:
iptables -I INPUT -s $BAN_IP -j DROP并写入持久化文件; - 配合
cron定期清理过期 IP(如 24 小时后自动解封)。
? 本质:
recent是内核态快速缓存,fail2ban/自定义脚本才是用户态决策中枢。二者分工明确,不可混淆。
❌ 常见误区澄清
-
recent不存储“信誉分数”:它只记“出现过几次+最后时间”,没有加权、衰减、历史累计等概念。 - 不能“扩容规则链”:iptables 规则链长度固定,新增规则只是追加到链尾,不是“扩容”防火墙能力。
-
--rttl不是防伪装万能钥匙:仅当攻击者 TTL 与正常用户明显不同时有效(如扫描器用固定 TTL=64,而真实客户端 TTL 随系统变化),多数场景意义有限。
✅ 最小可行方案(SSH 保护示例)
# 允许已建立连接(必须放最前) -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许本地和管理网段 -A INPUT -s 127.0.0.1 -j ACCEPT -A INPUT -s 192.168.1.0/24 -j ACCEPT # recent 阶段限流(60秒5次即封) -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --set --name ssh-try --rsource -A INPUT -p tcp --dport 22 -m state --state NEW \ -m recent --update --seconds 60 --hitcount 5 --name ssh-try --rsource \ -j DROP # 默认拒绝 -P INPUT DROP
保存后运行:
iptables-save > /etc/iptables/rules.v4 # Debian/Ubuntu # 或 service iptables save # CentOS 6
不复杂但容易忽略:规则顺序决定一切,--set 必须在 --update 前;ESTABLISHED 规则必须优先;DROP 放最后。











