Nginx 面对 DDoS 时应通过内存分片与连接节流延缓崩溃:限制单 worker 内存(调小 header/body 缓冲)、均匀分发连接(reuseport、worker_cpu_affinity、multi_accept off)、精简运行时(关闭日志/冗余模块)、启用 limit_conn/limit_req 熔断。

面对突发 DDoS 流量,Nginx 本身不提供主动防御能力,但合理的内存分片配置能显著延缓资源耗尽、避免进程崩溃、维持基础服务可用性。核心思路不是“扛住攻击”,而是“控制单个 worker 进程的内存爆炸风险”,让系统在压力下仍可响应关键请求、便于人工介入或联动限流设备。
限制单 worker 内存占用上限
DDoS 常表现为海量短连接、畸形头、大 body 或高频小请求,这些都会触发 Nginx 缓冲区分配。若不限制,一个 worker 可能因数千并发连接各占几 KB 缓冲而吃光数百 MB 内存。
- worker_rlimit_nofile 必须与系统 ulimit -n 对齐(如设为 65535),防止连接数超限时触发内核级错误或静默丢包
- client_header_buffer_size 设为 1k(非默认 4k),多数合法请求头远小于此;配合 large_client_header_buffers 2 1k 应对极少数长头,避免单请求占用 8k+ 内存
- client_body_buffer_size 降为 64k,并严格搭配 client_max_body_size 2m;拒绝大上传可大幅减少缓冲区内存驻留时间
- 禁用 proxy_buffering off(反向代理场景),改用小缓冲:proxy_buffer_size 2k; proxy_buffers 4 2k; 防止后端慢响应导致前端连接长期持有多段缓冲
拆分连接负载,避免单点内存峰值
不依赖“提高 worker_connections”,而是让连接更均匀分散,降低任意一个 worker 突然承载异常流量的概率。
- worker_processes 设为 CPU 物理核心数(非 auto),避免容器或虚拟机中误判导致进程过多、内存碎片加剧
- worker_cpu_affinity auto 启用自动绑核,确保每个 worker 独占 L1/L2 缓存,减少跨核同步开销与内存访问延迟
- multi_accept off(默认值),禁止单次事件循环接收全部就绪连接;改为逐个 accept,使连接更平滑分发到各 worker,削峰填谷
- 配合系统级 net.core.somaxconn=65535 和 net.ipv4.tcp_max_syn_backlog=65535,防止 SYN 队列溢出丢包,让 Nginx 有更多缓冲空间做连接节流
精简运行时上下文,压缩每连接内存 footprint
每个活跃连接在 Nginx 中不仅占缓冲区,还维护状态结构体、SSL 上下文、日志上下文等。减少冗余可直接压低 per-connection 内存开销。
- 所有 server 块统一使用 listen 80 reuseport(Linux 3.9+),内核层分流新连接,比用户态 worker 轮询更早分片
- HTTPS 站点共用 ssl_session_cache shared:SSL:4m(而非每个 server 单独定义),4MB 可缓存约 1.6 万个会话,避免重复 SSL 上下文分配
- 关闭非必要模块:确认 nginx -V 2>&1 | grep -o 'with-http.*_module' 不含 ngx_http_perl_module、ngx_http_xslt_filter_module 等重型模块;未启用也建议重新编译裁剪
- 全局关闭 access_log off,或仅记录 error_log /var/log/nginx/ddos_warn.log warn;高频率写日志会放大内存与 I/O 压力
启用连接级快速熔断机制
内存分片需配合主动节流,否则缓冲区再小,连接数无限增长仍会耗尽。
- 使用 limit_conn_zone $binary_remote_addr zone=addr:10m 定义客户端 IP 连接限制区,10MB 可跟踪约 16 万个 IP
- 在 server 或 http 块中添加 limit_conn addr 10,单 IP 最多保持 10 个并发连接;超出即返回 503,不分配任何缓冲区
- 搭配 limit_req_zone $binary_remote_addr zone=req_rate:10m rate=5r/s 控制请求速率,burst=10 nodelay,防突发毛刺穿透
- 设置 reset_timedout_connection on,对空闲超时连接立即释放资源,不等待 TCP FIN


















