前阵子服务器被不知道有意还是无意攻击了2次。。说是两次,,还是保守说法,因为这两次太猛烈了。直接导致服务当掉。。
第一次是年前,,具体是哪天不记得了(好像是26日)。。(最近事情多。忙得不可开交),那天记得我在服务器上调试PHP程序(因为cookie设置问题。我本地windows上跑不起来。只好迁到远程),但是后来服务器越来越慢,后来直接页面都刷不开了。开始以为是程序有问题,死循环什么的耗尽了服务器资源,,赶紧打了个电话去宁波让吕刚去reset一下,,但是重启后情况还是不见好转,就以为是服务器长时间超负荷工作。。硬件坏了。。但是开始让吕刚跑到机房把服务器抱到办公室插上键盘显示器。发现很好都没有问题。。然后再放回机架,故障依旧。。纳闷了。。远程遥控别人还真累,后来实在没有办法就把键盘显示器全都搬到了机房插上。。据说login都要等上n分钟。。拔掉网线又一切正常了。因为在插上网线的时候基本无法实现任何命令行操作。。所以只有凭空想象是不是http服务被人攻击了。。
赶紧service httpd stop然后再插上网线,嘿。。就好多了。。
因为当时服务器访问量非常大。一天有好几万,所以为了节省有限的服务器资源。。我把apache的log给关了。。所以就根本无法追根溯源得知请求来自哪里了。。但是http服务全关了不甘心。。mysun.org跟www.mysun.org的嫌疑最大。先把注释掉这两个virtualhost,再把服务起来。。嘿。。还是没事。。
就这样将就了几天,,转眼就过年了。。心里又痒痒起来。。小心翼翼地先把下载服务给停掉(因为所有下载都是首先请求download/index.php的,我就偷懒把index给mv掉,然后touch了一张new index.php,直接header location到gusetbook,如果网友来,,还可以暂时留点言什么的。),把mysun又开起来,做了张新年海报。。喜气洋洋一点。然后再把日志也开起来。。又相安无事了两天,前天傍晚,http服务又全线告急。IE根本刷不开页面,下载几乎没有流量,幸好ssh能上去。top一看,全是http服务,service httpd status进程号显示了一屏幕。。那个壮观啊。。
赶紧service httpd stop,其他ftp,ssh服务延时又恢复正常,,tail 了一下apache的log,发现请求都是去往http://www.mysun.org/download/XXX的,用户居然猜测出了我的实际路径跟原来的index.php的关系。。强!直接用flashget什么去下rmvb。。grep+wc一下还有单IP100线程的。。太变态了。。连最基本的对其他用户的尊重都没有。。
大过年的,,太忙了。。就先把download文件夹的软链接删了了事(download文件夹不在web目录下就是方便啊。哈哈)。。
这几天心事太重了。。半夜睡不着。。就起来捣鼓服务器。。google了一下,,发现据说mod_limitipconn可以做IP单线程限制。。说干就干。。先上mod_limitipconn的老巢:http://dominia.org/djao/limitipconn.html,上面的文档比较简洁明快。。mod_limitipconn有n多安装方式。。我——土人一个,编译复杂一点的东西老是失败。。不知道是不是人品问题。。就wget了个for FC3的rpm,寻思着FC3跟EL4应该是如出一辙。。rpm -qpl一看,
/usr/lib/httpd/modules/mod_limitipconn.so
/usr/share/doc/mod_limitipconn-0.22
/usr/share/doc/mod_limitipconn-0.22/ChangeLog
/usr/share/doc/mod_limitipconn-0.22/README
哈哈,要的就是mod_limitipconn.so,而且安装路径完全跟EL4的apache modules路径匹配,那就更方便了。rpm -ivh mod_limitipconn-0.22-1.i386.rpm
more一下README,easy,里面有example,cp到httpd.conf再改一下。。
# limitipconn_module configuration
ExtendedStatus On
LoadModule limitipconn_module lib/apache/mod_limitipconn.so
<IfModule mod_limitipconn.c>
<Location /data/website/>
MaxConnPerIP 1 # Max connection number per IP
</Location>
</IfModule>
哈哈,大功告成!
重启httpd服务,居然提示语法错误。。说我传递了多个参数给MaxConnPerIP,匪夷所思。。幸好vim的语法加亮提示了我。。#跟紧跟的注释并没有变成深蓝色。。那就意味着没有被正确注释掉。。中间有空格当然就视作mutil args了,
直接删掉#跟后面的注释(应该是我bash基础不过关了。。#可能只能在行头做整行注释,跟perl略微不同。。)保存,重启服务,OK了,
拿迅雷测试一下。。bingo,太打击人了。。10线程下载居然一点问题都没有。。百思不得其解。。难道IfModule mod_limitipconn.c应该改成IfModule mod_limitipconn.so?(因为我不是拿mod_limitipconn.c编译所得。。)试了一下还是不成功。。那么到底应该是.c还是.so呢?对了,不是可以拿注释去试么,,改成.so,添加了原本被判断为语法错误的#注释,没有提示出错。这下证实了我的想法,应该是.c的,那问题究竟出在哪里呢?版本号也应该没问题,是for apache2的,
不管了。。先来个全限制试试看,<Location />,嘿嘿把根全限掉。。重新下载,,迅雷开始报错。。后几个线程无法链接上服务器了。。哈哈,
这时候一个念头闪过。。是不是这个根是指apache的url根呢?也就是http://XXX.XXX/
那就试一下。。<Location /download>,哈哈哈哈哈哈,果然。。再试一下:<Location /test>果然download子目录又不限了。。
不错不错。。为了合理起见,就是用户看到一个自己需要的资源在下载的同时,比如200M,还可以继续浏览download目录下的其他文件列表,(所有http请求当然全部被视作单个session了!如果定为MaxConnPerIP 1,那用户一边下东西,一边就无法继续浏览其他资源了。郁闷程度可想而知。。或者是在下一个大东西。。而且已经下到80%了,然后突然看到一个比较诱惑的名字。。文件也比较小。。想马上一泽芳容,这个时候,双线程也就能显示其合理性了。。)
我帅吧。。。哈哈哈哈。。服务当然要以人为本啦~
忙活了那么久,就先这样跑着吧。。看看负载再说。。(本来是想用iptables也试试做访问规则的。。可以对比一下到底是防火墙层拒掉请求数据包效率高一点还是加载apache module效率高,但是看了一下iptables的文档,有点晕晕。。就放弃了。。懒人一个,,大概是受上次学校计算中心事件影响。什么服务器我拿到手里首先就来个service tptables stop/chkconfig iptables off,。。省了很多稀奇古怪的事。。)