Nginx 负载均衡如何配置 limit_req 防止后端被 CC 攻击

文章导读
在 Nginx 负载均衡架构中,通过 http 块定义 limit_req_zone 并在 location 块启用 limit_req,是防止单一 IP 高频请求耗尽后端资源的有效方法。但必须预留 burst 空间以适应正常业务波动,同时配置白名单避免误伤运维监控流量。
📋 目录
  1. A 生产环境配置示例
  2. B 限流原理简述
  3. C 参数调优建议
  4. D 效果验证方法
  5. E 常见风险与排查
  6. F 参考来源
A A

在 Nginx 负载均衡架构中,通过 http 块定义 limit_req_zone 并在 location 块启用 limit_req,是防止单一 IP 高频请求耗尽后端资源的有效方法。但必须预留 burst 空间以适应正常业务波动,同时配置白名单避免误伤运维监控流量。

先说结论:限流是止损手段而非根治方案,适合在攻击流量特征明显且业务允许一定延迟的场景下优先部署。

  • 先判断:确认攻击是否针对特定接口或 URI,避免全局误杀。
  • 优先做:基于 $binary_remote_addr 定义限流区,设置合理的 rate 和 burst,并配置运维白名单。
  • 再验证:观察 access.log 中 503 状态码比例,确认是否影响正常用户。

生产环境配置示例

以下是包含负载均衡、白名单及限流保护的完整配置片段。请根据实际业务 QPS 调整 rate 值,并将白名单 IP 替换为实际运维网段。

http {
    # 1. 定义 IP 白名单 (geo 模块)
    geo $limit_white {
        default 0;
        10.0.0.0/8 1;      # 内网网段
        192.168.1.100 1;   # 运维堡垒机 IP
    }

    # 2. 定义限流区,key 为客户端 IP,内存 10m,速率需按业务调整
    # log_level 设为 warn 避免正常限流日志泛滥
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    limit_req_log_level warn;
    limit_req_status 503;

    # 3. 定义后端上游服务器组
    upstream backend {
        server 192.168.1.10:8080;
        server 192.168.1.11:8080;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            # 4. 白名单跳过限流
            if ($limit_white) {
                set $limit_white 0;
            }
            # 注意:if 在 location 中性能较差,生产环境建议在 http 层通过 map 或单独 server 块处理白名单
            # 更推荐写法:在 limit_req_zone 前通过 map 变量控制 key,或使用 allow/deny 指令
            
            # 5. 应用限流,允许突发 20 个请求,nodelay 表示超出 burst 立即拒绝
            limit_req zone=one burst=20 nodelay;

            # 6. 代理到后端负载均衡
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 7. 自定义 503 错误页面,避免返回默认 Nginx 页面暴露版本
        error_page 503 /503.html;
        location = /503.html {
            internal;
            root /usr/share/nginx/html;
        }
    }
}

限流原理简述

CC 攻击的本质是模拟正常用户发送大量请求,耗尽服务器连接数或 CPU 资源。Nginx 的 limit_req 模块使用漏桶算法(leaky bucket algorithm),以固定速率处理请求,多余的请求会被延迟或直接拒绝。在负载均衡前端做这一步,可以避免无效请求穿透到后端应用服务器,保护数据库和业务逻辑层。

Nginx 负载均衡如何配置 limit_req 防止后端被 CC 攻击

参数调优建议

配置中的 rate 和 burst 值不能盲目复制,需结合业务监控数据:

  • rate 计算:统计正常业务高峰期的单 IP 平均 QPS。例如正常用户每秒请求 5 次,可设置 rate=5r/s 或略高。示例中的 10r/s 仅适用于低频接口。
  • burst 设置:用于应对瞬间流量波动。若业务允许短暂排队,可设置 burst=20;若需严格保护后端,配合 nodelay 参数直接拒绝超出部分。
  • key 选择:默认使用 $binary_remote_addr。若业务存在大量 NAT 共享 IP(如移动端),可考虑结合 $http_x_forwarded_for 或 Cookie 进行更细粒度限流。

效果验证方法

配置生效后,需通过压测和日志分析验证策略是否生效且未误伤:

1. 模拟高频请求:在测试环境使用 ab 工具发起高频请求,观察是否触发 503。

ab -n 1000 -c 100 http://your-domain.com/

2. 查看限流日志:检查 Nginx error.log,搜索 "limiting requests" 关键字,确认限流触发记录。

Nginx 负载均衡如何配置 limit_req 防止后端被 CC 攻击
grep "limiting requests" /var/log/nginx/error.log

3. 监控后端负载:对比开启限流前后,后端服务器的 CPU 负载和连接数是否有明显下降。

4. 白名单验证:使用白名单内的 IP 发起高频请求,确认不应被限流(状态码应为 200 而非 503)。

常见风险与排查

1. 运维 IP 被误封:未配置白名单可能导致运维管理 IP、健康检查探针或监控系统的请求被限制,导致故障排查困难。务必在 limit_req 前通过 geo 或 allow 指令放行可信 IP。

Nginx 负载均衡如何配置 limit_req 防止后端被 CC 攻击

2. 日志泛滥:默认情况下,限流触发会记录日志。若攻击流量大,error.log 可能迅速写满。建议设置 limit_req_log_level warn 或 error,减少 info 级别日志。

3. 静态资源限流:不要对 css、js、图片等静态资源启用严格的 limit_req,否则页面加载会失败。建议仅对 API 接口或动态请求 location 启用限流。

4. Nginx 自身性能:limit_req 是在 Nginx 层处理,如果攻击流量极大,Nginx 本身可能成为瓶颈,需结合 upstream 健康检查和多节点部署,必要时接入 WAF 或 CDN 清洗流量。

参考来源