limit模块无法按源ip独立限速,仅作全局速率匹配;真正单ip限速须用hashlimit(推荐)或recent模块组合实现,如每分钟限5个新ssh连接并允许突发5次。

用 iptables 的 limit 模块直接限制“单 IP 连接速率”是常见误区——它本身不按源 IP 统计,只对匹配到的包做全局速率控制。想真正实现单 IP 级别的平滑限速,必须搭配 recent 或 hashlimit 模块。其中 hashlimit 更推荐,它是专为这类场景设计的稳定方案。
为什么 limit 模块不能单独限单 IP?
limit 模块本质是令牌桶机制,统计的是整条规则匹配的总包速率,而非每个源 IP 独立计数。比如设了 --limit 5/s,10 个不同 IP 各发 1 个 SYN 包,全会被放行;而一个攻击 IP 在 1 秒内发 10 个 SYN,也只被当作“10 个匹配包”,前 5 个拿令牌通过,后 5 个丢弃——看似限了,但没隔离 IP,无法防分布式扫描。
用 hashlimit 实现真正单 IP 限速
hashlimit 按指定维度(如 srcip)维护独立计数器,支持突发容错,适合生产环境:
-
每分钟最多 5 个新 SSH 连接:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit-above 5/min --hashlimit-burst 5 --hashlimit-mode srcip --hashlimit-name ssh -j DROP - --hashlimit-burst 5 允许短时重连(如网络抖动),避免误杀;超出后严格按 5/min 执行
-
--hashlimit-mode srcip 确保每个 IP 单独计数;若需按 /24 网段统管,可改用
--hashlimit-mask 24 - 首次部署建议先用
-j LOG替代-j DROP,检查dmesg | grep ssh确认拦截行为符合预期
搭配 recent 模块的轻量替代方案
如果系统不支持 hashlimit(较老内核),可用 recent + limit 组合模拟:
- 先标记并记录每个新连接的源 IP:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name ssh --rsource - 再限制该 IP 在 60 秒内最多触发 5 次:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name ssh --rsource --seconds 60 --hitcount 6 -j DROP - 注意:recent 规则顺序敏感,务必放在所有 ACCEPT 之前,且需配合默认策略或兜底 DROP
关键细节与避坑提示
平滑的核心在于“突发容忍 + 精确统计 + 可观测性”:
- 别只写
-j DROP,加-m comment --comment "ssh-rate-limit"方便后续排查 - limit 和 hashlimit 的
--limit-burst或--hashlimit-burst不是“上限”,而是初始令牌数,设太小会导致首连就失败 - SSH 服务本身也有防护(如
MaxAuthTries 3、LoginGraceTime 30),iptables 限速应作为第一道网关,不替代应用层加固 - 规则生效后,用
iptables -L INPUT -n -v --line-numbers查看匹配包计数,验证是否真实触发










