iptables -m hashlimit 仅负责按源ip动态限流标记,不能实现qos调度;真正达成“人人平等并发限速”需与tc协同:hashlimit识别异常流量并标记,tc基于标记为各ip分配独立带宽通道。

直接说结论:iptables -m hashlimit 本身不能“开辟管道”,也不能做 QoS(服务质量)调度,它只负责按源 IP 动态建桶、计数、匹配;真正实现“人人平等的并发限速”需要它 + tc(Traffic Control)协同完成——hashlimit管“谁该被限”,tc 管“怎么限、限多严”。
下面分三块讲清楚怎么做、为什么这样设计、以及最容易翻车的点:
一、hashlimit 负责“识别并标记异常流量”
它不是限速器,而是“智能守门人”:对每个源 IP 维护一个独立令牌桶,只判断“这个 IP 当前是否超速”,然后打上“放行”或“待处理”标签。
- 用 --hashlimit-mode srcip 确保每个用户(即每个真实客户端 IP)独享一个桶,互不干扰
- 用 --hashlimit-above 10/sec 表示每秒最多允许 10 个新建连接(或请求包),超过就触发匹配
- 用 --hashlimit-burst 30 允许短时突发(比如页面加载瞬间发多个 AJAX),避免误伤正常用户
- 必须配 -j ACCEPT 放行合规流量,再紧跟一条无条件 -j DROP 拦截超限者——否则规则形同虚设
二、tc 负责“为每个 IP 开辟专属带宽通道”
hashlimit 只能决定“要不要丢包”,但无法控制发包节奏、延迟、队列深度。这些才是 QoS 的核心,必须交给 tc。
- 先用 iptables 的 -j MARK 或 -j CONNMARK 把不同源 IP 的流量打上唯一标记(如 mark 101 对应 192.168.1.101)
- 再用 tc qdisc add ... htb 创建根队列,分配总出口带宽(如 100Mbit)
- 用 tc class add ... classid 1:101 为每个标记创建子类,设定各自 rate(如 2Mbit)和 ceil(如 3Mbit)
- 最后用 tc filter add ... fw 把 mark 值映射到对应 class,实现“一人一管道”
三、关键细节与避坑指南
很多人以为加几条 hashlimit 就能“人人平等”,结果发现限速不准、IP 串桶、或者根本压不住流量——问题基本出在这几处:
- 不要混用 --hashlimit-name:同一个名字 = 同一个哈希表 = 多个规则共享桶。每个限速策略必须用唯一 name(如 login-rate、api-rate)
- INPUT 链限的是进来的连接请求,OUTPUT 链限的是出去的响应:若想控用户下载速度,得在 OUTPUT 链用 --hashlimit-mode dstip(因为响应包目的 IP = 用户 IP)
- hashlimit 不感知字节量:它统计的是“包数量”,不是“带宽 Mbps”。想控实际网速,必须靠 tc 整形;hashlimit 只适合做前置防刷(如防暴力登录、防爬虫)
- 长期运行要清理空闲条目:加 --hashlimit-htable-expire 60000(单位毫秒),防止哈希表占满内存
不复杂但容易忽略。











