HTTP 洪水攻击防御实战:Nginx 多层限流配置方案

适用场景

HTTP 洪水攻击(HTTP Flood)是 DDoS 攻击最常见形式之一。攻击者通过大量肉鸡或云服务发起海量看似合法的 GET/POST 请求,耗尽服务器的 CPU、内存或带宽资源,导致正常用户无法访问。本文适用于Nginx 反向代理环境的 Web 应用防护,包括各类 CMS、API 服务及电商平台。

前置条件

  • Nginx 1.18+(已编译 ngx_http_limit_req_module 和 ngx_http_limit_conn_module)
  • Python 3.6+(用于日志分析脚本)
  • 服务器 root 权限

原理说明

HTTP 洪水与 Slowloris(慢速攻击)不同:Slowloris 通过保持连接不关闭耗尽连接池,而 HTTP 洪水以极快速度发送完整 HTTP 请求。关键区别在于请求速率(RPS)请求特征分布。防御的核心是对比正常用户行为基线,识别异常高频访问并实施限流。

操作步骤

步骤一:Nginx 基础限流配置

首先在 nginx.conf 的 http 块中定义限流区域:

# /etc/nginx/nginx.conf -- http 块内

# 请求速率限制区域:基于客户端 IP
# rate=30r/s -- 平均每秒最多 30 个请求
# burst=50 -- 允许突发 50 个请求的缓冲
# nodelay -- 不延迟处理突发请求(超出直接拒绝)
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=30r/s;

# 并发连接数限制:每个 IP 最多 20 个并发连接
limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;

# 服务器级别速率限制(全局限流)
limit_req_zone $server_name zone=global:10m rate=500r/s;

然后在特定 server/location 块中启用:

# /etc/nginx/conf.d/default.conf -- server 块内

server {
    listen 443 ssl;
    server_name your-site.com;

    limit_req zone=per_ip burst=50 nodelay;
    limit_conn conn_per_ip 20;
    limit_req zone=global burst=1000 nodelay;

    limit_req_status 429;
    limit_conn_status 429;

    error_page 429 /429.html;
    location = /429.html {
        root /var/www/html;
        internal;
    }

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 对登录/API 接口实施更严格限制
    location /wp-login.php {
        limit_req zone=per_ip burst=5 nodelay;
        limit_conn conn_per_ip 5;
        proxy_pass http://backend;
    }

    location /api/ {
        limit_req zone=per_ip burst=10 nodelay;
        limit_conn conn_per_ip 10;
        proxy_pass http://backend_api;
    }
}

步骤二:UA 与请求特征过滤

攻击者常使用固定或明显伪造的 User-Agent。在 Nginx 中实施UA 黑名单

# UA 黑名单映射
map $http_user_agent $bad_ua {
    default 0;
    "~*curl" 1;
    "~*wget" 1;
    "~*python-requests" 1;
    "~*Go-http-client" 1;
    "~*Java/" 1;
    "~*libwww-perl" 1;
    "~*HTTPie" 1;
    "" 1;
}

server {
    if ($bad_ua) { return 403; }
}

注意:UA 过滤应谨慎使用,避免误伤爬虫和 API 客户端。更精确的做法是基于请求频率 + UA 组合判定。

步骤三:基于请求路径的精细化限流

limit_req_zone $binary_remote_addr zone=static:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=dynamic:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=search:10m rate=5r/s;

server {
    # 静态资源 -- 放宽限制
    location ~* \\.(jpg|jpeg|png|gif|css|js|ico|woff2?)$ {
        limit_req zone=static burst=200 nodelay;
        expires 30d;
        add_header Cache-Control "public";
    }

    # 动态页面 -- 适中限制
    location / {
        limit_req zone=dynamic burst=20 nodelay;
    }

    # 搜索/查询 -- 严格限制
    location ~* /(search|query|s\\.php) {
        limit_req zone=search burst=5 nodelay;
    }
}

步骤四:日志分析脚本

以下 Python 脚本分析 Nginx access.log,识别高频请求 IP 和攻击特征:

#!/usr/bin/env python3
"""
Nginx HTTP Flood 攻击特征分析脚本
用法: python3 flood_detect.py /var/log/nginx/access.log
"""
import sys, re, collections

LOG_PATTERN = re.compile(
    r'(?P[\d.]+) .* \[(?P

步骤五:自动封禁脚本

#!/bin/bash
# auto_ban.sh -- 自动封禁高频 IP
LOG="/var/log/nginx/access.log"
BAN_LIST="/etc/nginx/conf.d/ban_ip.conf"
THRESHOLD=500
WINDOW=60

python3 flood_detect.py "$LOG" "$WINDOW" "$THRESHOLD" | grep "高频攻击" | \
    awk '{print $1}' | while read ip; do
    if ! grep -q "$ip" "$BAN_LIST" 2>/dev/null; then
        echo "deny $ip;" >> "$BAN_LIST"
        echo "[BAN] $ip"
    fi
done

nginx -s reload

建议将此脚本加入 cron,每 5 分钟执行一次:

*/5 * * * * /usr/local/bin/auto_ban.sh >> /var/log/auto_ban.log 2>&1

配置验证

# 1. 检查 Nginx 配置语法
nginx -t

# 2. 使用 ab 模拟高频请求
ab -n 1000 -c 50 https://your-site.com/

# 3. 测试单 IP 限流
for i in $(seq 1 100); do
    curl -s -o /dev/null -w "%{http_code}\\n" https://your-site.com/ &
done
# 正常应看到部分 429

# 4. 检查 access.log 中的 429 记录
grep "429" /var/log/nginx/access.log | head -10

常见问题

Q1: limit_req 的 burst 和 nodelay 如何配合?

burst=N 允许瞬时超过 rate 的请求先排队,超过 N 的直接拒绝。不加 nodelay 时,排队请求会按 rate 速度被处理(导致延迟)。加上 nodelay 后,排队请求立即被处理,但超出 burst 的请求直接拒绝。推荐对 API 服务使用 nodelay,对正常页面访问可以不加 nodelay 以获得更平滑的限流效果。

Q2: 限流后如何区分正常用户爆发与攻击?

关注三个特征:请求路径分布(攻击者通常集中在少数几个路径)、User-Agent 多样性(攻击者 UA 往往单一或明显伪造)、来源 IP 分布(正常 CDN 回源 IP 固定,攻击 IP 分散)。建议对判定为”可疑”的 IP 先返回 429(非 403),配合前端 JS Challenge 验证(如 reCAPTCHA)进一步确认。

总结

HTTP 洪水攻击防御需要组合使用 Nginx 的多层限流机制:limit_req(请求速率)、limit_conn(并发连接数)、UA 过滤以及基于日志分析的自适应封禁。没有万能配置,需要根据实际业务流量持续调优参数。配合 CDN 层 WAF 和云端 DDoS 防护(如 Cloudflare、阿里云 DDoS 高防)可构建更完善的防御体系。