分类: LINUX
2009-01-09 16:46:31
为了防范SYN Flood攻击,等人提出了SYN Cookie机制,主要思想就是收到SYN报文时,在服务器端不保存任何信息,构造特殊的序列号后回复SYN-ACK报文,减少这种拒绝服务攻击对服务器的压力。收到ACK报文后,通过序列号解析判断其是否合法,决定连接是否建立。关于SYN Cookie的详细资料,请参考wikipedia的说明[1]。
计算Cookie值做为回复SYN-ACK的序列号,在处理SYN报文的tcp_v4_conn_request ()中调用,入口为cookie_v4_init_sequence ();
检验Cookie值是否合法,在tcp_v4_hnd_req ()中调用cookie_v4_check()->cookie_check()检查cookie值是否合法;
return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq + (count << COOKIEBITS) + ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) & COOKIEMASK)); |
以源/目的地址和端口、0以及syncookie_secret[0]为输入的hash值
sseq序列号
高八位为当前分钟数,即jiffies/(60*HZ),低24位为hash值+data后的24位,其中,hash值以源/目的地址和端口、当前分钟数和syncookie_secret[1]为输入。
如图1所示,三部分加和中,第一和三部分所用的hash算法相同。同时,显然可以得出,收到ACK报文时,第一个hash值是不变的,sseq是很容易求出的(ntohl(ack_th->ack_seq) - 1)即可)。而count值可以取出,但不是现在的系统分钟数。设发送SYNACK时时间为jiffies,系统分钟数为count,收到ACK时时间为jiffies’,系统分钟数为count’,即
count = 向下取整(jiffies/(60*HZ)), count' = 向下取整(jiffies'/(60*HZ))
那么,分钟数的差值diff=count'-count
//首先,去掉cookie三部分加和中的前两部分
cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; //接下来,取出cookie的高八位,即发送SYN-ACK时编码进去的当时的系统分钟数,用
//当前分钟数去减,即为前后时间的差值,精确到分钟。
diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS); //如果diff值过大,则认定cookie非法
if (diff >= maxdiff)
return (__u32)-1;
|
return (cookie - cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) & COOKIEMASK; /* Leaving the data behind */ |
return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; |
Linux 2.6.26中的syncookie机制实现了对MSS外的一些TCP选项的支持,但并未像MSS一样编码进cookie,即序列号,而是在支持timestamp的情况下,放入了timestamp的低9位。
[1]
[2]