幻想游戏网被攻击实录及总结

最近近一个月幻想游戏网都处于被攻击的状态,每天靠业余时间去维护、防御也搞得焦头烂额。昨晚终于恢复所有功能正式上线,整个过程大部分是我来搞的,应大佬要求,写一篇防御攻击的一些分析方法和总结。

前奏

11月的时候,网站偶尔会访问很慢,一开始也没放在心上,因为是偶尔出现的情况就以为是并发引起的问题,就没有太在意,准备有时间好好检查下程序的瓶颈(最后发现我们网站就没那么大并发-_-难过ing)。

最后有用户反映,简单的一个签到都要等十几秒。看下服务器负载,高的可怕,但当时对这方面经验真的很少,还以为是并发的问题,于是准备去优化下幻想游戏存在的性能问题。

优化

幻想游戏一直使用的是关系型数据库(MySQL),对于数据量比较大时候,读写还是比较消耗IO开销的。最开始做网站的时候,还是个学生,数据量也小,并没有考虑太多数据库层面的事情。一年时间,有的数据表数据已经几十万行了,竟然还没有建索引,着实有点尴尬,于是在数据库层面做了优化。

首先是MySQL的索引,按照经理的说法,每个表都至少有两个索引,虽然会对写操作有影响,但是带来的益处远大于弊端。我对所有读操作比较频繁的表都建立了索引,索引这块涉及的知识也还是很多的,“最左原则”、联合索引等等的(第一次面试的时候就在这块狠狠的被打击了)。

然后是签到数据,理论上来说,做操作的时候只要有用户前一天的数据就可以了(目前的逻辑是读取用户前一天的签到天数,如果是连续就累加,不连续就从1开始),所以之前的数据基本上是没用了,写了个脚本,清理了一个月前的签到数据(哈哈,毕竟感觉离做大数据分析还有点远)。

最后是redis,网站有排行榜功能,目前是实时更新的,像下载表、签到表什么的,数据已经几十万条,不停的读写,消耗应该说还是很大的,于是将排行榜的数据全部放入了redis里面,并配合Linux的crontab定时任务和Laravel的任务调度每周对排行榜进行一次更新。

攻击

本以为做了以上优化,负载会降下去了,现实却给了我一巴掌(最开始也说,网站目前的流量根本到不了优化性能那一步)。负载还是居高不下,网站基本处于瘫痪状态,把网站日志文件下载下来,准备分析一下。

结合Excel的分析能力,发现很多ip访问异常频繁,初步断定是ddos攻击,或者是有人在爬取我们网站。然后,安排,在程序基类写了一个限制ip访问函数,如果一分钟之内访问大于20次,就不让访问了,上线后果然负载降了下来,偶尔会满,但很快就降下来了。心里还挺美的,当时时间是下午五点多。

晚上和同事吃了顿饭,回到家九点多,打开宝塔面板,负载到了四五十···,一下子就懵了,看来对方是加大了力度,而且ip都很分散,基本无法判定是攻击还是普通用户。等到第二天到公司,发现了更可怕的事,由于匆忙上线,redis没有设置密码,被对方植入了挖矿程序(看到了一个shell脚本,查了里面关键的变量名,发现是和挖矿相关的东西)。于是搜相关资料,并在服务器全局搜了相关关键字,没有发现相关的脚本,而且服务器CPU正常。设置了redis密码(强度要高,平时感觉没啥,真被攻击就凉了),就继续搜防攻击的方法了。

防御

首先是预防一下对方是否是大面积的ddos攻击(其实能判定不是针对ip攻击的),还是对ip进行了隐藏,用的是加速乐提供的cdn隐藏服务器真实ip的服务,具体操作就不写了。

其次是分析日志,把一下访问频繁的ip直接禁掉。

但其实作用微乎其微,攻击还在继续。我们继续排查问题,我们把www开头的域名解析给停掉之后,发现负载正常了,所以判定对方攻击的www开头的域名,日志里面还有很多莫名的post请求(一看就不是网站内部路由),无奈我们先暂停了www的解析。

烦人的搜索引擎爬虫

之后我们一直用http://hxyou.cn 对用户进行开放,但也会存在负载爆满的情况,但不像之前那样高的离谱,不确定是不是又遭受到攻击。于是把网站日志下载下来,继续分析。

分析主要是看IP访问的频率以及请求的UA,可以看到有很多都是搜索引擎的爬虫,比如BaiduSpider,bingbot,YiSouSpider。但是也没听过爬虫能把网站爬垮的新闻。经过不断排查,发现有一个请求的UA出现的非常频繁,bytespider。分析得到的结果是今日头条的爬虫暴力爬取导致负载过高(真的很流氓),并且阿里系的神马搜索也很频繁,以及微软的必应。

既然这些搜索引擎这么流氓,不好意思,我也不需要您收录我们了。我在Nginx的配置文件里放了如下代码:

        #禁止Scrapy等工具的抓取
        if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) 
        {
             return 403;
        }
        #禁止指定UA及UA为空的访问
        if ($http_user_agent ~ "FeedDemon|bingbot|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|^$" ) 
        {
             return 403;             
        }
        #禁止非GET|HEAD|POST方式的抓取
        if ($request_method !~ ^(GET|HEAD|POST)$) 
        {
            return 403;
        }

这样,可以屏蔽你不想要爬取的搜索引擎爬虫。

同时也在网站根目录下面加了robots.txt文件,定义了一下,除了百度、谷歌,都不如爬取了。

监控

平时还有工作,也不能时时刻刻盯着服务器的负载,但是宝塔的监控推送好像是收费的,又不想掏钱,只能自己写一个了,思路如下:

利用php的sys_getloadavg()的函数读取当前服务器负载(这个函数只能在linux下用),把它写成laravel的命令,可以执行命令行返回负载值。然后结合linux的crontab定时任务和laravel的任务调度,每隔一分钟执行以下这条命令,如果负载大于1,就发邮件给我。

(小声bb:laravel的任务调度语法真优雅)

$schedule->command('SendLoadByEmail')->everyMinute()->between('8:00', '22:00');

结尾

网站终于恢复上线了,流失了不少用户,我们也给用户发放了积分、vip补偿,但是无法否认的是,这次真的是被对方吊打,幻想游戏网也是元气大伤。不过也算是给自己交了学费,积累了不少网络安全的知识(虽然很浅薄),要享受分析、解决问题的过程,也是一次很宝贵的经历了。

“幻想游戏网被攻击实录及总结”的5个回复

  1. 十多年前玩的幻想游戏2.0,昨天突然想到这个游戏了!就百度搜了一下,网站真的还在!但是没找到2.0、安装的3.0

发表评论

电子邮件地址不会被公开。 必填项已用*标注