晚上23点左右收到大量的监控报警,公司网站直接不能访问了,立即登录服务器,直接top看到情况如下:

wKiom1R33o2CIglhAAH_T-KD8CQ742.jpg

发现负载都达到了800了,机器眼看就要爆了,首先先停了mysql,发现负载有点下降,联系了开发同事一同查看,因为今天新上线了一些代码,可能是新上代码的问题,随后看到负载依然没降,然后将php和nginx都重启了,虽然短暂的降了一些,过一会立马负载又起来了,这时看了下nginx日志,看是不是用户访问导致的问题,结果一看就发现问题了,如下:

wKiom1R33qWyrnY3AAjSqydwWmA873.jpg

30分钟发了60w+的请求。

wKioL1R331XyfvTlAABaLA8wHwQ087.jpg

发现这个ip不停的发请求,很明显,是被攻击了,临时将这个ip在nginx中deny掉,直接返回给它503,配置如下:在server中加入

wKiom1R33ufBOvfaAAApMj1Nqyg355.jpg

负载也慢慢降下来了,服务也正常了,当时太晚了,洗洗就睡了,结果第二天早上一来又发现网站打不开了,直接看nginx日志,攻击者换了一个ip,跟昨晚的现象一样,这次直接在源头把他干掉了,就是添加iptables,如下:

wKioL1R334OSr2v5AAEr8pgdt3M099.jpg

将攻击的ip全部写入iptables里面,然后联系机房看能不能做策略协助解决这种CC攻击,最后机房那边也将这些ip给封了,但是攻击者在换ip怎么办?不可能他换一个我加一条把,看来只能发大招了,写了个iptables脚本,如下:

wKiom1R33xXyQS2tAAEmHF3l-ro822.jpg

统计tcp连接,同一ip超过500次tcp连接的肯定就是攻击者的ip了,正常用户也不可能一下去开500个窗口去访问我的网站吧,然后将这个ip直接在iptables上面干掉,现在好了,问题解决了,这种CC攻击有一个特点就是用的源ip基本都是固定的,DDOS有些可能是用不同原ip进行攻击,那么这种防御就显得有些吃力了。那遇到不同源ip攻击怎么防御呢?

首先要联系机房,一般机房都有监控和防御设备,让机房帮忙解决一些问题可能更有效,

不能在iptable上面去防御,就只能通过nginx去防御了,让nginx去识别哪些是攻击者,哪些是真正的用户?其实nginx有2个模块:ngx_http_limit_conn_module和ngx_http_limit_req_module 可以参考官方文档:

http://nginx.org/cn/docs/http/ngx_http_limit_req_module.html

http://nginx.org/cn/docs/http/ngx_http_limit_conn_module.html

首先在http中定义,如下:
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

然后到你需要限制的目录下面,server段中,一般就是php请求,如下:

location ~* ^/(.*)\.php?$ {

limit_conn addr 3;
limit_req zone=one burst=2 nodelay;

fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $host_path/$fastcgi_script_name;
include fastcgi_params;
}

应用这2条规则后,只要需要执行php脚本的这些页面同一个IP只许建立3个连接,并且每秒只能有1个请求(突发请求可以达到2个)。
虽然这样的规则一般来说对正常的用户不会产生影响(极少有人在1秒内打开3个页面),但是为了防止影响那些手快的用户访问,可以在nginx中自定义503页面,503页面对用户进行提示,然后自动刷新,这个参数可以根据自己的情况进行更改,这样不管攻击者是多个ip还是单个ip攻击都可以防御到.


如果在nginx日志中能找到攻击者特有的代码,这样就更容易防御,
比如User-agent。下面的是某一次CC攻击时的User-agent
Mozilla/4.0 (compatible; MSIE 5.01; 
Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate
几乎没有正常的浏览器会在User-agent中带上“must-revalidate”这样的关键字。所以我们可以以这个为特征进行过滤,将User-agent中带有“must-revalidate”的请求全部拒绝访问:

if ($http_user_agent ~ must-revalidate) {
return 403;
}


原文地址:http://www.myjishu.com/?p=240