一、怎么判断是不是被CC攻击了
CC攻击和正常流量峰值很像,这几个特征可以判断:
- 网站突然打开很慢或者502/504错误,但带宽使用率没跑满,CPU、内存、PHP、MySQL负载跑满了——因为CC是请求动态页面,消耗服务器计算资源,不是打满带宽;
- 看Nginx访问日志,同一个IP或者同一批IP短时间内大量请求同一个URL,比如一秒钟请求几十上百次;
- netstat看连接数,有大量同一个IP的ESTABLISHED连接:
netstat -ntu | awk '{print $5}' | cut -d: -f4 | sort | uniq -c | sort -nr | head -20
如果某个IP有几十上百个连接,大概率是攻击。 CC攻击的IP很多都是真实的代理IP,不像DDOS流量那么好识别,但是小规模CC还是有很多方法可以防的。
二、第一步:先封最明显的恶意IP
如果攻击IP比较集中,比如只有几个IP在疯狂请求,直接用Nginx或者防火墙封掉就行:
Nginx封IP:
在Nginx配置里加deny规则:
# 在server块或者http块里加deny 1.2.3.4; # 封单个IPdeny 1.2.3.0/24; # 封整个IP段
或者用iptables封:
iptables -I INPUT -s 1.2.3.4 -j DROP
如果攻击IP特别多,一个个封不过来,可以用fail2ban自动识别频繁请求的IP封禁,配置一下Nginx日志的规则,1分钟内请求超过60次的IP自动封1小时,能挡住大部分脚本小子的攻击。
三、第二步:Nginx层面做限流,挡住大部分请求
Nginx自带限流模块,不用装额外工具就能配置,针对单个IP限制请求频率: 在Nginx的http块里加限流区域配置:
# 定义限流区域,每个IP每秒最多10个请求,内存区域10Mlimit_req_zone $binary_remote_addr zone=cc_limit:10m rate=10r/s;
然后在要防护的server块或者location块里应用限流:
location / {limit_req zone=cc_limit burst=20 nodelay; # 突发最多20个请求不延迟# 剩下的正常配置try_files $uri $uri/ /index.php?$query_string;}
配置完nginx -t检查没问题就reload生效,这样单个IP每秒最多请求10次,超过的会直接返回503,不会把后端PHP/MySQL跑满。 注意rate别设太小,不然正常用户访问也会被拦,一般动态站点设10r/s左右足够了,正常用户一秒钟不可能点10次页面。 还可以针对特别耗资源的路径单独限流,比如搜索接口、评论接口,这些接口最容易被CC打,设更严格的限流规则:
location /search {limit_req zone=cc_limit rate=2r/s burst=5 nodelay;}
四、第三步:上CDN隐藏源站IP,挡第一层攻击
如果已经封IP、限流过了还是扛不住,就把网站套上CDN,把源站IP隐藏起来,所有请求先到CDN节点,CDN帮你挡一层攻击:
- 不要用廉价的免备案CDN,很多小CDN根本防不住CC,选大厂的CDN,比如阿里云、腾讯云、Cloudflare的免费版都有基础CC防护;
- 套CDN之前一定要确认源站IP没泄露过,不然攻击者直接绕开CDN打源站IP,CDN就白加了。如果IP已经泄露过,最好换个新的服务器IP再套CDN;
- CDN后台可以开CC防护、人机验证、频率限制,比服务器层面防效果好很多,攻击者看不到源站IP,打源站也打不到。
五、几个注意事项
- 尽量把静态页面缓存起来,比如首页、文章页这种不经常变的页面,用Nginx或者CDN缓存,请求直接在缓存层返回,不用请求PHP和MySQL,就算有CC请求,也不会消耗服务器资源,扛攻击能力会强很多;
- 不要一被攻击就拔网线关站,那样攻击者知道你站容易打死,以后会经常来打你;
- 如果是大规模的CC攻击,CDN免费版扛不住,那就只能买高防了,不过个人小站一般遇到的都是小规模CC,前面几个步骤基本就能挡住。