linux内核:SYN Cookie在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协议 3次握手(Three-Way Handshake)过程进行攻击大家知道协议规定如果端想向另端发起TCP连接它需要首先发送TCP SYN 包到对方对方收到后发送个TCP SYN+ACK包回来发起方再发送TCP ACK包回去这样 3次握手就结束了我们把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服务器系统造成很大系统负担最终导致系统不能正常工作
2、SYN Cookie原理

  SYN Cookie是对TCP服务器端 3次握手协议作些修改专门用来防范SYN Flood攻击种手段原理是在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时不分配个专门数据区而是根据这个SYN包计算出个cookie值在收到TCP ACK包时TCP服务器在根据那个cookie值检查这个TCP ACK包合法性如果合法再分配专门数据区进行处理未来TCP连接

  从上面介绍可以看出SYN Cookie原理比较简单到实际应用中它有多种区别实现方式

   3、Linux内核中SYN Cookie实现

  Linux内核中对SYN Flood有很好防护以下讨论都是针对Linux2.4.20内核进行在每个sock都有个tcp_opt即这个sockTCP选项在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_cookiecookie实质计算是在这个中进行

  在random.c文件里给出secure_tcp_syn_cookie定义的前给出两个宏它们定义分别为

    # COOKIEBITS 24
    # COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
  COOKIEBITS表示cookie比特长度;COOKIEMASK是个COOKIEBITS长比特串所有比特都是1

  还有两个比特串被定义成个__u32 2维

   __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
其中所有比特值在secure_tcp_syn_cookie中被随机赋予用get_random_s它们成为制作cookie密钥这两个被随机产生比特串是整个SYN Cookie实现方案关键另外还有个开关syncookie_init控制对这两个密钥改动

  还需要指出在文件syncookies.c中定义有个__u16组成 __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 := jfies/(HZ*60) 当前时间分钟值
data1 := msstab

  从前往后最后个小于skb中携带MSS值索引(值得注意是两个密钥在第次被化后就不会再有改动直到系统重新启动因此可以认为它是个常值)

  有了上面定义我们可以得到cookie等于

    isn := A+sseq + (count1<<COOKIEBITS) + (B+data1)&COOKIEMASK

  这个isn被赋予返回TCP SYN+ACK包中作为其中ISN值这就是cookie 产生过程在这个过程中没有在本地为这个连接请求分配任何存储空间

  在TCP服务器收到TCP ACK包时相应要进行SYN Cookie检查这个检查过程在tcp_v4_hnd_req中cookie_v4_check开始cookie_v4_checkcookie_checkcookie_checkcheck_tcp_syn_cookie

  check_tcp_syn_cookie在random.c中定义是和前面介绍

  secure_tcp_syn_cookie对应检查从TCP ACK中提取出ISN值

  在check_tcp_syn_cookie中假定ISN值如下

    isn := A+sseq + (count2<<COOKIEBITS) + (B+data2)&COOKIEMASK

  这里A、B都是根据当前这个skb中地址信息和syncookie_secret算出来;sseq是根据这个skb中seq值算出

  有了上面这些值TCP服务器就可以反算出count2和data2理论上来说只要这个isn是原来那个isn应该有

  count2 count1 
  data2 data1
