iptables的-m hashlimit不提供分布式能力,仅单机内核维护哈希表与令牌桶,但可通过合理设计实现类分布式per-ip或per连接限速——关键在哈希桶隔离粒度与accept+drop闭环链路。

iptables 的 -m hashlimit 本身不提供“分布式”能力,它只在单机内核态维护哈希表与令牌桶,但可以通过合理设计实现**类分布式效果的高效 per-IP 或 per-连接维度限速**——关键在于“哈希桶”的隔离粒度和规则链路闭环。下面直接说清楚怎么做、为什么有效、容易踩哪些坑。
明确限速目标与匹配维度
hashlimit 的核心是“谁和谁分开限”。不是所有模式都适用:
- srcip:最常用,每个客户端 IP 独立一个令牌桶,适合防单 IP 恶意刷量
- srcip,dstport:同一 IP 访问不同端口(如 8080 和 9000)走不同桶,适合多租户共用主机
- srcip,srcport:区分同一 IP 下不同源端口(比如浏览器多个标签页或 SDK 连接池),极少用,开销略高
- 避免单独用 dstip 或 dstport:无法锁定攻击源,限流失去意义
构建完整限速链路(必须两步闭环)
hashlimit 只是“匹配器”,不能直接丢包。必须配对使用 ACCEPT + DROP:
- 先写一条带
-m hashlimit的规则,匹配成功则-j ACCEPT - 紧接着写一条无条件
-j DROP规则(位置必须在 ACCEPT 后面) - 否则未匹配包会继续走默认策略,限速完全失效
示例(限制 HTTP 接口每 IP 每秒最多 15 请求,突发容许 45):
iptables -A INPUT -p tcp --dport 8080 -m hashlimit \ --hashlimit-name api-per-ip \ --hashlimit 15/sec \ --hashlimit-burst 45 \ --hashlimit-mode srcip \ -j ACCEPT iptables -A INPUT -p tcp --dport 8080 -j DROP
调优令牌桶参数:速率与突发的平衡
两个参数决定实际效果:
-
--hashlimit 15/sec:每秒补充 15 个令牌 → 长期平均上限为 15 包/秒(注意:单位是“包”,不是字节或请求体大小) -
--hashlimit-burst 45:桶最大容量 45 → 允许短时集中请求(如页面加载触发多个 AJAX) - burst 太小(如=1)会导致首屏卡顿;太大(如=200)会让限流形同虚设
- 若需按字节限速(如限带宽),需换算:500Mbps = 62.5MB/s ≈ 62500kb/s,再结合
--hashlimit-upto使用
验证与长期可用性保障
上线后不能只看规则是否存在:
- 查实时状态:
cat /proc/net/ipt_hashlimit/api-per-ip,能看到各 IP 当前令牌余量和最后匹配时间 - 压测验证:
for i in {1..50}; do curl -s -o /dev/null http://localhost:8080/test & done,观察是否在第 46 次开始失败 - 持久化保存:
iptables-save > /etc/sysconfig/iptables(CentOS/RHEL)或netfilter-persistent save(Debian/Ubuntu) - 避免命名冲突:每个
--hashlimit-name必须唯一,否则多个规则共享同一个桶,导致误限或漏限











