2016年10月23日,一个普通的周日晚上。
我正坐在沙发上看电视,突然手机响了,是服务器监控的告警短信:"服务器CPU使用率超过90%,带宽使用率超过90%。"
我心里咯噔一下,赶紧打开电脑,想SSH连上服务器看看情况。但是,SSH连接超时,连不上。网站也打不开,一直转圈。
我知道,出事了。
一、攻击发生时的现象
我先登录了云服务商的控制台,看看服务器的状态。
控制台显示,服务器的CPU使用率100%,带宽使用率100%,入站流量达到了几百Mbps,远远超过了平时的几Mbps。但是,服务器的状态是"运行中",没有宕机。
我尝试通过控制台的VNC登录服务器,终于连上了。登录之后,发现服务器非常卡,输入一个命令要等好几秒才能响应。
我先看了一下网络连接:
netstat -an | grep :80 | wc -l结果显示,有几千个连接到80端口,而且IP地址来自全国各地,明显不是正常的用户访问。
再看一下Nginx的访问日志:
tail -f /var/log/nginx/access.log日志刷得飞快,每秒有几百条请求,而且都是请求同一个页面(首页),User-Agent各种各样,IP地址也不一样,但是请求的内容都一样。
我马上意识到,这是被CC攻击了(Challenge Collapsar,是DDoS的一种,通过大量的HTTP请求把服务器压垮)。
二、排查过程
确认是CC攻击之后,我开始排查攻击的具体情况。
1. 分析攻击流量
我先看了一下Nginx的访问日志,统计一下攻击的特征:
# 统计访问量最高的URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 统计访问量最高的IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 统计User-Agent
awk '{print $12}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10分析结果显示:
- 攻击主要请求首页(/),占了90%以上的请求
- 攻击IP非常分散,来自全国各地,每个IP的请求量都不大(每秒几个请求),但是IP总数很多(几千个)
- User-Agent各种各样,有正常的浏览器UA,也有一些奇怪的UA
- 请求频率非常高,每秒有几百个请求,是平时的几十倍
这是典型的分布式CC攻击,用大量的肉鸡(被控制的电脑),每个肉鸡发少量请求,合起来就是大量的请求,把服务器压垮。
2. 检查服务器状态
我又看了一下服务器的状态:
# CPU和内存
top
# 网络连接
netstat -an | grep :80 | wc -l
# Nginx进程数
ps aux | grep nginx | wc -l
# PHP-FPM进程数
ps aux | grep php-fpm | wc -l结果显示:
- CPU使用率100%,主要是PHP-FPM进程占用
- 内存使用率80%,还没有用完
- 80端口的连接数有几千个
- Nginx和PHP-FPM的进程数都达到了上限
攻击的原理很清楚了:大量的HTTP请求,每个请求都要PHP处理,PHP-FPM进程被占满,新的请求只能排队,导致网站打不开,CPU跑满。
三、应急处理
确认了攻击情况之后,我开始应急处理。
第一步:临时封禁攻击IP
我先从访问日志中,找出请求量比较大的IP,用iptables临时封禁:
# 找出请求量超过100的IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | awk '$1 > 100 {print $2}' > /tmp/block_ips.txt
# 用iptables封禁
while read ip; do
iptables -I INPUT -s $ip -j DROP
done < /tmp/block_ips.txt但是,效果不好。因为攻击IP非常分散,每个IP的请求量都不大,封禁了一批,又来一批,根本封不完。
第二步:开启Nginx限流
封禁IP效果不好,我又开启了Nginx的限流模块(ngxhttplimitreqmodule),限制每个IP的请求频率:
# 在http块中配置
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
# 在server块中配置
location / {
limit_req zone=one burst=20 nodelay;
# ... 其他配置
}配置之后,重启Nginx。限流的效果还不错,每个IP每秒最多10个请求,超过的请求会被Nginx直接拒绝,不会到PHP-FPM。
但是,攻击IP太多了,虽然每个IP的请求被限制了,但是几千个IP,每个10请求/秒,合起来还是几万请求/秒,Nginx还是有点扛不住。
第三步:启用CDN防护
限流只能缓解,不能根本解决问题。我决定启用CDN(内容分发网络),把网站流量先到CDN,CDN过滤掉攻击流量,再把正常流量回源到服务器。
我用的是某云服务商的CDN,开启了"CC防护"功能。配置很简单:
- 把域名的DNS解析到CDN
- 在CDN配置回源地址(服务器的IP)
- 开启CC防护,设置防护等级
配置完成之后,等DNS生效(大概几分钟),网站的流量就先到CDN了。CDN会自动识别并拦截CC攻击,只把正常的请求回源到服务器。
启用CDN之后,效果立竿见影。服务器的入站流量从几百Mbps降到了几Mbps,CPU使用率从100%降到了20%以下,网站也恢复正常了。
CDN的CC防护,确实很有效。它有大量的节点和带宽,能扛住大流量的DDoS攻击,而且有智能的攻击识别算法,能准确识别并拦截CC攻击。
第四步:后端优化
启用CDN之后,攻击被挡住了,但是我还是做了一些后端优化,提高服务器的抗攻击能力:
- 页面缓存:把首页和文章详情页,用Redis做缓存,缓存时间5分钟。这样,大部分请求直接读缓存,不需要PHP处理,减轻了服务器的压力。
- 静态资源优化:把CSS、JS、图片等静态资源,都放到CDN上,不经过服务器,减少服务器的带宽和请求量。
- Nginx优化:调整了Nginx的workerprocesses、workerconnections、keepalive_timeout等参数,提高Nginx的并发处理能力。
- PHP-FPM优化:调整了PHP-FPM的pm.maxchildren、pm.startservers等参数,合理设置进程数,避免进程数过多导致内存不足。
四、事后总结
攻击持续了大概3个小时,从晚上8点到11点。启用CDN之后,攻击就被挡住了,网站恢复正常。
事后,我做了一些总结:
1. 攻击的原因
这次攻击,可能是因为我在某个论坛上和人吵架了,对方报复性地攻击我的网站。也可能是随机扫描,碰巧扫到了我的网站。具体原因,不得而知。
但是,不管是什么原因,网站被攻击了,说明我的安全防护做得不够。
2. 做得好的地方
- 有服务器监控,能及时发现异常
- 能快速判断攻击类型(CC攻击)
- 应急处理比较及时,从发现到恢复,用了大概1个小时
- 启用了CDN防护,从根本上解决了问题
3. 做得不好的地方
- 没有提前启用CDN,导致攻击发生时手忙脚乱
- 服务器没有做限流和缓存,抗攻击能力弱
- 没有DDoS攻击的应急预案,遇到攻击时,临时想办法,浪费了时间
- 数据备份不够及时,如果攻击导致数据丢失,后果不堪设想
4. 经验教训
- 安全无小事:不要觉得自己的小网站不会被攻击,现在的攻击工具很发达,随便一个人都能发起DDoS攻击
- 防患于未然:提前做好安全防护,比攻击发生了再补救,要好得多。提前启用CDN、配置限流、做好缓存,能大大提高网站的抗攻击能力
- CDN是个好东西:CDN不仅能加速网站,还能防护DDoS和CC攻击,对于中小网站来说,是性价比很高的安全防护方案
- 做好数据备份:不管有没有攻击,都要定期备份数据,最好是异地备份。万一服务器出问题(被攻击、硬盘损坏、服务商故障),数据还能恢复
- 制定应急预案:提前制定各种突发情况的应急预案,比如DDoS攻击、服务器宕机、数据丢失等,遇到情况时,按照预案处理,不会手忙脚乱
五、后续的安全加固
这次攻击之后,我对网站做了全面的安全加固:
1. 网络层防护
- 启用CDN,隐藏服务器真实IP
- 配置CDN的CC防护和DDoS防护
- 服务器只开放80和443端口,其他端口都关闭
- 用iptables限制SSH的登录IP,只允许特定IP登录
2. 应用层防护
- 配置Nginx限流,限制每个IP的请求频率
- 用Redis做页面缓存,减少PHP处理
- 静态资源全部放到CDN
- 配置WAF(Web应用防火墙),拦截SQL注入、XSS等常见攻击
3. 系统层防护
- 定期更新系统和软件,修复安全漏洞
- 禁用root登录,用普通用户+sudo
- 用密钥登录,禁用密码登录
- 配置fail2ban,防止暴力破解SSH
- 定期检查系统日志,发现异常及时处理
4. 数据备份
- 每天自动备份数据库,备份文件保留7天
- 每周备份网站文件,备份文件保留4周
- 备份文件同步到云存储,异地备份
- 定期测试备份恢复,确保备份可用
六、写在最后
服务器被攻击了:一次DDoS防护的真实经历。
这次攻击,虽然给我带来了一些麻烦,但是也让我学到了很多东西。以前,我总觉得自己的小网站不会被攻击,安全防护做得不够。这次攻击,给我敲响了警钟。
安全无小事,防患于未然。不管是大网站还是小网站,都要做好安全防护。不要等到被攻击了,才想起安全的重要性。
现在,我的网站已经做了全面的安全加固,CDN、限流、缓存、WAF、备份,都配置好了。虽然不能说绝对安全,但是抗攻击能力已经大大提高了。
如果你也有自己的网站,我建议你也检查一下安全防护做得怎么样。有没有启用CDN?有没有配置限流?有没有做缓存?有没有数据备份?有没有应急预案?
如果这些都没有,建议你尽快做起来。不要等到被攻击了,才后悔莫及。
最后,用一句话总结:
"安全是1,其他都是0。没有安全,一切都是空谈。"
愿我们的网站,都能安全稳定地运行。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录