nsfocus那弄来的
DoS 是英文Denial of Service 的缩写,从字面上看一目了然?D?D无法提供服务、拒绝服务,DDoS就是分布式(Distributed)的DoS攻击。DDoS与DoS的主要区别在于所谓的"分布式",意味着攻击者控制了一定数量的僵尸主机(zombies)所发起的攻击。
随着Internet应用以及网络带宽的高速增长, DoS/DDoS攻击发生的频度越来越高。出于商业竞争、打击报复和网络敲诈等各种目的,几乎是任何掌握一定带宽资源的人,只要从网络上下载攻击程序就可以发起DoS/DDoS攻击。由于实施容易、追查困难,同时由于法律规范不够健全,DoS/DDoS攻击已经成为网络管理员以及运营维护人员的头号大敌。
人们最常见的是利用TCP/IP协议设计缺陷发起的攻击,其中最为著名的攻击手段例如SYN Flood攻击相信很多人已经耳熟能详了。由于几乎所有的网络应用服务都是基于TCP协议或者UDP协议,因此攻击的技术手段也可以按照TCP和UDP来描述。
下面将讲述目前常见的攻击方式,在描述攻击方法的时候同时分析防护及其局限性。
常见的攻击方法分析
1. SYN Flood攻击。这是最早出现,也是最有效、最常见的攻击方式。
首先来看一下正常情况下一个TCP连接的建立过程:客户端向服务器发送SYN报文à服务器回应SYN/ACK报文à客户端回应ACK报文,至此连接才算建立。这个过程就是所谓的"三次握手"。在服务器收到SYN报文并回应SYN/ACK报文之后,会启动一个时钟等待第3次握手的ACK报文到达,并将此连接放入一个"半开连接"列表中。如果这个时钟超时(一般来说这个时钟是分钟的数量级),也就是说第3次握手的ACK报文无法到达服务器,那么服务器会重试发送SYN/ACK报文给客户端(重试的次数在3~5次,各种主机操作系统不同)。
恶意的攻击者利用攻击程序模拟这种情况的发生:伪造源IP地址向服务器发起相当数量的连接请求。由于是伪造源IP,服务器回应的SYN/ACK报文可能无法达到该IP地址对应的主机。经过短暂的时间,服务器上就将出现大量的半开连接。如果攻击程序发包速率相对较小的话,服务器的半开连接队列将被充满而无法接受新的SYN请求,这时候的表现就是正常客户端访问服务器会被立即中断,但此时服务器的负载并不很高。如果攻击程序发包速率很高的话,服务器上会迅速积累大量的SYN_RECV状态,系统负载很高,甚至鼠标键盘无法响应,此时从客户端访问服务器会有长时间的等待。因此,当netstat ?Can发现服务器上有大量的SYN_RECV状态的时候就可以判定遭受SYN Flood攻击了。
早期攻击工具(例如synkiller、 xdos和hgod等)通常是发送64字节的TCP SYN报文,而主机操作系统在发起TCP连接请求时发送SYN 报文是大于64字节的。因此,可以在关键节点上设置策略过滤64字节的TCP SYN报文(某些宣传具有防护SYN Flood攻击的产品就是这么做的)。随着工具的改进,发出的TCP SYN报文完全模拟常见的通用操作系统,并且IP头和TCP头的字段完全随机,这时就无法在设备上根据特定的规则来过滤攻击报文。
对于部属在网络前端的状态检测防火墙,SYN Flood攻击几乎是致命的。通常攻击者的目标只是一个服务器,可是当防火墙上开始累积大量SYN_RECV状态的Session直至防火墙 Session被完全充满时,所有到达其他未被攻击的服务器的连接请求也无法通过,最终整个网络瘫痪。
为了避免SYN Flood攻击的影响,一个想法是验证发起SYN请求的源IP地址是否真实。部署在服务器前端的防火墙接收到SYN报文的时候,主动回应SYN/ACK。如果是正常的连接请求客户端就会回应ACK报文到达防火墙上,经过验证之后,防火墙再模拟客户端向服务器发起SYN请求,如图1所示。这种做法将3次握手演变成了6次握手过程,这样伪造源IP的连接请求就无法到达服务器上,从而服务器不会受到任何的影响。目前,很多操作系统/防火墙已经实现了类似的算法,例如著名的Linux SYN Cookie。
显然,SYN Cookie可以在理论上解决伪造源IP的SYN Flood攻击。但是,这个算法在实际环境中有很多问题。假设攻击流量在50Mbps,如果完全做SYN Cookie的话就意味着要回应50Mbps左右的流量。这样做首先防火墙可能不堪重负最终无法响应,其次防火墙前端的网络设备将充斥着大量无用的垃圾流量,假设这个网络的正常流量本身在50Mbps 左右,再加上防火墙主动回应的50M流量,带宽基本充满,前端的网络设备将开始出现随机丢包,攻击者的目的也就达到了。在某些情况下,由于防火墙前端的网络设备要转发大量的数据包,如果配置不当甚至可能由于负载很高而无法正常工作。在实际情况中,我们发现有些交换机在大流量DoS攻击的时候无法响应,或者进入了共享模式(即将接收到的数据包往所有的交换机端口广播)。
改进的算法是有选择的进行主动回应。在这里引入了网络时代的"2/8原则",即 80%的人通常只会集中访问20%的服务器。部署在服务器前端的设备可以学习哪些客户端IP建立连接的成功率是比较高的,在攻击发生的时候尽可能优先保证这些客户端IP能和服务器正常建立连接。这样就将攻击带来的影响降到最低点。同时,还可以辅助以其他的手段来判断是否主动回应。例如,在服务器看来一个客户端的IP包的TTL值是比较固定的(除非路由发生了大的改变),而攻击程序很难正确计算TTL值,因此在攻击发生的当时可以通过判断TTL值来计算是否主动回应。
SYN Flood攻击即使到今天仍然是DoS/DDoS攻击的主角,并且越来越多地与其他攻击方式混合在一起使用,使得抗拒绝服务攻击的任务更加复杂。
2. ACK Flood攻击。在TCP连接建立之后,所有的数据传输TCP报文都是带有ACK标志位的,主机在接收到一个带有ACK标志位的数据包的时候,需要检查该数据包所表示的连接四元组是否存在,如果存在则检查该数据包所表示的状态是否合法,然后再向应用层传递该数据包。如果在检查中发现该数据包不合法,例如该数据包所指向的目的端口在本机并未开放,则主机操作系统协议栈会回应RST包告诉对方此端口不存在。通常状态检测防火墙所做的事情与此类似,只不过防火墙只拦截非法的数据包,而不主动回应。
对比主机以及防火墙在接收到ACK报文和SYN报文时所做动作的复杂程度,显然ACK报文带来的负载要小得多。所以在实际环境中,只有当攻击程序每秒钟发送ACK报文的速率达到一定的程度,才能使主机和防火墙的负载有大的变化。当发包速率很大的时候,主机操作系统将耗费大量的精力接收报文、判断状态,同时要主动回应RST报文,正常的数据包就可能无法得到及时的处理。这时候客户端(以IE为例)的表现就是访问页面反应很慢,丢包率较高。但是状态检测的防火墙通过判断ACK报文的状态是否合法,借助其强大的硬件能力可以较为有效的过滤攻击报文。当然如果攻击流量非常大(特别是千兆线路上,我们曾经观察到200~300Mbps左右的ACK Flood),由于需要维护很大的连接状态表同时要检查数量巨大的ACK报文的状态,防火墙也会不堪重负导致全网瘫痪。
目前ACK Flood并没有成为攻击的主流,而通常是与其他攻击方式组合在一起使用。回顾前面描述的SYN Cookie算法,其核心思想是主动回应SYN/ACK包,然后校验第3次握手的ACK报文是否合法,目前大多数实现中校验ACK报文的合法性都涉及到较为复杂的算法。当SYN Flood与ACK Flood一起发生的时候, 主机和防火墙将耗费大量的精力来计算ACK报文是否合法以致不堪重负。
从以上的描述可以看到ACK Flood具有"单包攻击"的特点。但我们仍然可以从TCP/IP协议的特性以及数据传输特性中得到一定的统计规律。在现实世界中,正常数据传输的两个方向(客户端à服务器,服务器à客户端)上的报文数量基本上是均衡的,同时数据报文的内容是较为随机的。因此,当数据传输两个方向上的报文数量发生倾斜的时候,基本上可以判定发生了攻击。并且在大多数情况下,由于为了追求发包的速率,攻击报文的内容是较为固定的。因此,防护设备可以通过学习攻击报文的特征,当某个特征在一段时间的采样内大量重复出现,那么基本上可以判定符合此特征的数据报文为攻击报文。当然,统计的方法不可避免会带来误判,因此将统计方法与连接状态检测结合起来是比较合理的做法。
3. Connection Flood。称为连接耗尽攻击,顾名思义就是将服务器上可用的连接数占满直至无法正常响应。与前面讲述的攻击方式不同的是,连接耗尽攻击使用真实的IP地址与服务器建立连接。攻击者操控了大量的傀儡主机或者使用代理服务器来发起大规模的连接。当连接数达到一定规模,超过了服务器的能力时,正常的连接请求将无法建立。通过不断地与服务器建立大量的连接,最终服务器的内存资源将被耗尽。应该说,连接耗尽攻击比以上的攻击更为复杂,手段和变化更为丰富多彩。判断连接耗尽攻击需要对netstat ?Can显示的连接状态进行分析,可能出现的情况有:
1) 若干个源IP与服务器建立了大量的连接;
2) 大量的连接处于TIME_WAIT, FIN_WAIT状态;
除了建立大量的连接之外,攻击程序在与服务器建立连接之后可能始终不放弃连接,并间隔地向服务器发送垃圾数据包使得连接状态始终保持,拖延服务器释放连接的时间,这种连接也可以称之为"空连接"。
显然,如果攻击者掌握的傀儡主机数量不够的话,就需要每个傀儡主机与服务器建立相当数量的连接才能使攻击效果比较明显。防火墙就可以通过限制每个源IP的连接数来将攻击的影响降到最低点。但是当傀儡主机数量足够多的时候,几乎是每个源IP只与服务器同时保持2到3个连接,如果限制源IP的连接数,就有可能使得正常的服务无法正常访问。大多数的网站内容丰富多彩,打开一个页面就可能需要向服务器发起数十个连接,限制连接就有可能使得页面上的内容无法正常打开。
连接耗尽攻击对防火墙带来的冲击也是很明显的,由于连接数量巨大,占用了大量的连接表项,防火墙的负载和内存使用率将会明显上升。如果在防火墙前面部署具有防护连接耗尽攻击能力的设备,在傀儡主机向服务器发起连接请求的时候,防护设备是无法简单的根据SYN包来判断是否是正常连接的,从而只能让连接通过,只有当连接建立之后才有可能判断是否恶意的连接,但此时已经对服务器和防火墙造成了一定的影响。所以防护设备在连接建立之后,如果一断时间内没有有效的数据包从客户端到达,则可以判定此连接为"空连接",同时应当尽快地主动清除已经建立的连接,使得防火墙和服务器释放连接表项。
4.Get Flood攻击,也就是 "刷Script脚本"攻击。以上SYN Flood、ACK Flood、Connection Flood都可以说是针对TCP层的攻击,而Get Flood攻击则是针对7层应用协议发起的攻击。这种攻击主要针对使用ASP,JSP,PHP,CGI脚本程序动态生成页面的系统。通常动态页面的生成涉及到后台数据库的操作,如果攻击程序与服务器建立连接之后,不断地发送Get请求,使得脚本程序提交查询、列表等耗费大量数据库资源的调用,数据库服务器的负载将急剧上升使得正常的数据库操作也无法响应,这样动态页面的生成就很缓慢甚至最终操作失败。
在使用这种攻击方式的时候,攻击者通常使用匿名的代理服务器发起请求。显然,代理服务器数量越多的话效果越明显,同时代理服务器的同步性越好的话攻击效果越显著。由于很多网站提供代理列表,因此攻击者使用上千个甚至数千个代理服务器发起攻击并不是一件困难的事情。发送一个GET/POST请求,对客户端的CPU耗费和带宽的占用微乎其微,因此当发生攻击的时候在防护设备和防火墙上并不能观察到包速率和流量的明显变化。
Get Flood攻击如果针对静态页面的话,则效果会大打折扣。因此,对付Get Flood攻击可以从优化页面构造上着手,尽可能避免过多地使用动态页面;在请求动态页面之前要求通过认证,这样攻击程序就无法直接发送页面请求。
虽然表面上看Get Flood攻击所发出的页面请求与正常的访问页面没有区别,但仔细思考一下如果防护设备在收到一个页面请求的时候主动回应一个带Cookie的内容,防护设备回应的内容到达正常客户端的时候会使得客户端作出相应的动作,而对于使用工具发起页面请求的客户端将不会有任何的响应。假设工具对回应的内容进行分析,那么工具发送页面请求的速率将大大降低,使得攻击效果不明显。

