CC攻击(Challenge Collapsar)的可怕之处在于,它往往不追求巨大的流量带宽,而是通过大量看似正常的请求,精准打击那些消耗服务器资源巨大的URL。面对这种攻击,单靠本地的Nginx配置往往力不从心,因为恶意流量已经抵达服务器网卡,占用了宝贵的带宽和连接数资源。最优雅的防御姿态,是将防线前移,利用云防火墙在流量入口处清洗掉90%的泛洪攻击,再由后端Nginx进行精细化的逻辑层校验,从而实现一硬一软、一外一内的双层拦截体系。
云防火墙的粗粒度清洗:基于行为特征的封禁云防火墙的核心优势在于其巨大的带宽储备和基于全网威胁情报的分析能力。它不需要理解你的业务逻辑,只需要在TCP/IP层和HTTP协议层识别“非人类”的特征。配置时,我们不应只满足于默认的阈值,而需要根据业务特性进行定制化调优。
首先是地域封锁。如果你的业务仅面向国内用户,直接在云防火墙的访问控制策略中,一键封禁所有境外IP,这能瞬间消除来自海外僵尸网络的大部分噪音。其次是连接数与请求速率限制。这比Nginx的limit_req模块更底层。例如,设置单一源IP对服务器的并发TCP连接数超过50即触发拦截,或者单个IP在5秒内发起超过200个请求便自动拉入黑名单。这种策略直接作用于四层,恶意IP甚至无法完成TCP握手,更别提抵达Nginx监听端口了。
最关键的是利用云防火墙的“HTTP Flood”防护模块。这里需要精细配置,不能一刀切。建议开启“严格模式”前,先通过日志分析正常用户的访问峰值。例如,如果你的网站登录接口通常每秒只有10次请求,那么将CC防护阈值设置为每秒30次就是一个既安全又不误杀的临界点。云防火墙一旦触发拦截,通常会返回验证码跳转或直接丢弃SYN包,这种清洗效率是服务器本地防火墙无法比拟的。
本地Nginx的逻辑层防御:细粒度的令牌校验经过云防火墙清洗后的流量,大部分已经是合法用户的请求,但仍可能混入慢速攻击或绕过云防火墙特征库的变种CC攻击。此时,Nginx的角色从“扛量”转变为“鉴权”。我们不建议在Nginx层面再做简单的IP频率限制,因为云防火墙已经做了,重复劳动且容易误伤。Nginx应专注于动态令牌验证。
一种极其有效的方案是结合Nginx的HttpLuaModule或OpenResty,实现“重定向验证”。原理很简单:当用户第一次访问受保护页面时,Nginx不直接返回内容,而是返回一个302状态码,重定向到一个极轻量的验证页面,并在重定向的URL参数中携带一个加密的Token和跳转回源地址的标识。验证页面可以是一段极简的JavaScript,要求浏览器执行一次数学计算或解析一次Cookie,然后自动跳转回源站并带上计算结果。Nginx在接收到第二次请求时,校验Token的有效性和计算结果的正确性。
对于不支持JavaScript或Cookie的爬虫工具,它们无法完成这一跳转闭环,自然被拦截在逻辑层之外。这种方法的妙处在于,它将防御成本转嫁给了攻击者。攻击者必须维护完整的浏览器堆栈才能穿透,攻击成本呈指数级上升,而正常用户的浏览器在毫秒级内即可完成跳转,几乎无感知。
Nginx配置实战:编写Lua脚本实现智能验证以下是一段嵌入Nginx配置的Lua脚本逻辑示例,用于实现上述的Cookie校验重定向机制。请确保你的Nginx编译了lua-nginx-module。
# 在 http 块中定义共享内存,用于存储已验证的IP白名单
lua_shared_dict cc_whitelist 10m;
server {
listen 80;
server_name your-domain.com;
# 受保护的路径
location /protected/ {
access_by_lua_block {
local whitelist = ngx.shared.cc_whitelist
local client_ip = ngx.var.remote_addr
-- 1. 检查是否已在白名单中
if whitelist:get(client_ip) == "1" then
return -- 放行
end
-- 2. 检查请求中是否携带了有效的验证Token
local token = ngx.var.arg_token
local salt = "your_secret_salt_2024"
if token then
-- 简单验证:Token 应为 IP + 时间戳的MD5,有效期60秒
local now = ngx.time()
for i = 0, 60 do
local expected = ngx.md5(client_ip .. (now - i) .. salt)
if token == expected then
-- 验证通过,加入白名单,有效期1小时
whitelist:set(client_ip, "1", 3600)
return
end
end
end
-- 3. 验证失败,生成新Token并发起重定向
local new_time = ngx.time()
local new_token = ngx.md5(client_ip .. new_time .. salt)
local redirect_url = "https://your-domain.com/verify.html?token=" .. new_token .. "&redirect=" .. ngx.var.request_uri
return ngx.redirect(redirect_url, 302)
}
# 验证通过后的正常代理或静态文件处理
root /var/www/html;
}
}
上述代码实现了一个动态白名单机制。首次访问的IP会被302重定向到验证页面,验证页面只需读取URL参数中的token并再次跳转回源站即可。一旦验证通过,IP会被缓存在共享内存中,后续请求直接放行,避免了反复验证带来的延迟。这种本地逻辑层防御与云防火墙的暴力清洗形成了完美的互补。
协同作战:利用X-Forwarded-For与云防火墙联动多层拦截最容易出现的问题是源IP丢失。云防火墙作为反向代理,如果不做特殊配置,Nginx日志中记录的将是云防火墙的节点IP,导致无法针对真实客户端进行策略限制。必须确保云防火墙开启了“透传真实IP”功能,通常是通过设置X-Forwarded-For头实现。
在Nginx端,需要修改日志格式并安装real_ip模块。配置如下:
# 设置信任的云防火墙回源IP段
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# 日志格式中记录真实IP
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" ';
这样,Nginx中的Lua脚本获取到的remote_addr就是真实客户IP,白名单机制才能生效。同时,当Nginx检测到某个IP在验证环节表现异常(如不断尝试伪造Token),可以将该IP通过API实时反馈给云防火墙。多数云厂商提供API接口,允许你动态添加黑名单。例如,Nginx的日志监控脚本可以分析日志,一旦发现某IP在1分钟内触发了20次Token校验失败,就调用云防火墙API直接将该IP在入口处封禁24小时。这种“后端判决、前端执行”的联动,让防御体系具备了自我进化的能力。
静态资源与动态接口的差异化防护策略很多配置失误在于对所有URL应用了同样的严格策略。CC攻击很多时候是针对搜索接口、登录接口等消耗资源的动态请求,而静态图片、CSS文件即使被频繁请求,消耗也极小。因此,分层拦截必须做到动静分离。
在云防火墙层面,可以对静态资源目录(如*.jpg, *.css)设置更高的阈值,甚至关闭JavaScript跳转验证,只保留基础的连接数限制,保证加载速度。而在Nginx层面,针对/api/路径下的动态请求,开启严格的Lua验证;针对/static/路径,则直接关闭Lua验证,仅依靠云防火墙的默认防护。这样既保证了核心接口的安全,又避免了静态资源加载因重定向验证而出现延迟或阻塞。
此外,对于登录接口,除了Token验证,还应在Nginx中集成失败次数限制。例如,使用Redis存储登录失败计数,同一IP在10分钟内失败5次,不仅拒绝请求,同样通过API将IP推送到云防火墙黑名单。这种针对业务逻辑的精准打击,是单纯依靠云防火墙无法做到的。
容灾与降级:当云防火墙出现故障时多层架构必须考虑单点故障风险。如果云防火墙服务出现波动,所有流量将直接透传或中断。因此,Nginx必须具备独立的兜底能力。建议在Nginx中保留一套简化版的limit_req配置作为最后防线。
# 兜底策略:当云防火墙回源头丢失或透传时启用
map $http_x_forwarded_for $is_from_firewall {
default 0;
"~*cloudfirewall" 1; # 假设云防火墙会添加特定标识
}
# 如果未经过云防火墙,开启本地严格限流
limit_req_zone $binary_remote_addr zone=fallback:10m rate=10r/s;
location / {
if ($is_from_firewall = 0) {
limit_req zone=fallback burst=5 nodelay;
}
# 其余逻辑...
}
这套组合拳打下来,从云端的海量流量清洗,到本地Nginx的逻辑令牌验证,再到针对性的API联动封禁,构建了一个纵深防御体系。攻击者需要先突破基于行为分析的云防护,再面对需要完整浏览器渲染能力的本地验证,攻击门槛被大幅抬高。这种架构不仅解决了高并发下的资源耗尽问题,也弥补了通用防火墙无法理解业务逻辑的短板,是目前应对复杂CC攻击最稳健的落地实践之一。
