数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 35|回复: 0

Nginx 如何防御 DDOS 网络攻击?

[复制链接]
发表于 2025-12-30 00:29:47 | 显示全部楼层 |阅读模式 IP属地:福建省厦门市 电信
先泼盆冷水:Nginx防不了真正的DDOS。

被打过一次就知道了。当年公司网站被攻击,带宽直接打满100M,Nginx进程连TCP握手都完成不了,配置写得再好也白搭。最后找云厂商上了高防才扛住。

但Nginx能防的是应用层攻击,也就是CC攻击(Challenge Collapsar)。这类攻击不靠带宽取胜,而是用大量HTTP请求耗尽你的服务器资源——CPU、内存、连接数、PHP-FPM进程池等。

下面说说怎么配。


一、先搞清楚能防什么



Nginx工作在应用层,网络层的攻击请求根本到不了Nginx就把系统资源打满了。

明白这点后,下面的配置才有意义。



二、限制请求速率(核心)

Nginx官方模块ngx_http_limit_req_module,用令牌桶算法限流。

  1. http {
  2.     # 定义限流区域:按IP限制,每秒10个请求
  3.     limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
  4.    
  5.     server {
  6.         location /api/ {
  7.             # 应用限流:burst=20允许突发,nodelay不排队
  8.             limit_req zone=api_limit burst=20 nodelay;
  9.             
  10.             # 超限返回503
  11.             limit_req_status 503;
  12.         }
  13.     }
  14. }
复制代码


参数解释:

    $binary_remote_addr:按客户端IP统计,占用空间比$remote_addr少
    zone=api_limit:10m:共享内存区域,10MB大概能存16万个IP状态
    rate=10r/s:每秒10个请求,实际是每100ms放1个令牌
    burst=20:桶容量,允许突发20个请求
    nodelay:突发请求立即处理,不排队等待

    参考:Nginx官方文档 - limit_req_module



三、限制并发连接数

  1. ngx_http_limit_conn_module 限制同时在线的连接数。

  2. http {
  3.     limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
  4.    
  5.     server {
  6.         # 每个IP最多100个并发连接
  7.         limit_conn conn_limit 100;
  8.         
  9.         # 整个server最多10000个连接
  10.         limit_conn_zone $server_name zone=server_limit:10m;
  11.         limit_conn server_limit 10000;
  12.     }
  13. }
复制代码


这个对下载类服务特别有用,防止某个IP开几百个连接吃光带宽。



四、Slowloris攻击防护

Slowloris攻击很阴险:建立连接后,用极慢的速度发送HTTP请求头,保持连接不释放,耗尽服务器的连接数。

Nginx默认配置就能防一部分,但建议显式设置:

  1. http {
  2.     # 读取请求头超时
  3.     client_header_timeout 10s;
  4.    
  5.     # 读取请求体超时
  6.     client_body_timeout 10s;
  7.    
  8.     # 发送响应超时
  9.     send_timeout 10s;
  10.    
  11.     # 长连接超时
  12.     keepalive_timeout 30s;
  13.    
  14.     # 请求头大小限制
  15.     client_header_buffer_size 1k;
  16.     large_client_header_buffers 4 8k;
  17. }
复制代码


请求头超过10秒还没发完?肯定不是正常用户,直接断开。



五、封禁恶意IP

静态黑名单

  1. http {
  2.     geo $blocked {
  3.         default 0;
  4.         include /etc/nginx/blacklist.conf;
  5.     }
  6.    
  7.     server {
  8.         if ($blocked) {
  9.             return 403;
  10.         }
  11.     }
  12. }
复制代码


/etc/nginx/blacklist.conf:

1.2.3.4 1;
5.6.7.0/24 1;


动态封禁(配合fail2ban)

在/etc/fail2ban/jail.d/nginx-cc.conf里配置:

  1. [nginx-cc]
  2. enabled = true
  3. port = http,https
  4. filter = nginx-cc
  5. logpath = /var/log/nginx/access.log
  6. maxretry = 100
  7. findtime = 60
  8. bantime = 3600
  9. action = iptables-multiport[name=nginx-cc, port="http,https"]
复制代码


60秒内同一IP请求超过100次,封禁1小时。



六、其他加固

User-Agent过滤

  1. # 封禁空UA和常见攻击工具
  2. if ($http_user_agent = "") {
  3.     return 403;
  4. }

  5. if ($http_user_agent ~* "python-requests|curl|wget|scrapy|Go-http-client") {
  6.     return 403;
  7. }
复制代码


攻击脚本很多用默认UA,这能挡一部分低级攻击。

正经爬虫会带正常UA,这招防君子不防小人。

限速下载

  1. location /download/ {
  2.     limit_rate 1m;  # 每个连接限速1MB/s
  3.     limit_rate_after 10m;  # 下载10MB后开始限速
  4. }
复制代码




七、完整配置模板

  1. http {
  2.     # === 限流配置 ===
  3.     limit_req_zone $binary_remote_addr zone=global:10m rate=30r/s;
  4.     limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
  5.     limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
  6.     limit_conn_zone $binary_remote_addr zone=conn:10m;
  7.    
  8.     # === 黑名单 ===
  9.     geo $blocked {
  10.         default 0;
  11.         include /etc/nginx/blacklist.conf;
  12.     }
  13.    
  14.     # === 超时配置 ===
  15.     client_header_timeout 10s;
  16.     client_body_timeout 10s;
  17.     send_timeout 10s;
  18.     keepalive_timeout 30s;
  19.    
  20.     server {
  21.         listen 80;
  22.         server_name example.com;
  23.         
  24.         # 黑名单拦截
  25.         if ($blocked) {
  26.             return 403;
  27.         }
  28.         
  29.         # 空UA拦截
  30.         if ($http_user_agent = "") {
  31.             return 403;
  32.         }
  33.         
  34.         # 全局限流
  35.         limit_req zone=global burst=50 nodelay;
  36.         limit_conn conn 100;
  37.         
  38.         # API限流
  39.         location /api/ {
  40.             limit_req zone=api burst=20 nodelay;
  41.             proxy_pass http://backend;
  42.         }
  43.         
  44.         # 登录严格限流
  45.         location /api/login {
  46.             limit_req zone=login burst=5 nodelay;
  47.             proxy_pass http://backend;
  48.         }
  49.     }
  50. }
复制代码




八、但还是不够

说实话,上面这些配置只能防住小规模攻击和脚本小子。

真被盯上了,几百个代理IP轮着上,每个IP请求速率都不超限,limit_req就废了。


这时候需要:

    云厂商高防:把攻击流量在机房入口就清洗掉
    CDN分流:攻击流量分散到边缘节点
    WAF:检测异常请求模式,比如同一个接口被不同IP高频调用
    验证码/JS挑战:Cloudflare那种”检测浏览器”的页面

Nginx是最后一道防线,不能指望它扛住所有攻击。



总结




实际部署建议:

    先把限流和超时配好(必选)
    配合fail2ban动态封禁(推荐)
    条件允许上CDN/高防(大流量必选)

多台服务器的话,配置要保持一致。我们几台Nginx分布在不同机房,用星空组网组到一起后,Ansible批量更新配置很方便。

最后,定期看日志。很多攻击都是有前兆的,提前发现就不会半夜被叫醒了。



来自:花宝宝 后端老兵 | 星空组网 starvpn.cn





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2026-2-7 10:22 , Processed in 0.124801 second(s), 16 queries , Gzip On, Redis On.

Powered by Discuz!

© 2006-2026 MyDigit.Net

快速回复 返回顶部 返回列表