HAProxy 如何配置 rate limit 限制请求频率防止 CC 攻击

文章导读
HAProxy 通过 stick-table 在内存中记录源 IP 的请求频率,配合 deny 动作实现速率限制。适用于 HTTP/HTTPS 七层流量清洗,风险在于可能误伤共享出口 IP 的正常用户。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

HAProxy 通过 stick-table 在内存中记录源 IP 的请求频率,配合 deny 动作实现速率限制。适用于 HTTP/HTTPS 七层流量清洗,风险在于可能误伤共享出口 IP 的正常用户。

先说结论:HAProxy 防 CC 攻击的核心是使用 stick-table 统计请求频率并触发拒绝策略。

  • 先判断:确认攻击流量特征是基于 IP 高频请求还是特定 URL 高频访问。
  • 优先做:在 frontend 段落定义 stick-table 并设置 http_req_rate 阈值。
  • 再验证:通过日志观察被拒绝请求的状态码及来源 IP 分布。

命令速用版

以下配置片段可直接放入 HAProxy 配置的 frontend 段落,实现每 10 秒内单 IP 超过 100 请求则拒绝。

frontend http_front
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }

为什么会这样

stick-table 是 HAProxy 内置的键值存储结构,专门用于保存 counters。

HAProxy 在处理请求时会将指定条件(如源 IP)作为 key 存入表格,并自动累加请求计数。当计数超过设定阈值时,触发 deny 动作直接断开连接,无需后端服务器参与,从而保护后端资源。

分步处理

步骤 1:定义 stick-table

在 frontend 或 backend 段落开头定义表格类型和存储内容。type ip 表示按 IP 存储,store http_req_rate(10s) 表示统计 10 秒内的请求速率。

步骤 2:追踪请求源

使用 http-request track-sc0 src 命令告诉 HAProxy 将当前请求的源 IP 记录到索引为 0 的 stick-table 中。

步骤 3:设置拒绝规则

使用 http-request deny 配合 fetch 表达式 sc_http_req_rate(0) 读取计数。gt 100 表示超过 100 次即拒绝。deny_status 429 返回 Too Many Requests 状态码。

步骤 4:重载配置

执行 haproxy -c -f /etc/haproxy/haproxy.cfg 检查语法,确认无误后 systemctl reload haproxy 生效。

HAProxy 如何配置 rate limit 限制请求频率防止 CC 攻击

怎么验证是否生效

查看 HAProxy 日志中是否出现状态码 429 的记录。

使用压测工具或脚本对同一 IP 发起高频请求,观察超过阈值后是否立即返回 429。同时监控 HAProxy 进程内存占用,确认 stick-table 未导致内存异常增长。

常见坑

NAT 环境误伤:如果用户处于大型 NAT 网关后(如公司出口、移动网络),多个用户共享一个公网 IP,速率限制可能误封正常用户。

内存消耗:stick-table 存储在内存中,size 设置过大会消耗过多内存,设置过小会导致旧数据过早淘汰,需根据并发 IP 数量调整。

SSL 终止位置:如果 HAProxy 前端是 TCP 模式且未终止 SSL,无法获取 HTTP 请求频率,必须在 backend 或 SSL 终止后的 frontend 配置。

常见问题

如何给特定 IP 设置白名单?

使用 ACL 匹配可信 IP 段并在 deny 规则前跳过。

配置 acl is_whitelist src 192.168.1.0/24,然后在 deny 行添加 if !{ is_whitelist } 条件。

限制特定 URL 而不是全局限速怎么办?

将 track-sc 和 deny 规则放在特定的 backend 或使用 path 匹配 ACL。

在 http-request 规则中增加 if { path_beg /api } 条件,仅对特定路径启用限速。

stick-table 数据重启后会丢失吗?

是的,stick-table 数据仅存储在内存中,重启 HAProxy 后计数器清零。

这属于正常设计,防 CC 主要关注实时流量,无需持久化历史数据。

参考来源

  • HAProxy Technologies, "HAProxy Configuration Manual", https://www.haproxy.com/documentation/haproxy-configuration-manual/
  • HAProxy Technologies, "Stick Tables", https://www.haproxy.com/documentation/hapee/latest/configuration/section-7.html#7.2