一、 CC攻击的原理:
CC攻击的原理就是攻击者控制某些主机不停地发大量数据包给对方服务器造成服务器资源耗尽,一直到宕机崩溃。CC主要是用来消耗服务器资源的,每个人都有这样的体验:当一个网页访问的人数特别多的时候,打开网页就慢了,CC就是模拟多个用户(多少线程就是多少用户)不停地进行访问那些需要大量数据操作(就是需要大量CPU时间)的页面,造成服务器资源的浪费,CPU长时间处于100%,永远都有处理不完的连接直至就网络拥塞,正常的访问被中止。
二、CC攻击的种类:
CC攻击的种类有三种,直接攻击,代理攻击,僵尸网络攻击,直接攻击主要针对有重要缺陷的 WEB 应用程序,一般说来是程序写的有问题的时候才会出现这种情况,比较少见。僵尸网络攻击有点类似于 DDOS 攻击了,从 WEB 应用程序层面上已经无法防御,所以代理攻击是CC 攻击者一般会操作一批代理服务器,比方说 100 个代理,然后每个代理同时发出 10 个请求,这样 WEB 服务器同时收到 1000 个并发请求的,并且在发出请求后,立刻断掉与代理的连接,避免代理返回的数据将本身的带宽堵死,而不能发动再次请求,这时 WEB 服务器会将响应这些请求的进程进行队列,数据库服务器也同样如此,这样一来,正常请求将会被排在很后被处理,就象本来你去食堂吃饭时,一般只有不到十个人在排队,今天前面却插了一千个人,那么轮到你的机会就很小很小了,这时就出现页面打开极其缓慢或者白屏。
三、CC攻击与DDOS的区别
1) 什么是DDoS攻击?
DDoS攻击就是分布式的拒绝服务攻击,DDoS攻击手段是在传统的DoS攻击基础之上产生的一类攻击方式。单一的DoS攻击一般是采用一对一方式的,随着计算机与网络技术的发展,DoS攻击的困难程度加大了。于是就产生了DDoS攻击,它的原理就很简单:计算机与网络的处理能力加大了10倍,用一台攻击机来攻击不再能起作用,那么DDoS就是利用更多的傀儡机来发起进攻,以比从前更大的规模来进攻受害者。常用的DDoS软件有:LOIC。
在这里补充两点:第一就是DDOS攻击不仅能攻击计算机,还能攻击路由器,因为路由器是一台特殊类型的计算机;第二是网速决定攻击的好和快,比如说,如果你一个被限制网速的环境下,它们的攻击效果不是很明显,但是快的网速相比之下更加具有攻击效果。
2)什么是CC攻击?
3)两者区别
DDoS是针对IP的攻击,而CC攻击的是服务器资源。
'防止CC攻击
Dim CC_Info(4),strInfo,strTemp
If Session("CC_Info") = "" Then
CC_Info(0) = "cclog.txt" '日志文件名
CC_Info(1) = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
CC_Info(2) = Request.ServerVariables("REMOTE_ADDR")
CC_Info(3) = 4 'N秒内禁止刷新当前页面
CC_Info(4) = "badip.txt" 'IP黑名单文件名
Session("CC_Info") = CC_Info(0) &"|"& CC_Info(1) &"|"& CC_Info(2) &"|"& CC_Info(3) &"|"& CC_Info(4)
Else
strInfo = Split(Session("CC_Info"),"|")
CC_Info(0) = strInfo(0)
CC_Info(1) = strInfo(1)
CC_Info(2) = strInfo(2)
CC_Info(3) = strInfo(3)
CC_Info(4) = strInfo(4)
End If
Const chkRefresh = 1 '0关闭防刷新
Const chkProxy = 1 '0关闭代理验证
Const chkBadIP = 1 '0关闭IP黑名单
If Session("BadIP") = "" Then
strInfo = ReadFile(CC_Info(4))
If strInfo = "" Then strInfo = "williamlong.info"
Session("BadIP") = strInfo
Else
strInfo = Session("BadIP")
End If
'/*第一层判断,N秒内禁止刷新*/
If chkRefresh = 1 Then
If Session("RefreshTime")="" Then
Session("RefreshTime")=Now()
Else
If DateDiff("s", Session("RefreshTime"), Now()) < CInt(CC_Info(3)) Then
SaveLog CC_Info(0),CC_Info(1) & "["& CC_Info(2) & "]" & Now() &vbCrLf
Response.Write("系统繁忙,请稍候再试!错误代码001")
Response.End()
Else
Session("RefreshTime")=Now()
End If
End If
End If
'/*第二层判断,代理禁止查看*/
If chkProxy = 1 Then
If CC_Info(1) <> "" Then
If InStr(strInfo,CC_Info(1)) = 0 Then
strTemp = CC_Info(1) & vbCrLf
If InStr(strInfo,CC_Info(2)) = 0 Then
strTemp = strTemp & "[" & CC_Info(2) & "]" & vbCrLf
End If
SaveLog CC_Info(4),strTemp
strInfo = strInfo & strTemp
Session("BadIP") = strInfo
End If
'记录CC攻击日志
SaveLog CC_Info(0),CC_Info(1) & "["& CC_Info(2) & "]" & Now() &vbCrLf
Response.Write("系统繁忙,请稍候再试!错误代码002")
Response.End()
End If
End If
'/*第三层判断,IP黑名单禁止查看*/
If chkBadIP = 1 Then
If InStr(strInfo,CC_Info(2))>0 Then
Response.Write("系统繁忙,请稍候再试!错误代码003")
Response.End()
End If
End If
'ForReading=1,ForWriting=2,ForAppending=8
Function SaveLog(filename, filecontent)
On Error Resume Next
Dim fso, thisfile
filename = Server.MapPath(filename)
Set fso = CreateObject("Scripting.FileSystemObject")
If Err <> 0 Then
Response.Write("写入文件"&filename&"失败,可能您的系统不支持FSO!")
Response.End()
End If
Set thisfile = fso.OpenTextFile(filename, 8, True)
thisfile.write (filecontent)
thisfile.Close
Set fso = Nothing
End Function
Function ReadFile(filename)
On Error Resume Next
Dim fso, thisfile
Set fso = CreateObject("Scripting.FileSystemObject")
If Err <> 0 Then
Response.Write("读取文件"&filename&"失败,可能您的系统不支持FSO!")
Response.End()
End If
Set thisfile = fso.OpenTextFile(Server.MapPath(filename), 1, True)
ReadFile = thisfile.ReadAll
thisfile.Close
Set thisfile = Nothing
Set fso = Nothing
End Function
Apache服务器现在使用较多的有三种简单防护方式。
mod_reqtimeout:Apache2.2.15后,该模块已经被默认包含,用户可配置从一个客户端接收HTTP头部和HTTPbody的超时时间和最小速率。如果一个客户端不能在配置时间内发送完头部或body数据,服务器会返回一个408REQUEST TIME OUT错误。配置文件如下:
< IfModule mod_reqtimeout.c >
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
< /IfModule >
mod_qos:Apache的一个服务质量控制模块,用户可配置各种不同粒度的HTTP请求阈值,配置文件如下:
复制代码
< IfModule mod_qos.c >
/# handle connections from up to 100000 different IPs
QS_ClientEntries 100000
/# allow only 50 connections per IP
QS_SrvMaxConnPerIP 50
/# limit maximum number of active TCP connections limited to 256
MaxClients 256
/# disables keep-alive when 180 (70%) TCP connections are occupied
QS_SrvMaxConnClose 180
/# minimum request/response speed (deny slow clients blocking the server, keeping connections open without requesting anything
QS_SrvMinDataRate 150 1200
< /IfModule >
mod_security:一个开源的WAF模块,有专门针对慢速攻击防护的规则,配置如下:
SecRule RESPONSE_STATUS “@streq 408” “phase:5,t:none,nolog,pass, setvar:ip.slow_dos_counter=+1, expirevar:ip.slow_dos_counter=60, id:’1234123456′”
SecRule IP:SLOW_DOS_COUNTER “@gt 5” “phase:1,t:none,log,drop,
msg:’Client Connection Dropped due to high number of slow DoS alerts’, id:’1234123457′”
传统的流量清洗设备针对CC攻击,主要通过阈值的方式来进行防护,某一个客户在一定的周期内,请求访问量过大,超过了阈值,清洗设备通过返回验证码或者JS代码的方式。这种防护方式的依据是,攻击者们使用肉鸡上的DDoS工具模拟大量http request,这种工具一般不会解析服务端返回数据,更不会解析JS之类的代码。因此当清洗设备截获到HTTP请求时,返回一段特殊JavaScript代码,正常用户的浏览器会处理并正常跳转不影响使用,而攻击程序会攻击到空处。
而对于慢速攻击来说,通过返回验证码或者JS代码的方式依然能达到部分效果。但是根据慢速攻击的特征,可以辅助以下几种防护方式:1、周期内统计报文数量。一个TCP连接,HTTP请求的报文中,报文过多或者报文过少都是有问题的,如果一个周期内报文数量非常少,那么它就可能是慢速攻击;如果一个周期内报文数量非常多,那么它就可能是一个CC攻击。2、限制HTTP请求头的最大许可时间。超过最大许可时间,如果数据还没有传输完成,那么它就有可能是一个慢速攻击。
简单的Nginx防CC方式
实验
Nginx配置
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
#限制每ip每秒不超过20个请求,漏桶数burst为5
#brust的意思就是,如果第1秒、2,3,4秒请求为19个,
#第5秒的请求为25个是被允许的。
#但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
#nodelay,如果不设置该选项,严格使用平均速率限制请求数,
#第1秒25个请求时,5个请求放到第2秒执行,
#设置nodelay,25个请求将在第1秒执行。
limit_req zone=one burst=1 nodelay;
}
}
上面样本的配置是什么意思呢?
$binary_remote_addr 表示:客户端IP地址
zone 表示漏桶的名字
rate 表示nginx处理请求的速度有多快
burst 表示峰值
nodelay 表示是否延迟处理请求,还是直接503返回给客户端,如果超出rate设置的情况下。
详细的可以参考官方说明文档:Module ngx_http_limit_req_module
模拟请求
这里我们需要Apache Benchmark这个小工具来生成请求
//1个用户持续100s的时间向服务器发送请求
ab -t 100 -c 1 -vvv example.com
Nginx配置样本一
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
limit_req zone=one burst=1 nodelay;
}
}
ab测试结果如下所示:
数据 成功的请求数 失败的请求数 请求时间 每秒成功的请求数
1 100 19438 101.195 0.98
2 100 17651 100.655 0.99
3 97 25735 100.424 0.96
4 101 26791 100.000 1.01
5 98 19051 100.514 0.98
平均 99 21733.2 100.557 0.98
以上失败的请求在Nginx上生成的错误日志如下显示
2015/05/09 12:48:57 [error] 6564#0: *2219 limiting requests, excess: 1.273 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
2015/05/09 12:48:57 [error] 6564#0: *2220 limiting requests, excess: 1.272 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
2015/05/09 12:48:57 [error] 6564#0: *2221 limiting requests, excess: 1.271 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
2015/05/09 12:48:57 [error] 6564#0: *2222 limiting requests, excess: 1.270 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
2015/05/09 12:48:57 [error] 6564#0: *2223 limiting requests, excess: 1.269 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
2015/05/09 12:48:57 [error] 6564#0: *2224 limiting requests, excess: 1.268 by zone "one", client: 10.0.2.2, server: example.com, request: "GET / HTTP/1.0", host: "example.com"
如上ab测试中如果是失败的请求,nginx的limit_req模块会统一返回503给客户端,浏览器上面显示的是这个样子的。
Nginx配置样本二
在配置二里面,我把burst(峰值)提高到了10
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
limit_req zone=one burst=10 nodelay;
}
}
数据 成功的请求数 失败的请求数 请求时间 每秒成功的请求数
1 110 19042 100.144 1.09
2 111 22271 101.714 1.09
3 111 18466 100.504 1.10
4 111 16468 101.285 1.09
5 111 12770 100.596 1.10
平均 110 17803 100.788
1.09
从数据来看,提高了burst值,明显nginx成功的请求数上去了。
Nginx配置样本三
在样本二的基础上,我们把nodelay去除掉
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
limit_req zone=one burst=10;
}
}
数据 成功的请求数 失败的请求数 请求时间 每秒成功的请求数
1 96 0 100.223 1.09
2 98 0 100.238 0.97
3 100 0 100.761 0.99
4 96 0 100.074 0.95
5 97 0 100.021 0.96
平均 97.4 0 100.263 0.97
从这里的数据可以看到将nodelay的参数去掉的话,成功的请求数在100左右而失败的请求数变成0了,为什么呢?
有nodelay参数的时候,nginx正常是及时处理当前的请求的并响应数据给客户端,但是如果超过limit_req_module的限制,那么会统一返回503给客户端。
无nodelay参数的时候,nginx正常是及时处理当前的请求的并响应数据给客户端,但是如果超过limit_req_module的限制,那么会将此此请求缓存「就先这么理解」起来稍后再处理,所以也就不会出现大量的失败请求数了。
存在的问题
虽然用limit_req_module可以一定上的防止CC攻击,但是有误杀概率;国内宽带用户的IP地址已经大量内网化,几百人共享一个IP的可能性是很大的。