前面讲述的主要是tcp类型的攻击,由于TCP协议具有连接状态,在 TCP类型的攻击面前或许人们可以设计一些根据连接特性的算法来较为有效对攻击进行防护。但在针对UDP服务的攻击面前,服务器显得更加脆弱,可以利用的协议特性更少,防护的难度更高。UDP协议是无状态的,而基于UDP应用的协议五花八门,很多属于商业公司开发的私有协议,人们无法知道其协议的格式,从而无法设计非常有效的通用防护算法。但可以分析一些常用的、公开的UDP应用协议,提出有针对性的防护算法。
首先仍然可以得到应用的统计特性,这在讲述ACK Flood的时候曾经提到:正常数据传输的两个方向(客户端à服务器,服务器à客户端)上的报文数量基本上是均衡的,同时数据报文的内容是较为随机的。当网络上两个方向的报文数量发生倾斜并且报文内容较为固定的时候,一定是发生了攻击行为。防护设备可以通过模式识别算法抽取出报文中的特征,并将符合此特征的报文认为是攻击报文而丢弃。通过模式识别算法学习特征的过程比较复杂,目前并没有防火墙能够做到这一点,只有少数的专业防护设备实现了这样的算法。
但是这样的通用防护模型在防护某些特定的应用时候可能效果并不明显,同时如果攻击程序随机生成UDP包负载,则将无法学习到特征。或许针对一些特定的应用来定制防护算法是目前唯一可行的方法。
从人们最经常使用的DNS服务来分析可以做些什么事情。DNS服务器对人们正常使用Internet 有着极为重要的作用,一旦DNS服务器遭受攻击,人们使用网络将受到严重的影响。
UDP DNS Query Flood攻击采用的方法是向被攻击的服务器发送大量的域名解析请求,通常请求解析的域名是随机生成或者是网络世界上根本不存在的域名,被攻击的DNS 服务器在接收到域名解析请求的时候首先会在服务器上查找是否有对应的缓存,如果查找不到并且该域名无法直接由服务器解析的时候,DNS 服务器会向其上层DNS服务器递归查询域名信息。域名解析的过程给服务器带来了很大的负载,每秒钟域名解析请求超过一定的数量就会造成DNS服务器解析域名超时。
根据微软的统计数据,一台DNS服务器所能承受的动态域名查询的上限是每秒钟9000个请求。而我们知道,在一台P3的PC机上可以轻易地构造出每秒钟几万个域名解析请求,足以使一台硬件配置极高的DNS服务器瘫痪,由此可见DNS 服务器的脆弱性。目前最常用的DNS服务器软件是Bind。
通常攻击者采用的手段包括:
1) 利用发包程序向DNS服务器发送不带任何负载的NULL数据包。由于数据包本身不符合协议规定,服务器在收到报文的时候将直接丢弃。因此这种攻击方式除非攻击流量比较大,否则不会有明显的效果。
2) 利用程序构造DNS解析请求固定的域名,由于DNS服务器在解析请求的时候会在系统cache存放上一次解析的结果,这种攻击方式也需要较大的流量。
3) 向DNS服务器发起解析请求随机的、不存在的域名;这样DNS服务器就需要进行频繁的字符串匹配,由于在本地无法查到对应的结果,服务器必须使用递归查询向上层域名服务器提交解析请求,引起连锁反应。
目前尚没有防火墙能对DNS服务器的攻击进行防护,只有少数的专业防护设备可以做到。
防护仍然可以从统计学的角度出发。作为安装在DNS服务器前面的防护设备,在平时运行时可以统计哪些域名是经常被解析请求的,哪些域名是从来都没有被解析请求过的,学习域名解析的结果,对那些经常无法解析的域名引入类似的信誉机制。在攻击发生的时候,防护设备利用内建的高速cache根据平时学习到的域名解析的结果主动响应解析请求,这样减轻DNS服务器的负载。同时,根据统计的结果,过滤部分明显非法的解析请求(例如某个从来未被解析过的域名),对突然发起大量频度较低的域名解析请求的源IP地址进行带宽限制。通过采取这些方法,可以将攻击带来的影响降到最低点。