作者:田逸([email protected])
正在努力板砖,一阵急促的电话铃想起,同事紧急告知,论坛访问很慢,其它技术人员已经折腾了半天找不到原因,需要尽快处理。
首先简单了解了一些情况,运营的同事说前几天有管理员帐号被泄漏(咋泄漏的?设置简单密码,真像把后备箱那块砖拿过去拍他),被人用工具自动发帖,好家伙,一晚上发了上万个帖子。上午在qq群里看他们聊天,说费了很多时间才把这些垃圾帖子删掉。论坛的discuz程序没有做任何改动,怀疑是被恶意攻击。论坛不能访问已经大半天,来不及详细了解情况,挽起袖子,开干了。
再登录系统前,查阅资料确认整个论坛的逻辑拓扑,如下图所示:
注:此图省略了管理网络(通过vpn对服务器进行管理)
按这个拓扑结构,逐级进行检查和排错,具体步骤为:
(一)负载均衡器进行检查
1、检查系统负载、内存使用情况:输出表明是正常的;
2、检查磁盘空间使用情况,未发现有分区被塞满;
3、检查系统日志,为发现异常输出;
4、检查应用程序运行情况,执行命令 ipvsadmin ,有转发数而且数字不断变化,这可以确认应用程序keepalived 及lvs都是正常的。
由上面几点可确定负载均衡毫无问题,模拟故障切换,用户的请求也能自动切换到辅助负载均衡器。
(二)检查应用服务器
1、查看几个服务器的负载,load值好几十,严重超标;
2、查看磁盘空间使用情况,为发现使用率大于80%的分区;
3、查看系统日志,未发现文件系统损坏,内核异常之类的问题;
4、查看内存使用情况,未发现耗尽内存而占用交换分区swap的情况;
5、检查应用程序php及nginx,nginx无异常,而php偶尔有慢日志输出;
初步判断,是php引起的负载异常。关闭php片刻,系统负载很快降到正常水平。怀疑被人恶意攻击,通过查看tcp状态,也无有价值的线索。
如果被攻击,同一个ip的tcp连接数应该可能是很大的一个值。一般的经历,是上千上万的水平。尝试用iptables禁掉几个连接数多的源ip,效果不明显,负载还是很高。关掉php,负载降低,再启动,负载很快又爬升起来。看来,问题还不在这里。
(三)检查与应用服务器紧密关联的文件服务器
论坛程序是以nfs的方式共享给多个应用服务器使用的,这样的目的在于减少服务器之间的数据同步,假如不以共享的形式,则每个应用服务器都应保存一份完全相同的数据文件。因为一些数据文件随时间推移会不断发生变化,那么为了保证用户访问的一致性,就必须实时同步这些更新数据。
1、 检查系统负载、内存使用情况,发现一切正常;
2、 检查磁盘空间使用情况,未发现被塞满的分区;
3、 检查系统日志,未发现异常输出;
4、 检查nfs相关进程和配置,未发现异常;
以前发生过论坛访问异常的情况,引起的原因就是共享文件系统(nfs)分区文件系统损坏,导致nfs客户端(即php应用服务器)不能写入缓存。为了确认这个猜测,在文件服务器及客户端,都进行了创建和删除文件测试,一切正常。
(四)检查缓存服务器。
数据缓存使用的应用程序是memcached,这种服务器系统,仅仅运行这么一个应用,因为是内存存储数据,因此一般情况下,怀疑有故障,只需重启memcached,让它再重新缓存就好。
1、 检查系统负载、内存使用情况,一切正常;
2、 检查系统日志,无异常;
3、 检查网络状况,也很正常;
重启memcached,对应用服务器的负载毫无帮助,看来问题也不在这里。
(五)检查数据库服务器。
仅仅剩下它了,问题很显然,就与这个相关。吸一口带雾霾的空气,登录主数据库及从数据库服务器系统,进行如下常规排查。
1、 检查系统负载、内存使用情况,一切正常;
2、 检查磁盘空间使用情况,未发现被塞满的磁盘分区;
3、 检查系统日志,未发现异常输出;
4、 检查网络连接情况,主服务器连接数很少,而从服务器的连接数很多;这至少说明,在系统层面,主数据库服务器的正常的,从服务器系统,在系统层面看来,也基本认为是正常的。
本集群使用的论坛程序discuz本身支持数据库读写分离,因此主服务器的任务是承担数据更新的任务,而查询一类的工作,则由只读状态的从服务器(slave)承担。我们先层主服务器的应用层面进行排查,步骤如下:
(1)、检查mysql的错误日志及满查询日志,为发现异常输出;
(2)、检查mysql进程是否正常,执行mysql –p 登录一下,能进入mysql客户端命令行,守护进程正常;
(3)、mysql客户端执行命令 show full processlist;输出寥寥几行,一切在可以接受的范围;
由此判定,数据库主服务器无异常。
现在,山穷水尽,水落石出,问题多半就是这个从数据库服务器的问题了。系统层面的检查,为发现有用的线索。查mysql错误日志,未见异常;查mysql慢查询日志,果然有输出,而且还不断有新的输出。
一条sql语句好长啊,限于篇幅,不打算全副输出截图。登录mysql客户端,执行show full processlist; 天啦,好半天才输出完毕,线程数超过1000了(我设定的mysql最大连接数是1000),而输出的内容,大部分是慢查询里边的东东。用 mysql –p –e “show processlist;”>/root/sql_out 把这些sql形成一个文本文件,转发给程序员。他们看半天,也没有得出一个结论。有人建议杀掉看是异常的sql语句,但杀掉后,还是不行。大家还是怀疑被攻击,通过dns处理,把请求先定向到360,起到一定的攻击过滤作用。从监控见面看,确实有结果cc攻击被拦截。但对应用服务器的负载降低不起什么作用,并且论坛还是处于打不开的状态。
以超级系统管理员的帐号登录论坛后台,关闭论坛后,服务器负载立即恢复正常水平;再打开论坛,负载立马飙升。邪门了啊,居然在技术层面查不出问题所在。折腾了一天,头都大了。在qq群嚷了几句:“谁改了程序没有?谁在后台做什么设置没有啊?…..”,有人冒出来一句:“删垃圾贴的时候,为了快速删除,设置了页面显示帖子的数量值”。
我数学是政治老师教的,算不出多个板块多人访问的时候,具体要显示多少条记录,但大家都相信,这一定是很恐怖的一个数字。
发现问题,意识到问题的严重性。
论坛后台更改这个设置,几秒钟后,应用服务器的负载降下来了,从数据库的连接数也趋于正常,论坛也可以跟以前一样,可以浏览、发帖……
这一切,追溯起来,就是某些论坛管理员设置该死的简单密码。