但是这种结论仅仅是个理论情况在TCP服务器端并没有保存原来count1和data1因此不能直接进行比较TCP服务器采取思路方法是:

  1)计算出当前分钟值

  count3 := jfies/(HZ*60)

  用count3和count2比较如果差值超过COUNTER_TRIES(4)分钟则认为这 个ACK包不合法

  2)看data2是不是个合法msstab索引也就是说是不是小于NUM_MSS 即((msstab)/(msstab[0]) - 1)如果小于则认为这个ACK 合法否则认为非法

  上面介绍就是Linux内核Linux2.4.20中对SYN Cookie实现方式下面讨论下它合理性希望得到结论是这种方案可以有效实现般TCP连接同时可以防止SYN Flood攻击

  从上面介绍来说合法TCP连接请求定可以通过SYN Cookie流程方面我们看SYN Cookie在系统受到各种SYN Flood攻击时会采取行为SYN Flood攻击方式是攻击者作为TCP客户机发送大量TCP SYN包而不再发送其他这时SYN Cookie会为每个SYN包计算出相应ISN值并返回SYN+ACK包而在本地将不分配任何存储空间因此不会被成功攻击

  根据SYN Cookie原理攻击者有可能直接发送大量ACK包这时SYN Cookie提取出每个包isn值并假定它有下面格式

    isn := A+sseq + (count<<COOKIEBITS) + (B+data)&COOKIEMASK

  反算出count和data

  攻击者并不知道这里A和B因此经过反算出count和data几乎不可能都合理因此TCP服务器也几乎不可能为这些ACK包分配存储空间这也就介绍说明了SYN Cookie达到起到了抵挡SYN Flood攻击作用

  4、SYN Cookie Firewall

  从上面介绍可以看到Linux内核中SYN Cookie机制主要功能是防止本机遭受SYN Flood攻击但是在很多情况下仅仅实现这样SYN Cookie机制是不够如果我们要考虑个网关模式防火墙它不仅要保护本机免受各种网络攻击还要保护它后面所有对外有开放TCP端口主机免受这些攻击比如个局域网中有个服务器开放了FTP服务给外界这个服务器主机就有可能遭受到来自互联网上SYN Flood攻击而这时防火墙会将所有攻击SYN包转发给受害主机

  种杜绝这种情况思路方法是SYN Cookie Firewall它是SYN Cookie种扩展形式来说它是利用原来SYN Cookie原理在内网和外网的间实现TCP 3次握手过程代理(proxy)机制

  为了方便描述我们假定个外在TCP客户机C希望通过防火墙F连接到局域网中个TCP服务器S

  在防火墙收到来自外网SYN包时它并不直接进行转发而是缓存Cache在本地再按照原来SYN Cookie机制制作好个针对这个SYN包SYN+ACK包注意这个SYN+ACK包中ack顺序号为特制cookie值c更重要是这个包源地址被伪造成了S地址(为了描述方便我们这里暂时不考虑NAT等其他原因)这样C会接收到这个SYN+ACK包并认为是从S反馈回来于是C再响应个ACK包并认为和STCP连接已经建立起来这时防火墙F收到这个ACK包按照前面描述SYN Cookie原理来检查这个ACK中ack顺序号如果认为合法F将本地缓存Cache来自CSYN包发送给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的间实现了对 3次握手协议代理次" 3次握手"在TCP Client和防火墙的间进行第 2次" 3次握手"在防火墙和TCP Server的间在第次" 3次握手"时使用前面介绍SYN Cookie流程个问题在进行两次" 3次握手"时出现了:如图所示进行第次" 3次握手"后TCP Client认为后续数据包seq值从c+1开始而进行第 2次" 3次握手"后TCP Server认为后续发来数据包seq值从c`+1开始 c是cookiec`是TCP Server随机产生c和c`几乎不可能相等也就是说在完成上面两个" 3次握手"后如果不进行其他操作后续从TCP Client到TCP Server数据包都将被认为顺序号不对而被丢掉种补救思路方法就是在防火墙本地保存个值δ



  δ = |c - c`|

  利用这个差值在每个数据包经过防火墙时将其seq值修改这样后续数据流量可以完美地在TCP Server和TCP Client的间传输了

  整理总结

  现在普遍使用IPv4协议带有很多安全上问题其中面对SYN Flood攻击软弱就是在不改变TCP 3次握手流程情况下TCP Server几乎不可能有效防范SYN Flood攻击要保证完全防范SYN Flood必须修改 3次握手协议SYN Cookie是种很有效思路方法思想比较简单主要是如何具体实现Linux系统也提供了种实现作者通过研读Linux2.4.20内核中代码基本了解了Linux内核中实现SYN Cookie手段将其整理总结成文字和对SYN Cookie同样感兴趣朋友分享、交流

 


Tags:  linux内核完全注释 linux内核编译 深入理解linux内核 linux内核

延伸阅读

最新评论

发表评论