1. 当流量洪水来袭:认识DDoS与Nginx的关系

Nginx作为现代网站的流量守门人,每天要处理数以万计的请求。但当遭遇DDoS攻击时,这个守门人就像突然面临洪水冲击的水闸,处理不当就会导致服务崩溃。不同于传统防火墙,Nginx自身就携带多种"防洪闸门",比如请求速率限制、连接控制等原生功能。

真实案例:某电商网站在大促期间遭遇每秒5万次的CC攻击,攻击者用伪造IP高频请求商品详情页。通过Nginx的限流模块,他们在不增加硬件的情况下将异常请求拦截了87%。

2. 基础防御工事搭建

2.1 请求频率限制(limit_req模块)

http {
    # 创建10MB内存区存储访问状态,限制每秒100个请求
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
    
    server {
        location /api/ {
            # 启用限流,允许突发200个请求,立即执行限制
            limit_req zone=api_limit burst=200 nodelay;
            proxy_pass http://backend;
        }
    }
}

参数解析:

  • $binary_remote_addr:用二进制格式存储客户端IP
  • zone:定义存储区域名称和内存大小
  • burst:类似"缓冲池",允许突发流量
  • nodelay:立即拒绝超额请求

适用场景:保护API接口、登录页面等关键端点 缺点:无法识别高级伪造IP攻击

2.2 连接数管控(limit_conn模块)

http {
    # 每个IP同时最多保持50个连接
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    server {
        location /download/ {
            limit_conn addr 50;
            limit_rate_after 10m;  # 前10MB不限速
            limit_rate 100k;       # 超过后限速100KB/s
        }
    }
}

实战效果:某视频站用此配置阻止了攻击者通过海量慢连接耗尽服务器资源

3. 进阶防御策略

3.1 地理围栏(GeoIP模块)

http {
    # 加载GeoIP数据库
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    
    # 封禁特定国家访问
    map $geoip_country_code $allowed_country {
        default 1;
        CN 0; US 0; JP 0;  # 允许中、美、日
        RU 1;              # 封禁俄罗斯
    }

    server {
        if ($allowed_country) {
            return 444;  # 特殊状态码直接关闭连接
        }
    }
}

注意事项:需要定期更新GeoIP数据库

3.2 请求特征过滤(Lua扩展)

location / {
    access_by_lua_block {
        local headers = ngx.req.get_headers()
        
        -- 拦截非常见User-Agent
        if not headers["User-Agent"] then
            ngx.exit(ngx.HTTP_FORBIDDEN)
        end
        
        -- JS挑战验证
        if ngx.var.cookie_js_challenge ~= "passed" then
            ngx.header["Set-Cookie"] = "js_challenge=passed"
            ngx.say('<script>document.cookie="js_challenge=passed";location.reload();</script>')
            ngx.exit(ngx.OK)
        end
    }
}

技术栈说明:需要OpenResty环境 优势:可有效拦截简单爬虫攻击

4. 防御组合拳实战

4.1 多层过滤架构

  1. 前端用limit_req拦截高频请求
  2. 中间层通过Lua脚本做行为验证
  3. 后端用limit_conn防止连接耗尽

某金融平台配置示例:

http {
    limit_req_zone $binary_remote_addr zone=global:20m rate=50r/s;
    limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

    server {
        location / {
            limit_req zone=global burst=100;
            limit_conn conn_zone 30;
            
            access_by_lua_file /etc/nginx/lua/antibot.lua;
            
            # 正常请求处理...
        }
    }
}

4.2 动态黑名单维护

# 自动封禁异常IP脚本
awk '{if($9>499) print $1}' /var/log/nginx/access.log \
| sort | uniq -c | sort -nr \
| awk '{if($1>1000) print "deny "$2";"}' >> block.conf

# 每小时执行并重载配置
0 * * * * /usr/bin/update_block.sh && nginx -s reload

5. 技术方案对比分析

防御方式 配置难度 防护效果 性能影响 适用场景
基础限流 ★☆☆☆☆ ★★☆☆☆ 5%以下 小规模突发流量
连接限制 ★★☆☆☆ ★★★☆☆ 3-8% 慢连接攻击
GeoIP过滤 ★★★☆☆ ★★★★☆ 2% 地域性攻击
Lua验证 ★★★★☆ ★★★★☆ 10-15% 高级脚本攻击
动态黑名单 ★★★★☆ ★★★★★ 可变 持续定向攻击

6. 避坑指南:那些年我们踩过的雷

6.1 配置陷阱

错误示例:

limit_req_zone $remote_addr zone=test:10m rate=10r/s;  # 使用ASCII存储IP

正确姿势:

limit_req_zone $binary_remote_addr zone=test:10m rate=10r/s;  # 二进制格式省空间

6.2 监控盲区

推荐配置:

# 在http模块添加
log_format security '$remote_addr - $http_x_forwarded_for - [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'Rate:$limit_req_status Conn:$limit_conn_status';

access_log /var/log/nginx/security.log security;

7. 终极防御:云地协同方案

当单机防御达到极限时(通常超过10Gbps流量),建议:

  1. 启用Cloudflare等CDN服务
  2. 配置Nginx前置清洗服务器
  3. 结合iptables进行SYN洪水防护

混合架构示例:

互联网 → Cloudflare → 清洗中心 → Nginx集群 → 业务服务器

技术总结

经过压力测试,合理配置的Nginx可独立抵御5-10Gbps的DDoS攻击。某在线教育平台的实际数据显示:

  • 攻击请求拦截率:92.7%
  • 误封正常用户率:0.03%
  • CPU消耗增长:15-20%

关键配置要诀:

  1. 限流值从保守值开始,逐步调优
  2. 定期分析访问日志优化规则
  3. 重要接口启用二次验证
  4. 保持Nginx版本更新(特别是修复CVE-2023-44487等漏洞)

记住:没有银弹防御方案,持续监控和策略迭代才是王道。当遇到百G级攻击时,请及时联系专业安全团队。