返回首页

Nginx 安全配置实战 — 防DDoS/限流/WAF 规则编写

📅 创建于 2026-05-12 🔄 更新于 2026-09-05 📝 715 字

Nginx 安全配置实战:防DDoS、限流与WAF规则编写

Nginx 只能看到自己所在层面的连接、请求、URI、Header、Body 和上游交互结果。 超过这个边界的事情——大带宽 DDoS、链路拥塞、源站前设备被打满——单靠 Nginx 配置解决不了。 核心原则:先分层判断,再做针对性限制。

一、三层攻击防御坐标系

攻击类型 Nginx 可见层级 首选能力 误用方向
大带宽 DDoS 网络入口之前 CDN/高防清洗 指望 Nginx 单机硬扛
连接洪泛 连接层 limit_conn、超时、backlog 只靠 URI 级限流
请求洪泛 请求层 limit_req 只看 active connections
扫描/注入探测 规则层 WAF、黑白名单 只调连接数
撞库/爆破 接口行为层 限速+验证码+账号联动 仅按 IP 限制

二、先修观测面

2.1 真实源地址恢复(前提)

限流、封禁、黑白名单全部建立在正确源地址之上,否则全部失真。

# /etc/nginx/conf.d/security/realip.conf
set_real_ip_from 10.10.0.0/16;
set_real_ip_from 172.20.0.0/16;
set_real_ip_from 192.168.10.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

⚠️ 关键: 不要写 0.0.0.0/0,否则任何客户端都能伪造 XFF 绕过限流。

# 验证:第一列应该是真实客户端 IP,而不是代理 IP
tail -n 20 /var/log/nginx/access.security.log | awk '{print $1}'

2.2 日志格式补齐

log_format security_main '$realip_remote_addr [$time_local] '
  '"$request" $status $body_bytes_sent '
  'rt=$request_time urt=$upstream_response_time '
  'uaddr="$upstream_addr" uri="$uri" '
  'args="$args" ua="$http_user_agent" '
  'xff="$http_x_forwarded_for"';
access_log /var/log/nginx/access.security.log security_main;

关键字段:$realip_remote_addr(真实 IP)、$request_time$upstream_response_time$status

2.3 连接状态页

server {
  listen 127.0.0.1:8080;
  location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
  }
}

Active connections 持续高但 QPS 不高 → 慢连接/空闲连接占坑。


三、连接层防护

limit_conn — 并发连接限制

# http 层:定义统计键和内存区
limit_conn_zone $binary_remote_addr zone=conn_per_ip:20m;

# server/location 层:应用
location /admin/ {
  limit_conn conn_per_ip 10;
  proxy_pass http://admin_backend;
}

常见误改: 全站统一低阈值 → HTTP/2 用户误伤。应该按业务路径拆阈值。

关键超时配置

keepalive_timeout 15;
keepalive_requests 1000;
reset_timedout_connection on;
client_header_timeout 10s;
client_body_timeout 15s;
send_timeout 15s;

四、请求层防护

limit_req — 请求速率限制

# http 层:定义限流区
limit_req_zone $binary_remote_addr zone=req_login:20m rate=5r/s;
limit_req_zone $binary_remote_addr zone=req_sms:20m rate=2r/s;
limit_req_zone $binary_remote_addr zone=req_default:50m rate=30r/s;

# location 层:按接口应用
location = /api/login {
  limit_req zone=req_login burst=10 nodelay;
  proxy_pass http://auth_backend;
}

location = /api/sms/send {
  limit_req zone=req_sms burst=5;          # 不加 nodelay:平滑排队
  proxy_pass http://sms_backend;
}

nodelay vs 不加:

  • nodelay → 超过速率后快速拒绝,适合不允许多次重试的接口
  • 不加 nodelay → 短时突刺被延迟处理,用户体验更平滑

分级原则: 对登录、短信、注册等敏感接口用低阈值;对公开 API 用较高阈值。

限流也常出现在踩坑清单中,详见 nginx-config-pitfalls 踩坑点十二「核心接口未做限流」及真实 IP 配置踩坑点十一。


五、规则层防护(原生 WAF)

危险方法拦截

if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 405; }

常见扫描路径拦截

location ~* /(\.git|\.svn|\.env|wp-admin|wp-login\.php|
               phpmyadmin|actuator|jenkins|manager/html) {
  return 403;
}

恶意 UA 拦截

map $http_user_agent $bad_ua {
  default 0;
  ~*(sqlmap|nmap|nikto|masscan|acunetix|dirbuster|gobuster) 1;
}
server { if ($bad_ua) { return 403; } }

