一、CC 攻击的原理:为什么它比 DDoS 更阴险
CC(Challenge Collapsar)攻击并非用海量带宽压垮服务器,而是模拟真实用户、持续向你的动态接口发起大量"看似正常"的请求——刷登录、刷验证码、刷 API、刷后台。它不占用网络带宽,却会疯狂消耗 PHP-FPM 进程、数据库连接和内存,导致正常用户访问变慢甚至 502。由于每个请求都长得像人类,传统的防火墙和 CDN 流量清洗很难识别。Nginx 的请求频率限制(limit_req)和并发连接限制(limit_conn)正是防御这类攻击的第一道稳固防线。
二、limit_req:按请求速率限流
Nginx 用 limit_req_zone 定义"共享内存 + 限流规则",用 limit_req 在具体 location 触发。核心配置示意:
# 定义名为 req_limit 的限流域,key 取客户端 IP,10m 是共享内存大小
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=req_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
}
rate=10r/s:每 IP 每秒最多 10 个请求,超出即处理。burst=20:允许瞬时突发 20 个请求的缓冲,避免误伤正常的短时抖动。nodelay:突发缓冲内的请求不延迟排队立即放行;不加则超出速率的会排队限速(延迟),可形成"削峰"。需要严格平滑时用不带 nodelay 的限速,需要快速响应时用 nodelay。
key 也可以用 $server_name、$uri 或 $http_user_agent,但最常用还是真实 IP。若经过 CDN,需配合 set_real_ip_from + real_ip_header X-Forwarded-For 拿到真实客户端 IP,否则所有请求会被当成 CDN 出口 IP 这一个 key 限死。
三、limit_conn:限制并发连接数
有的攻击是"低频高并发"——连接建立得很多,拖垮进程。用 limit_conn 限制单 IP 并发连接:
http {
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /download/ {
limit_conn conn_limit 50;
limit_conn_status 429;
proxy_pass http://backend;
}
}
}
它和 limit_req 是互补的两道闸:limit_req 管"每秒来多少",limit_conn 管"同时挂多少连接"。对下载站、图片站这类大文件场景,并发连接限制尤为重要,能有效防刷流量。
四、按 URI、按 UA、按区域精细化限流
攻击往往集中在少数几个热点接口,可以只对敏感路径限流,不动正常流量:
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
limit_req_zone $http_user_agent zone=ua_limit:10m rate=1r/s;
map $http_user_agent $is_bad_ua {
default 0;
"~*Mozilla" 1; # 略,真实应根据特征判断
}
server {
# 只对 /api 和 /admin 施加严格限制
location ~ ^/(login|admin|api/) {
limit_req zone=api_limit burst=5 nodelay;
}
}
}
还可以用 map 根据 UA、Cookie、区域(配合 GeoIP 模块)把流量打标记,对恶意特征单独加快限速,对正常访问放行,实现"精准打击"。恶意 IP 还可以 deny 直接拒绝:
location /admin/ {
deny 1.2.3.4; # 直接封禁已知恶意 IP
allow 192.168.1.0/24;
deny all; # 其余全部拒绝,仅内网可访问
proxy_pass http://backend;
}
五、配合状态码、日志与告警
被限流会返回 429 Too Many Requests,前端可据此提示"请求过于频繁"。生产中建议:
limit_req_status 429; limit_req_log_level warn; # 记录限流事件 error_page 429 /429.html; # 给用户更友好的页面
在日志里检索 "status":429 或 grep nginx error log 中的 "limiting requests" 即可发现被限频才放行与拒绝的比例,帮助判断限流阈值是否过严误伤正常用户,从而动态调整 rate 和 burst。配合监控工具(如 Grafana 采集 error log),攻击开始时能第一时间收到告警。
六、限流之外的纵深防御组合
限流只是缓解手段,真正的 CC 防御要层层叠加:CDN + WAF 规则拦截高频源 IP;关闭不需要的隐蔽接口;给动态接口加验证码/滑块降低机器人成功率;数据库连接池和 PHP-FPM 调优保证即使被刷也不至于雪崩;最后再用 Nginx 的 limit_req / limit_conn 兜底。多租户要特别注意 limit_req_zone 共享内存大小,过小会报 "no free slots",需适当调大。
写在最后
Nginx 限流不是万能的,但它是离应用最近、成本最低、见效最快的一道闸。合理的设计是:白天正常阈值、对敏感接口单独收紧、CDN 层先挡一波、Nginx 层限速限连、日志层盯 429 异常、加上人工黑名单与告警。把这套组合跑起来,即使防不住所有攻击,也能让你的网站在激烈 CC 下保持可访问而不是直接躺平。
