记一次被自己DDOS攻击
服务器报警
7月24号下午5点半开始,突然服务器报警,检查监控,发现CPU异常100%。
该服务器正常情况下CPU使用率在40%已经算高了,另外负载经过调试都保持在CPU承受范围内。
系统负载同时飙升
数据包的量直上云霄
TCP连接数上2W,正常情况下最多6K
最开始没有处理,一般来说ddos不会持续太久,结果7点服务器开始响应变慢反馈,必须处理了,辛亏有随身远程应急预案。
此服务器代码半年没动过,之前都正常的,只是中午的时候更新了下漏洞补丁,原则上是不会导致这个问题才对。通过linux命令分析了一下相关的进程,应该不是补丁导致的,否则打完补丁就应该出问题,而不是等到5点。
一开始为了应付CPU过高的问题,怀疑是我之前设置的php-fpm子线程过大(500),服务器上下文频繁切换,导致本身就已经高负载?索性就把值设为小到280试试看什么情况,但是并没有好转,php-fpm慢日志还建议调大,又调回之前的设置。
再来看数据包,已经要上天了,初步评估是ddos攻击。
初步分析
经过了1个多小时的日志分析,定位到心跳写数据库异常,导致数据库连接爆满卡死,影响到了别的业务。所以禁用了该接口,服务器相对可用。
晚上11点多回到家,依旧没有恢复的意思,并且还出现了每隔5分钟一次攻击(00:16之后)。决定用cache的inc记录看一下接口调用情况。
基本上是每秒1K+的访问,偶尔会有高并发,短时间调用了76W+次,其他接口几乎为0,现在是接近凌晨2点钟,理论上设备这个点钟已经关的差不多了,而且默认设备是5分钟调用一次心跳接口,不可能在这个时候大面积并发。
DDOS无误,但是这个量好像有点小,并且一般也不会通过接口调用形式攻击吧,阿里云都没有触发ddos流量清洗。
进一步分析
接下来就是看哪个IP发送的了。用netstate查了下感觉好像又比较正常。
根据该方法的日志,看到这些IP在几秒内调用接口300次左右,有些不可思议,但是这些IP确实是对应的设备IP,难道是被自己的设备DDOS了?!
再来5分钟一次心跳,不就是监控中后来的5分钟一次异常情况?每五分钟会出现一次峰值。
但是他们是如何做到秒级的百次调用呢?除非APK有问题,但是之前又没见出现?
再次深入分析,尝试禁封某些设备IP无效,反而更加猖狂,应该是设备APK集体出现BUG了,导致实例化了N个线程同时进行接口调用……怎么办?设备端的APK是友方开发,并且长时间没有更新维护了,又没办法让设备重启,最后决定分析设备日志。
最终分析
第二天联系运维人员取了一台并发量很高的设备日志。刚好这台设备记录了事件的全过程,分析结果如下:
1、7月24号5点半之前,设备运转良好
2、之后出现心跳时token失效的情况,然后开始以指数级新增心跳线程。
可以看到重新获取token之后,就出现了2个心跳包发送请求
3、反编译APK发现重新获取token部分的代码是有bug的
这里应该是if和else,否则在没有重新获取到token的情况下,又立马执行一次runnable,导致又再次报错一次。
4、这个异常情况只会在token过期的时候出现,正常情况理论不会过期,所以这个bug一直没有发现。
分析出问题之后,服务端临时去掉了token校验,联系友方修复bug,发布更新,问题解决。
总结
昨晚搞到4点钟,今天继续分析到4点,历时10个小时心中的石头终于落下。
1、设备端应至少有重启指令,以防万一。
2、一个小小的逻辑代码,可以使服务器直接崩溃。
3、日志监控真的很重要。
4、对于一些特殊情况,普通的测试很难遇到,除非是有经验的测试人员,否则只能等线上才能发现了。