空 UA 也要拦(2026-09 增补):map 中追加 "" 1;"-" 1;——空 User-Agent 通常是恶意工具或配置错误的客户端。反向边界:遵守协议的搜索引擎爬虫(Googlebot/Baiduspider)过频时不要屏蔽,用 robots.txt 的 Crawl-delay: 10 控制抓取间隔 + 限流处理;robots.txt 对恶意爬虫无效,必须靠限流兜底(暴涨场景全流程见 nginx-log-spike-crawler-troubleshooting)。

低阶参数特征拦截(必须先用审计模式)

map $query_string $bad_args_audit {
  default 0;
  ~*(union\s+select|sleep\(|benchmark\(|
     information_schema|/etc/passwd|<script) 1;
}

# ⚠️ 先审计,不拦截
log_format waf_audit '$time_local ip=$realip_remote_addr '
  'uri="$uri" args="$args" hit=$bad_args_audit';
access_log /var/log/nginx/waf_audit.log waf_audit if=$bad_args_audit;

# 确认误伤可控后再升级为拦截
# if ($bad_args_audit) { return 403; }

误杀重灾区: 搜索接口、富文本接口、上传或模板编辑接口。


六、ModSecurity + CRS 接入

# 先「检测」后「拦截」
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

# main.conf — 先检测
SecRuleEngine DetectionOnly
Include /etc/nginx/modsec/crs/crs-setup.conf
Include /etc/nginx/modsec/crs/rules/*.conf

# 误伤可控后改为
# SecRuleEngine On

精准启用: 只对高风险路径开启,不要全站一把梭。

location /api/ {
  modsecurity on;
  modsecurity_rules_file /etc/nginx/modsec/api-only.conf;
  proxy_pass http://api_backend;
}

七、黑白名单与可信来源

geo $office_allow {
  default 0;
  203.0.113.0/24  1;
  198.51.100.10/32 1;
}
map $office_allow $admin_guard {
  0 1;
  1 0;
}
location /admin/ {
  if ($admin_guard) { return 403; }
  proxy_pass http://admin_backend;
}

屏蔽误伤三类高危目标(2026-09 增补):CDN 节点 IP(屏蔽=切断所有经该节点的用户)、公司出口 IP(屏蔽=全体员工被挡)、运营商 NAT 网关(屏蔽=大量普通用户被挡)。纪律:优先限流、其次屏蔽;先确认 realip 生效再按 IP 处置;屏蔽条目设有效期、定期复查;每条屏蔽记录原因便于追溯。


八、配置目录结构(可独立回滚)

/etc/nginx/
├── nginx.conf
├── conf.d/
│   ├── site.conf
│   └── security/
│       ├── realip.conf              # 真实地址恢复
│       ├── rate-limit-zones.conf    # 限流区定义
│       ├── waf-maps.conf            # WAF 规则 map
│       ├── allow-deny.conf          # 黑白名单
│       └── site-policy.conf         # 站点级应用策略
└── modsec/
    ├── main.conf
    └── crs/

每层独立回滚: 新 WAF 规则误伤时只回滚 waf-maps.conf,不影响真实 IP 和限流。


九、判断坐标系

现象 首看指标 更可能的问题层 第一动作
active connections 高,QPS 不高 stub_status, request_time 连接层 调连接限制/超时
某 URI QPS 高,连接数一般 URI TopN, IP TopN 请求层 limit_req 按接口
403/444 上升,URI 离散 UA 异常 access log, 规则命中日志 规则层 审计扫描特征和黑白名单
5xx 上升 + upstream_time 高 upstream 日志 上游已满 限流入口保护上游
所有来源像同一 IP $realip_remote_addr 地址恢复错误 先修 real IP

关联页面

页面关联点
nginx-config-pitfalls踩坑点十一(真实 IP)+ 踩坑点十二(限流)的安全配置上下文
nginx-502-504-connection-reset-guide上游异常与入口拦截的区别判断
nginx-pre-launch-checklist上线前检查(限流项与此文配套)
server-security-hardening-checklist服务器安全加固总纲(Nginx 加固上下文)
rate-limiting-algorithms接口限流 5 种算法详解(计数器/滑动窗口/令牌桶/漏桶/Redis+Lua),限流的算法原理参考
nginx-realtime-push-guideSSE/WebSocket 推送,WSS 安全配置参考
nginx-load-balancing-strategy-guideNginx 负载均衡策略选择实战指南,加权轮询与 IP Hash 深度对比
nginx-log-analysis-monitoring-guideNginx 日志分析与监控体系构建指南
nginx-production-performance-optimization生产级 Nginx 性能优化(OS 内核/Worker 进程/HTTP I/O/Upstream)
nginx-log-analysis-troubleshooting-guideNginx 日志分析、4xx/5xx/超时故障排查与真实案例复盘
network-troubleshooting-order防火墙/iptables 与 Nginx 安全联动
nginx-log-spike-crawler-troubleshootingNginx 访问日志暴涨排查手册:14 步 runbook(本页防护手段的完整处置场景)