4. iptables 限速实战:hashlimit、connlimit、recent 模块

限速这件事,说白了就是跟攻击流量抢时间。你想想看,DDoS 打过来的时候,带宽和连接数都是有限的,谁先占住资源谁就赢。iptables 里这三个模块——hashlimit、connlimit、recent——就是我手头最常用的三板斧。

我个人习惯把它们分成两类:连接数控制和速率控制。connlimit 管连接数,hashlimit 和 recent 管速率。今天咱们一个一个拆开讲。

4.1 connlimit:限制单 IP 并发连接数

connlimit 模块干的事很简单——限制单个源 IP 能建立的并发连接数。我在项目中遇到过不少 SYN Flood 变种,攻击者用大量伪造 IP 打满服务器连接表,这时候 connlimit 就是第一道防线。

4.1.1 基本用法

# 限制每个 IP 最多 20 个并发 SSH 连接
iptables -A INPUT -p tcp --dport 22 -m connlimit \
  --connlimit-above 20 -j DROP

# 限制每个 IP 最多 100 个并发 HTTP 连接
iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 100 -j DROP

这里要注意,--connlimit-above 的意思是“超过这个数就丢包”。所以 20 表示允许 20 个,第 21 个开始被拒绝。

4.1.2 掩码匹配

有时候攻击者用同一个 C 段 IP 打你,一个一个限制太麻烦。connlimit 支持掩码匹配:

# 限制 /24 网段最多 200 个并发连接
iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 200 --connlimit-mask 24 -j DROP
我的经验:connlimit 对 CC 攻击效果不错,但对真正的分布式攻击(每个 IP 只发几个连接)就力不从心了。这时候需要配合 hashlimit 一起用。

4.2 hashlimit:精细化速率控制

hashlimit 是我最喜欢的一个模块。它用哈希表来跟踪每个 IP 的流量速率,能做到非常精细的控制。说白了,就是给每个 IP 单独记一笔账,超了就限速。

4.2.1 核心参数

参数 作用 示例
--hashlimit-above 触发限速的阈值 10/minute
--hashlimit-burst 允许的突发量 20
--hashlimit-mode 匹配维度 srcip, dstip, srcport, dstport
--hashlimit-name 哈希表名称 httplimit
--hashlimit-htable-size 哈希表大小 100000

4.2.2 实战配置

我记得有一次客户被 HTTP Flood 打得服务器 CPU 飙到 100%,我上去配了这么一条规则:

# 每个源 IP 每分钟最多 30 个 HTTP 请求,允许突发 50 个
iptables -A INPUT -p tcp --dport 80 -m hashlimit \
  --hashlimit-above 30/minute \
  --hashlimit-burst 50 \
  --hashlimit-mode srcip \
  --hashlimit-name http_limit \
  -j DROP

为什么要设 burst?因为正常用户偶尔会快速刷新页面,burst 就是给这种正常行为留的缓冲。我曾经见过有人把 burst 设成 0,结果正常用户刷新一下就断了,投诉电话被打爆。

4.2.3 多维度匹配

hashlimit 可以同时匹配多个维度,比如按源 IP + 目标端口:

# 每个源 IP 对每个目标端口,每分钟最多 10 个连接
iptables -A INPUT -p tcp -m hashlimit \
  --hashlimit-above 10/minute \
  --hashlimit-mode srcip,dstport \
  --hashlimit-name port_limit \
  -j DROP
避坑指南:我曾经在生产环境把 --hashlimit-htable-size 设得太小,结果哈希冲突导致正常用户被误杀。建议至少设成 100000,如果服务器内存够大,可以设到 500000。

4.3 recent:动态黑名单机制

recent 模块跟前面两个不太一样。它更像一个动态的黑名单系统——记录每个 IP 最近的活动,然后根据历史行为做判断。

4.3.1 工作原理

recent 维护一个 IP 地址列表,你可以往里面加 IP、查 IP、删 IP。每次匹配到规则,它就会更新这个列表。我常用它来做“三次犯规就封禁”的逻辑。

# 第一步:记录 SSH 登录失败的 IP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
  -m recent --name ssh_brute --set

# 第二步:如果这个 IP 在 60 秒内出现超过 4 次,就封禁 300 秒
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
  -m recent --name ssh_brute --update \
  --seconds 60 --hitcount 4 -j DROP \
  -m comment --comment "SSH brute force protection"

4.3.2 常用参数

参数 说明
--set 将源 IP 加入列表
--update 更新列表中的时间戳
--seconds 统计时间窗口
--hitcount 触发阈值
--name 列表名称
--rcheck 只检查不更新
--remove 从列表中移除

4.3.3 实战:防暴力破解

嗯,这里要注意顺序。recent 的规则必须两条配合:第一条负责记录,第二条负责判断。我曾经见过有人只配了第二条,结果 IP 从来没被记录过,规则形同虚设。

# 更完整的防暴力破解方案
iptables -N SSH_CHECK

# 记录新连接
iptables -A SSH_CHECK -m recent --name ssh_brute --set

# 检查是否超限
iptables -A SSH_CHECK -m recent --name ssh_brute \
  --rcheck --seconds 60 --hitcount 4 -j LOG \
  --log-prefix "SSH_BRUTE: "

iptables -A SSH_CHECK -m recent --name ssh_brute \
  --rcheck --seconds 60 --hitcount 4 -j DROP

iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
  -j SSH_CHECK
核心思路:connlimit 管并发,hashlimit 管速率,recent 管历史行为。三者配合使用,基本能挡住 90% 以上的应用层攻击。

4.4 三模块对比与选型

模块 适用场景 优势 劣势
connlimit 连接数型攻击 配置简单,资源消耗低 无法控制请求速率
hashlimit 请求速率型攻击 精细化控制,支持突发 内存消耗较大
recent 暴力破解、慢速攻击 动态封禁,灵活性强 需要两条规则配合
iptables 限速三模块知识体系 iptables 限速模块 connlimit 限制并发连接数 --connlimit-above --connlimit-mask hashlimit 精细化速率控制 --hashlimit-above --hashlimit-burst --hashlimit-mode recent 动态黑名单 --set / --update --seconds / --hitcount 选型建议 连接数攻击 → connlimit 速率攻击 → hashlimit 暴力破解/慢速攻击 → recent

4.5 组合实战:三层防御

你想想看,真正的攻击不会只打你一层。所以我一般会把这仨模块叠起来用:

# 第一层:connlimit 限制并发
iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 100 -j DROP

# 第二层:hashlimit 限制速率
iptables -A INPUT -p tcp --dport 80 -m hashlimit \
  --hashlimit-above 30/minute \
  --hashlimit-burst 50 \
  --hashlimit-mode srcip \
  --hashlimit-name http_rate \
  -j DROP

# 第三层:recent 动态封禁
iptables -A INPUT -p tcp --dport 80 -m recent \
  --name http_abuse --set
iptables -A INPUT -p tcp --dport 80 -m recent \
  --name http_abuse --rcheck \
  --seconds 120 --hitcount 10 -j DROP
我的习惯:三层规则按顺序执行,第一层过滤掉明显异常的连接,第二层压制速率,第三层收拾顽固分子。这样每层压力都不大,性能损耗也小。

好了,这三个模块的用法和实战配置就讲到这里。记住一点:限速不是目的,让正常用户不受影响才是。配置的时候多想想正常用户的行为模式,别把自己人拦在外面。