Nginx限流防刷与CC攻击防护实战配置
做过Web服务的都知道,接口裸奔是找死。
不设防的后果:羊毛党刷爆优惠券、爬虫拖垮服务器、CC攻击搞瘫业务。
整理一下Nginx层面的防护方案,都是生产环境验证过的配置。
一、限流基础
Nginx有两个核心限流模块:
ngx_http_limit_req_module:限制请求速率ngx_http_limit_conn_module:限制连接数
1.1 限制请求速率
http {
# 定义限流区域
# $binary_remote_addr:按客户端IP限流
# zone=req_limit:10m:共享内存区域名和大小
# rate=10r/s:每秒10个请求
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
server {
location /api/ {
# 应用限流
# burst=20:允许突发20个请求
# nodelay:突发请求不延迟处理
limit_req zone=req_limit burst=20 nodelay;
proxy_pass http://backend;
}
}
}
参数解释:
rate=10r/s:平均每秒10个请求,即每100ms一个burst=20:桶大小,允许突发20个请求nodelay:突发请求立即处理,不排队等待
1.2 限制连接数
http {
# 按IP限制连接数
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /download/ {
# 每个IP最多10个连接
limit_conn conn_limit 10;
# 限制每个连接的速度
limit_rate 1m; # 1MB/s
}
}
}
适用场景:下载服务、视频流媒体。
二、分场景限流
2.1 登录接口防暴力破解
http {
# 登录接口严格限流
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
server {
location /api/login {
limit_req zone=login_limit burst=5 nodelay;
# 超限返回429
limit_req_status 429;
proxy_pass http://backend;
}
}
}
每秒只允许1次登录请求,防止暴力破解。
2.2 短信验证码防刷
http {
# 验证码接口更严格
limit_req_zone $binary_remote_addr zone=sms_limit:10m rate=1r/m;
server {
location /api/sms/send {
# 每分钟1次
limit_req zone=sms_limit burst=3;
proxy_pass http://backend;
}
}
}
2.3 搜索接口防爬虫
http {
# 搜索接口中等限流
limit_req_zone $binary_remote_addr zone=search_limit:10m rate=5r/s;
server {
location /api/search {
limit_req zone=search_limit burst=10 nodelay;
proxy_pass http://backend;
}
}
}
三、CC攻击防护
CC攻击就是用大量代理IP发请求,单IP限流不够用。
3.1 请求频率+并发连接双重限制
http {
limit_req_zone $binary_remote_addr zone=cc_req:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=cc_conn:10m;
server {
# 请求频率限制
limit_req zone=cc_req burst=50 nodelay;
# 并发连接限制
limit_conn cc_conn 50;
# 超限状态码
limit_req_status 503;
limit_conn_status 503;
}
}
3.2 基于User-Agent过滤
server {
# 封禁空UA和常见爬虫UA
if ($http_user_agent = "") {
return 403;
}
if ($http_user_agent ~* "python|curl|wget|scrapy|httpclient") {
return 403;
}
# 封禁特定UA
if ($http_user_agent ~* "MJ12bot|AhrefsBot|SemrushBot") {
return 403;
}
}
3.3 基于Referer过滤
server {
location /api/ {
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) {
return 403;
}
}
}
3.4 cookie验证
server {
location / {
# 检查是否有验证cookie
if ($cookie_verified != "yes") {
# 返回验证页面,通过JS设置cookie后重定向
return 302 /verify.html;
}
proxy_pass http://backend;
}
}
这个方法可以过滤掉不执行JS的简单爬虫。
四、IP黑白名单
4.1 黑名单
http {
# 加载黑名单文件
geo $blocked_ip {
default 0;
include /etc/nginx/blacklist.conf;
}
server {
if ($blocked_ip) {
return 403;
}
}
}
黑名单文件:
# /etc/nginx/blacklist.conf
1.2.3.4 1;
5.6.7.0/24 1;
4.2 白名单
http {
geo $whitelist {
default 0;
10.0.0.0/8 1; # 内网
192.168.0.0/16 1; # 内网
}
server {
location /admin/ {
if ($whitelist = 0) {
return 403;
}
proxy_pass http://backend;
}
}
}
4.3 动态封禁
配合fail2ban实现自动封禁:
# /etc/fail2ban/filter.d/nginx-cc.conf
[Definition]
failregex = ^<HOST> .* "(GET|POST).* HTTP.*" (429|503)
ignoreregex =
# /etc/fail2ban/jail.d/nginx-cc.conf
[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
logpath = /var/log/nginx/access.log
maxretry = 100
findtime = 60
bantime = 3600
60秒内触发100次429/503就封禁1小时。
五、实战配置模板
综合以上方案的完整配置:
http {
# 限流区域定义
limit_req_zone $binary_remote_addr zone=global_limit:20m rate=50r/s;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# 黑名单
geo $blocked_ip {
default 0;
include /etc/nginx/blacklist.conf;
}
# 白名单
geo $whitelist {
default 0;
10.0.0.0/8 1;
192.168.0.0/16 1;
}
server {
listen 80;
server_name example.com;
# 黑名单拦截
if ($blocked_ip) {
return 403;
}
# 空UA拦截
if ($http_user_agent = "") {
return 403;
}
# 全局限流
limit_req zone=global_limit burst=100 nodelay;
limit_conn conn_limit 100;
# API接口限流
location /api/ {
limit_req zone=api_limit burst=30 nodelay;
proxy_pass http://backend;
}
# 登录接口严格限流
location /api/login {
limit_req zone=login_limit burst=5 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
# 静态资源不限流
location /static/ {
expires 7d;
add_header Cache-Control "public, immutable";
}
# 管理后台白名单
location /admin/ {
if ($whitelist = 0) {
return 403;
}
proxy_pass http://backend;
}
}
}
六、监控与告警
光限流不够,还要能看到发生了什么。
6.1 日志格式
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time '
'$limit_req_status';
access_log /var/log/nginx/access.log detailed;
6.2 实时统计
# 统计429状态码
tail -f /var/log/nginx/access.log | grep " 429 " | wc -l
# 按IP统计请求数
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
6.3 自定义限流日志
location /api/ {
limit_req zone=api_limit burst=30 nodelay;
# 限流日志
limit_req_log_level warn;
}
被限流的请求会记录到error.log:
limiting requests, excess: 30.234 by zone "api_limit"
七、压测验证
配置完要验证效果:
# 用ab压测
ab -n 1000 -c 100 http://example.com/api/test
# 用wrk压测
wrk -t4 -c200 -d30s http://example.com/api/test
观察:
- 正常请求能过
- 超限请求返回429或503
- 服务器资源没被打满
八、远程管理
我们有几个边缘节点部署了Nginx做CDN,分布在不同城市。之前更新配置很麻烦,现在用星空组网把所有节点组到一起,SSH直连更新配置很方便。
总结
Nginx防护策略:
| 攻击类型 | 防护方案 | 核心配置 |
|---|---|---|
| 单IP刷接口 | 请求速率限制 | limit_req |
| 下载带宽滥用 | 连接数+速度限制 | limit_conn + limit_rate |
| 暴力破解 | 严格限流 | rate=1r/s |
| CC攻击 | 多层防护 | 限流+UA过滤+黑名单 |
| 爬虫 | UA+Referer过滤 | if判断 |
防护策略要分层:
- 第一层:IP黑名单
- 第二层:速率限制
- 第三层:行为判断
- 第四层:验证码(业务层)
别等被攻击了才想起来加防护。
有其他防护方案欢迎分享~

浙公网安备 33010602011771号