如何防止Python Web应用被CC攻击?Gunicorn与Nginx协同防护
摘要:# 当Python Web被CC攻击盯上:别让Gunicorn和Nginx成了“纸老虎” ˃ 说真的,我见过不少中小型创业团队,代码写得漂亮,业务跑得挺顺,结果上线三个月,被一波CC攻击直接打回原型——服务器CPU飙到99%,数据库连不上,用户投诉电话被…
当Python Web被CC攻击盯上:别让Gunicorn和Nginx成了“纸老虎”
说真的,我见过不少中小型创业团队,代码写得漂亮,业务跑得挺顺,结果上线三个月,被一波CC攻击直接打回原型——服务器CPU飙到99%,数据库连不上,用户投诉电话被打爆。老板急得跳脚,技术团队熬夜查日志,最后发现攻击者用的就是最基础的脚本,成本不到一百块。
01 真实场景
先别急着翻技术文档,咱们聊个真实场景。上个月,我帮一个做电商的朋友处理过类似问题。
他们用Flask+Gunicorn+Nginx架构,平时流量稳定,结果大促前一周,突然发现网站响应慢得像蜗牛。登录服务器一看,好家伙,Gunicorn的worker进程全在满负荷运转,Nginx日志里全是同一个IP段的请求,每秒上百次访问商品详情页。
“我们不是有Nginx吗?怎么还这样?”朋友一脸困惑。这就是很多人的误区——以为上了Nginx就万事大吉,其实配置不对,防护就是摆设。
02 CC攻击到底在打什么?
CC攻击(Challenge Collapsar)说白了就是针对应用层的“人海战术”。它不像DDoS那样用流量压垮带宽,而是模拟真实用户行为,疯狂请求那些最消耗资源的页面或接口。
比如你的商品详情页需要查数据库、渲染模板、调用推荐算法,一个请求可能占用0.1秒CPU时间。正常用户每秒点一次,但攻击脚本一秒能发100个请求,相当于100个“假用户”在同时消耗你的服务器资源。
Python Web应用尤其容易中招,为什么?因为Gunicorn这类WSGI服务器的并发模型。
Gunicorn默认用同步worker,一个worker同一时间只能处理一个请求。如果20个worker都被攻击请求占着,真实用户就只能排队——这就是为什么网站会“卡死”而不是“宕机”。
03 Gunicorn的“内功”调优
很多人一上来就想着加硬件、上高防,其实第一道防线就在你的Gunicorn配置里。
worker数量别瞎设。我看到不少团队直接照搬教程,CPU核数*2+1,结果8核机器配了17个worker。真遇到CC攻击,这17个worker瞬间全被占满,系统资源直接爆炸。
我的经验是:先压测,再定数。用locust模拟真实业务场景,看看单个请求平均耗时,算算你的业务能承受的并发量。通常我会建议从workers = CPU核数开始,留出系统缓冲空间。
超时时间要狠心。Gunicorn的timeout默认是30秒,太长了。对于CC攻击,攻击者巴不得你的连接挂得越久越好。根据你的业务实际调整——API接口可以设3-5秒,普通页面8-10秒足矣。
# 一个相对保守的配置示例
workers = 4 # 4核机器
worker_class = 'sync' # 同步模型,简单稳定
timeout = 10 # 10秒不响应就断开
keepalive = 2 # 保持连接时间别太长
(这里插一句,有些教程会推荐用gevent异步worker,确实能提升并发能力,但调试起来麻烦,而且对某些阻塞型库不友好,新手慎用。)
04 Nginx的“外功”配置
Nginx如果只是当个反向代理转发请求,那真是大材小用了。它其实是你抵御CC攻击的主力军。
限流是核心。Nginx的limit_req模块用好了,能挡住80%的初级攻击。
# 在http块中定义限流规则
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 在具体location中应用
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://gunicorn_backend;
}
这个配置的意思是:每个IP每秒最多请求10次,允许突发20个请求。超过的直接返回503。别小看这个数字,对正常用户来说,一秒点10次已经算“手速惊人”了,但攻击脚本一秒能发上百次,正好被卡住。
缓存静态资源。很多CC攻击会故意请求图片、CSS、JS这些静态文件,虽然单个消耗小,但架不住量大。
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
设置长期缓存,这些请求就不会打到Gunicorn,Nginx自己就处理了。
05 协同防护的关键点
单独配置Gunicorn和Nginx不难,难的是让它们配合起来。
连接数要对齐。Nginx的worker_connections要和系统的ulimit、Gunicorn的worker数匹配。我见过一个案例:Nginx配了1024个连接,但系统限制只有512,结果一半连接被系统拒绝,白配了。
超时要接力。Nginx的proxy_read_timeout应该比Gunicorn的timeout稍长一点。比如Gunicorn设了10秒超时,Nginx可以设12秒。这样避免Gunicorn已经断开连接,Nginx还在傻等的尴尬情况。
日志要联动。Nginx日志记录客户端IP、请求时间、状态码;Gunicorn日志记录worker处理时间、请求路径。出问题时两边日志对照着看,很快就能定位是哪个环节被攻击打满了。
06 那些“小众但实用”的招数
除了常规配置,我再分享几个实战中好用的技巧:
用$http_user_agent识别爬虫。很多攻击脚本的User-Agent很固定,甚至直接是空。在Nginx里加个判断,把这些请求引导到静态错误页,别消耗动态资源。
给管理后台加IP白名单。很多攻击会先试探/admin、/wp-login这类路径。如果你的后台不需要公网访问,直接Nginx层面限制IP,省心省力。
监控关键指标。别等用户投诉了才发现被攻击。监控Gunicorn的worker占用率、Nginx的499/503错误码数量、单个IP的请求频率。设置阈值告警,早发现早处理。
(说到监控,有个坑提醒一下:别只看CPU和内存,Python应用要特别关注文件描述符数量和数据库连接数,这两个经常是被CC攻击拖垮的隐藏因素。)
07 什么时候该上“重型武器”?
如果你的应用确实重要,而且预算允许,可以考虑更专业的防护方案。但记住一个原则:从简单到复杂,从便宜到贵。
先调优Gunicorn和Nginx,这是零成本的。如果还不行,可以考虑:
- 云服务商的WAF:阿里云、腾讯云都有按量计费的WAF,规则更新快,能识别常见的攻击模式
- 高防IP:适合IP暴露且经常被针对的场景,但价格不菲
- 源站隐藏:用CDN或高防IP做前端,真实服务器IP不暴露,这是终极防护
但说实话,对大多数中小型Python Web应用来说,把Gunicorn和Nginx配置好,已经能防住90%的CC攻击了。很多团队的问题不是没上高级防护,而是基础配置都没做对。
08 最后几句大实话
防护CC攻击就像给房子装防盗门——没有绝对的安全,只有相对的成本。
攻击者也在进化,今天有效的规则,明天可能就被绕过。所以除了技术防护,更重要的是建立应急响应机制:谁负责监控、发现问题怎么沟通、切换防护策略的流程是什么。
别等到真被打的时候,技术群里@所有人问“怎么办啊急在线等”。平时做次演练,把关键配置写成文档,把监控大盘放在显眼位置。
行了,不废话了。如果你的Python Web应用还在裸奔,或者配置得稀里糊涂,今晚就抽半小时看看Gunicorn和Nginx的配置吧——这可能是你今年性价比最高的半小时投入。

