Chinaunix首页 | 论坛 | 博客
  • 博客访问: 345747
  • 博文数量: 306
  • 博客积分: 3975
  • 博客等级: 中校
  • 技术积分: 3265
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-27 13:14
文章分类

全部博文(306)

文章存档

2017年(1)

2016年(3)

2015年(11)

2014年(15)

2013年(178)

2012年(41)

2011年(38)

2010年(9)

2009年(9)

2008年(1)

分类: LINUX

2011-05-26 12:30:59

在目前以IPv4为支撑的网络协议上搭建的网络环境中,SYNFlood是一种非常 危险而常见的DoS攻击方式。到目前为止,能够有效防范SYNFlood攻击的手段并不多,而SYNCookie就是其中最著名的一种。 /SYNCookie原理及其在Linux内核中的实现//


概述 在目前以IPv4为支撑的网络协议上搭建的网络环境中,SYN Flood是一种非常危险而常见的DoS攻击方式。到目前为止,能够有效防范SYN Flood攻击的手段并不多,而SYN Cookie就是其中最著名的一种。SYN Cookie原理由D. J. Bernstain和 Eric Schenk发明。在很多操作系统上都有各种各样的实现。其中包括Linux。本文就分别介绍一下SYN Flood攻击和SYN Cookie的原理,更重要的是介绍Linux内核中实现SYN Cookie的方式。最后,本文给出一种增强目前Linux中SYN Cookie功能的想法。 一 SYN Flood攻击 SYN Flood攻击是一种典型的拒绝服务型(Denial of Service)攻击。所谓拒绝服务型攻击就是通过进行攻击,使受害主机或网络不能够良好的提供服务,从而间接达到攻击的目的。 SYN Flood攻击利用的是IPv4中TCP协议的三次握手(Three-Way Handshake)过程进行的攻击。大家知道协议规定,如果一端想向另一端发起TCP连接,它需要首先发送TCP SYN 包到对方,对方收到后发送一个TCP SYN+ACK包回来,发起方再发送TCP ACK包回去,这样三次握手就结束了。我们把TCP连接的发起方叫作"TCP客户机(TCP Client)",TCP连接的接收方叫作"TCP服务器(TCP Server)"。值得注意的是在TCP服务器收到TCP SYN request包时,在发送TCP SYN+ACK包回TCP客户机前,TCP服务器要先分配好一个数据区专门服务于这个即将形成的TCP连接。一般把收到SYN包而还未收到ACK包时的连 接状态成为半开连接(Half-open Connection)。 在最常见的SYN Flood攻击中,攻击者在短内 发送大量的TCP SYN包给受害者,这时攻击者是TCP客户机,受害者是TCP服务器。根据上面的描述,受害者会为每个TCP SYN包分配一个特定的数据区,只要这些SYN包具有不同的源地址(这一点对于攻击者来说是很容易伪造的)。这将给TCP服务器系统造成很大的系统负担, 最终导致系统不能正常工作。 二 SYN Cookie原理 SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。 从上面的介绍可以看出,SYN Cookie的原理比较简单。到实际的应用中,它有多种不同的实现方式。 三 Linux内核中的SYN Cookie实现 Linux内核中对SYN Flood有很好的防护。以下的讨论都是针对Linux2.4.20内核进行的。在每一个sock都有一个tcp_opt即这个sock的TCP选项。在 tcp_opt其中有一个tcp_listen_opt,这里存储的是这个sock在LISTEN状态下时保存的一些选项,其中有一个 open_request结构的数组,数组长度为TCP_SYNQ_HSIZE(512)。所有这些表示在一个sock,最多可以同时开启512个半开连 接(这是在不考虑其他条 件时的最大值,实际情况中不会达到这个值)。当这个数组满了时,新来的open_request会顶替掉一个老的open_request。这样,即使没 有启动SYN Cookie,也能够在SYN Flood发生时保护系统免于瘫痪。问题是这种处理方法会在面对SYN Flood攻击时丢掉正常的TCP连接请求。SYN Cookie的作用恰恰是保证在面对SYN Flood攻击时,一方面能够拒绝非法的TCP连接请求,一方面正常连接可以被建立。 Linux内核对TCP流程的处理主要在tcp_ipv4.c文件中的函数实现。具体的,当处理TCP SYN包时,系统进入tcp_v4_conn_request函数。其中调用cookie_v4_init_sequence生成一个 ISN(Initial Sequence Number)。Linux内核把它作为SYN Cookie流程中的cookie。 cookie_v4_init_sequence函数在syncookies.c文件中定义,它又调用random.c文件中的 secure_tcp_syn_cookie函数。cookie的实质计算是在这个函数中进行的。 在random.c文件里给出secure_tcp_syn_cookie函数的定义之前给出两个宏,它们的定义分别为 #define COOKIETS 24 #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) COOKIEBITS表示cookie的比特长度;COOKIEMASK是一个COOKIEBITS长的比特串,所有比特都是1。 还有两个比特串,被定义成一个__u32的二维数组 static __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE]; 其中所有的比特值在secure_tcp_syn_cookie中被随机的赋予,用get_random_bytes函数。它们成为制作cookie的密 钥。这两个被随机产生的比特串是整个SYN Cookie实现方案的关键。另外还有一个开关syncookie_init控制对这两个密钥的改动。 还需要指出,在文件syncookies.c中定义有一个__u16组成的表static __u16 const msstab[],这个表中保存的是一些可能的MSS(Maximum Segment Size)值。 secure_tcp_syn_cookie函数的返回值就是计算得到的ISN值,即cookie。为了描述方便,我们给出如下定义: tmp1 := saddr + daddr + ((sport<<16)+dport) + syncookie_secret[0] tmp2 := saddr + daddr + ((sport<<16)+dport) + syncookie_secret[1] tmp11 := HASH_TRANSFORM(tmp1[16], tmp1) tmp22 := HASH_TRANSFORM(tmp2[16], tmp2) A := tmp11[0][17] B := tmp22[1][17] sseq := ntohl(skb->h.th->seq) 这里的skb是携带TCP SYN的那个skb count1 := jiffies/(HZ*60) 当前时间的分钟值 data1 := msstab 从前往后最后一个小于skb中携带的MSS值的值的索引(值得注意的是两个密钥在第一次被初始化后,就不会再有改动,直到系统重新启动。因此可以认为它是 一个常值。) 有了上面的定义我们可以得到cookie等于 isn := A+sseq + (count1<<<模式的防火墙,它不仅要保护本机免受各种网络攻击,还要保护它后面的所有对外有开放TCP端口的主机免受这些攻击。比如一个局域网中有个服务器开放了FTP服务给外界,这个服务器主机就有可能遭受到来自上 的SYN Flood攻击。而这时的防火墙会将所有的攻击SYN包转发给受害主机。 一种杜绝这种情况的方法是SYN Cookie Firewall。它是SYN Cookie的一种扩展形式。总的来说,它是利用原来SYN Cookie的原理在内网和外网之间实现TCP三次握手过程的代理(proxy)的机制。 为了方便描述,我们假定一个外在的TCP客户机C希望通过防火墙F连接到局域网中的一个TCP服务器S。 在防火墙收到来自外网的SYN包时,它并不直接进行转发,而是缓存在本地,再按照原来SYN Cookie的机制制作好一个针对这个SYN包的SYN+ACK包,注意,这个SYN+ACK包中的ack顺序号为特制的cookie值c,更重要的是这 个包的的源地址被伪造成了S的地址(为了描述方便,我们这里暂时不考虑NAT等其他因素)。这样C会接收到这个SYN+ACK包,并认为是从S反馈回来 的。于是C再响应一个ACK包,并认为与S的TCP连接已经建立起来。这时防火墙F收到这个ACK包,按照前面的描述的SYN Cookie原理来检查这个ACK中的ack顺序号。如果认为合法,F将本地缓存的来自C的SYN包发送给S,这时S会响应一个SYN+ACK包到C,其 中也携带一个seq号, 我们设为c`。当然这个包不会到达C,而是由防火墙F截取,F根据这个包中的序列号等信息,造一个ACK包响应到S。这时的情况是:C认为自己已经与S建 立了TCP连接;S认为自己与C建立了TCP连接。以后的TCP数据内容可以直接穿过防火墙F,在S和C之间交互。 上图是SYN Cookie Firewall的工作原理,它相当于在TCP Server与TCP Client之间实现了对三次握手协议的代理。第一次"三次握手"在TCP Client与防火墙之间进行,第二次"三次握手"在防火墙与TCP Server之间。在第一次"三次握手"时使用前面介绍的SYN Cookie流程。有一个问题在进行两次"三次握手"时出现了:如图所示,进行第一次"三次握手"后,TCP Client认为后续数据包的seq值从c+1开始,而进行第二次"三次握手"后,TCP Server认为后续发来的数据包的seq值从c`+1开始, c是cookie,c`是TCP Server随机产生的。c和c`几乎不可能相等,也就是说在完成上面的两个"三次握手"后,如果不进行其他操作,后续从TCP Client到TCP Server的数据包都将被认为顺序号不对而被丢掉。一种补救方法就是在防火墙本地保存一个值δ δ = |c - c`| 利用这个差值,在每个数据包经过防火墙时,将其seq值修改一下,这样,后续的数据流量可以完美地在TCP Server和TCP Client之间传输了。 总结 现在普遍使用的IPv4协议带有很多安全上的问题,其中面对SYN Flood攻击的软弱就是一点。在不改变TCP三次握手流程的情况下,TCP Server几乎不可能有效的防范SYN Flood的攻击。要保证完全防范SYN Flood,必须修改三次握手协议。SYN Cookie是一种很有效的方法。它的思想比较简单,主要是如何具体的实现,Linux系统也提供了一种实现。

阅读(1425) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~