Nginx环境下防止CC攻击的终极指南:模块配置与优化
摘要:# Nginx环境下防止CC攻击的终极指南:模块配置与优化 说真的,我见过太多站长了——平时聊起防护头头是道,真遇到CC攻击的时候,手忙脚乱,连Nginx日志都看不太明白。 (这种场景你应该不陌生吧?) 很多人觉得,上了高防IP或者WAF就万事大吉了…
说真的,我见过太多站长了——平时聊起防护头头是道,真遇到CC攻击的时候,手忙脚乱,连Nginx日志都看不太明白。
(这种场景你应该不陌生吧?)
很多人觉得,上了高防IP或者WAF就万事大吉了。其实吧,很多CC攻击恰恰是“绕”过了这些外围防护,直接怼到你的Nginx上的。你的源站如果还裸奔,或者配置得稀里糊涂,那攻击来了真扛不住,别硬撑。
今天咱们不聊那些PPT上很猛的方案,就扎扎实实,把Nginx这一层的防护掰开揉碎了讲清楚。我这两年处理过不少真实案例,发现很多问题不是出在“没防护”,而是“配错了”或者“没调优”。
一、先搞清楚:CC攻击到底在打你哪里?
说白了,CC攻击就是想用最少的资源,把你服务器搞趴下。它不像DDoS那样拼流量,而是模拟正常用户,疯狂请求你那些最耗资源的页面。
——比如你网站的动态搜索、登录接口、或者某个复杂的商品列表页。
我去年帮一个电商站处理过,攻击者就盯着它的商品评论分页接口打,每秒几千次请求。表面看每个请求都“合法”,但MySQL连接池瞬间被占满,整个站就卡死了。
所以防CC的第一步永远是:你知道你的弱点在哪吗?
别急着上配置,先用top命令看看服务器负载,用netstat看看连接数,或者直接打开Nginx的access.log,按IP排个序(awk '{print $1}' access.log | sort | uniq -c | sort -nr)。攻击来了,这些数据会说话。
二、核心模块:用好Nginx自带的“三板斧”
很多教程一上来就让你装第三方模块,其实Nginx自带的几个限流模块用好了,能挡掉80%的普通CC攻击。
1. limit_req_zone & limit_req:请求频率限制(最常用)
这个模块是按请求速率限流。原理有点像地铁早高峰限流,控制进入站台的人数。
http {
# 在http块里定义共享内存区,记录IP的请求状态
# $binary_remote_addr 用二进制存IP,省空间
# zone=one:10m 分配10M内存,大概能存16万个IP状态
# rate=10r/s 限制每秒10个请求
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
server {
location / {
# burst=5 允许突发5个请求排队,超过的直接503
# nodelay 如果不加,排队的请求会匀速处理;加了就立即处理突发请求,但超过burst+rate的依然拒绝
limit_req zone=one burst=5 nodelay;
proxy_pass http://your_backend;
}
# 关键接口可以单独设更严的限制
location /api/login {
limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
limit_req zone=login burst=3 nodelay;
proxy_pass http://your_backend;
}
}
}
注意:rate设多少合适?这得看你的业务。我一般建议,静态资源可以放宽(比如30r/s),动态接口尤其是登录、提交订单这些,一定要严(2-5r/s)。你想想,正常用户一秒会登录5次吗?
2. limit_conn_zone & limit_conn:连接数限制
有些攻击者会用慢连接(Slowloris变种)占着你的连接池不放手。这个模块就是限制同一IP的并发连接数。
http {
# 定义共享内存区,记录IP连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
# 限制每个IP同时只能有10个连接
limit_conn addr 10;
# 还可以针对特定location单独限制
location /download/ {
limit_conn addr 5; # 下载区限制更严
}
}
}
大实话:对于普通网站,单个IP并发10个连接其实已经算宽松了。真遇到下载站或者长连接场景,你再调高。
3. ngx_http_realip_module:拿到真实用户IP
如果你前面套了CDN或者高防代理,Nginx看到的IP全是代理服务器的IP,那上面两个模块就全废了。
——所以必须让Nginx能拿到真实用户IP。
http {
# 从X-Forwarded-For头里取真实IP,需要你信任的代理IP列表
set_real_ip_from 103.21.244.0/22; # Cloudflare的IP段,举例
set_real_ip_from 其他代理IP段;
real_ip_header X-Forwarded-For;
real_ip_recursive on; # 递归剔除可信代理IP,取最右边的真实IP
}
重要提醒:这个配置不对,后面所有基于IP的限制都会失灵。我见过不少站长,高防IP买了一年,压根没配这个,被打的时候还以为高防没用……其实是你自己没配好。
三、进阶玩法:第三方模块与策略组合
如果自带模块不够用,或者攻击更狡猾,可以考虑编译第三方模块。不过,编译前务必备份好原配置文件,别问我怎么强调这一点。
1. ngx_http_limit_req_module 的增强:limit_req2(OpenResty常用)
这个模块支持更复杂的条件,比如可以对某个URL参数单独限速。适合那种攻击者总用不同IP但攻击同一商品ID的场景。
2. 人机验证集成:轻度攻击“减速”,重度攻击“验证”
这是我最推荐的一种组合策略:
- 第一步:用
limit_req限制请求频率,超过的返回429(Too Many Requests)。 - 第二步:对频繁触发限流的IP,动态跳转到一个简单的验证页面(比如一个需要点击按钮的JS挑战)。
- 第三步:验证通过后,加入临时白名单一段时间。
这个逻辑可以用OpenResty的Lua脚本实现,也可以用Nginx配合Fail2ban等工具。思路比工具重要——目的是增加攻击者的成本,而不是完全堵死。
(说白了,就是让机器攻击变难,但别误伤正常用户。)
四、“优化”比“配置”更重要:别让防护拖垮性能
很多站长一通猛配,最后发现网站没被打垮,反而被自己的防护规则拖慢了。这里有几个坑:
1. 日志级别别乱开
调试的时候开info甚至debug没问题,生产环境长期开debug日志?你的磁盘IO会先撑不住。建议用error级别,真出问题了再临时调整。
2. 共享内存区大小(zone)要算好
前面说的10m能存16万IP,是根据每个IP大约64字节算的。如果你的网站日均IP就几千,那1m或2m足够了。设大了浪费内存,设小了频繁淘汰记录,影响精度。
3. 慎用“全局限流”
别动不动就在http块里全局限速。先给静态资源(图片、CSS、JS)设置宽松规则,或者直接放行。把严苛的规则精准地用在动态接口上。
4. 定期检查与动态调整
防护规则不是一劳永逸的。我自己的习惯是,每周看一眼Nginx的error.log,搜索503、429、limit这些关键词,看看有没有误伤。大促前,提前把限流阈值调高一些。
五、最后几句心里话
防CC这件事,没有“终极”方案,只有“更适合”当前业务阶段的策略。小站起步,用好Nginx自带模块就够了;业务增长,再考虑接入高防WAF做纵深防御。
最怕的是两种极端:一种是盲目自信,觉得“我的站小,没人打”;另一种是过度防护,买一堆用不上的高级功能,基础配置却漏洞百出。
(你自己心里掂量一下,是不是这样?)
行了,配置和思路都在这了。别光收藏,去服务器上敲两行命令,看看你的Nginx现在到底是个什么状态。实战中出的问题,比任何指南都更有价值。
遇到具体问题,评论区见——当然,别问我被打了怎么办,那得具体看日志。我只能说,提前准备的人,总比临时抱佛脚的从容那么一点点。

