当前位置: 首页 > Linux

TCP中SYN-Cookies的简单解释

时间:2023-04-06 07:11:25 Linux

本文逐步介绍了TCP中的syn-cookie技术,包括它的由来、原理和实例测试。SYNFlood攻击TCP连接建立时,客户端通过发送SYN报文向处于监听状态的服务器发起连接,服务器为该连接分配一定的资源并发送SYN+ACK报文。对于服务端来说,此时的连接状态称为半开(Half-Open),当它收到客户端回复的ACK报文时,就认为连接已经建立。在这个过程中,如果服务器没有收到ACK报文(比如在链接中丢失),服务器会在超时后重传SYN+ACK。如果多次超时重传仍未收到,服务器将回收资源并关闭半连接,就好像原来的SYN报文从未到达过一样!这看起来很正常,但是如果有坏人故意发送大量的假SYN报文,服务器就会分配大量注定无用的资源,而从backlog的意思来看,半连接数服务器可以保存的内容是有限的。!所以当服务器收到大量攻击包后,就无法再正常接收连接。换句话说,它的服务不再可用了!这就是SYNFlood攻击的原理,是典型的DDoS攻击。连接请求的关键信息Syn-Flood攻击成立的关键是服务器资源是有限的,服务器在收到请求时会分配资源。一般来说,服务器使用这些资源来保存本次请求的关键信息,包括请求的来源和目的(五元组),以及TCP选项,如最大报文段长度MSS、时间戳timestamp、selectresponseenableSack,窗口缩放因子Wscale等。当后续的ACK报文到达,三次握手完成,建立新的连接,可以将此信息复制到连接结构中,指导后续的报文收发。所以现在的问题是,服务器如何在不分配资源的情况下,验证后面可能到达的ACK的有效性,从而保证这是一次完整的握手,获得SYN报文中携带的TCP选项信息。SYNcookiesalgorithmSYNCookiesalgorithmwiki可以解决对于上面的第一个问题和第二个问题的部分内容,我们知道在建立TCP连接时,双方的初始数据包序号可以是任意的。SYNcookies利用了这一点,并根据以下规则构造初始序列号:设t是一个缓慢增加的时间戳(典型的实现是每64s递增)设m是客户端发送的SYN消息中的MSS选项值设s为连接的元组信息(源IP、目的IP、源端口、目的端口)和t经过密码运算后的Hash值,即s=hash(sip,dip,sport,dport,t),则s的结果为低24位,初始序号n为:高5位为tmod32,后3位为m的编码值,低24位为s当客户端收到这个SYN+ACK报文,它会按照TCP标准的ACK报文进行回复,报文中的ack=n+1,那么服务器收到后,ack-1就可以取回原来发送的SYN+ACK报文中的序号!服务器巧妙地通过这种方式间接保存了SYN报文的部分信息。接下来,服务端需要检查序列号ack-1:将高5位表示的t与当前的进行比较,看到达时间是否可以接受。根据t和连接元组重新计算s,看是否和低24位一致,如果不一致,说明消息是伪造的。解码序列号中隐藏的mss信息到此为止,即可成功建立连接。SYNCookies的缺点既然SYNCookies可以减少资源分配,为什么TCP标准中没有包含它呢?原因是SYNCookies也是有代价的:MSS码只有3位,所以最多只能使用8个MSS值。服务器必须拒绝客户端的SYN消息中仅在SYN和SYN+ACK中协商的其他选项,因为服务器没有地方保存这些选项。例如,Wscale和SACK都添加了密码操作。Linux中的SYNCookiesSYNCookies在Linux上的实现在序列号生成方面与wiki中描述的算法有些不同。SYN+ACK的序号通过以下公式计算:内核编译需要开启CONFIG_SYN_COOKIESseq=hash(saddr,daddr,sport,dport,0,0)+req.th.seq+t<<24+(hash(saddr,daddr,sport,dport,t,1)+mss_ind)&0x00FFFFFF其中,req.th.seq表示客户端SYN报文中的序号,mss_ind为客户端通知的MSS值的编码客户端。它的值在比较新的内核中有4种(老内核有8种),分别对应以下4种值static__u16constmsstab[]={536,1300,1440,/*1440,1452:PPPoE*/1460,};有兴趣的可以按照下面track浏览调用顺序tcp_conn_request|--cookie_init_sequence|--cookie_v4_init_sequence|--__cookie_v4_init_sequence|--secure_tcp_syn_cookieSYNCookies和timestamp如果服务端和客户端都开启timestamp选项,那么服务端可以开启客户端在SYN报文中携带TCP选项的情况暂时保存在一个时间戳中。目前低6位分别用于保存Wscale、SACK和ECN。客户端会在ACK的TSecr字段中带回这些值。实验Linux中的/proc/sys/net/ipv4/tcp_syncookies是内核中的SYNCookies开关,0表示关闭SYNCookies;1表示在新连接压力比较大的时候启用SYNCookies,2表示一直使用SYNCookies。本实验运行在4.4.0内核上,服务器监听50001端口,backlog参数为3(该参数的含义)。同时模拟不同客户端注入SYN包。测试代码没有启用SYNCookiesCho0>/proc/sys/net/ipv4/tcp_syncookies可以看到服务器在收到3个SYN报文后,不再响应新的连接请求,这就是SYN-Flood方式的攻击.有条件地使用SYNCookiesCho1>/proc/sys/net/ipv4/tcp_syncookies由于服务器的backlog参数为3,所以从图中第四个SYN+ACK(#8消息)开始使用SYNCookies。从时间戳可以看出消息#8(44167748)小于消息#6(44167796)。44167748=0x2A1F244,后6位为0b000100,与SYN报文中wscale=4一致。小结SYNCookie技术允许服务器在收到客户端的SYN报文时无需分配资源就可以存储客户端信息。这些信息保存在SYN+ACK的初始序号和时间戳中。对于正常连接,此信息将与ACK消息一起返回。REFSYN洪水攻击改进syncookies