三次握手的缺陷&accpet()函数调用时机
我记得这个问题是大4同学在找工作的时候被问及的(我考研)。他当时也是一脸懵逼,回来之后还把这个跟我说了,我也不知道这个问题的答案(说白了就是知识串联的不好)。不过后来从新整理一下思路就得到答案了。完全可以从之前的知识以及常识推出这个问题的答案。
三次握手的缺陷
我们都知道三次握手的第一步是客户端向服务器发送连接请求,第二步是服务器回应客户端的请求,第三步是客户端确认连接。从上图可以看出,前两个报文的SYN都置为1,说明它们是同步报文段,同步报文段比较特殊,即使它并没有携带任何应用程序数据,它也要占用一个序号值。其实这个问题的答案就在第二步。在第二次握手时,服务器的TCP收到连接请求报文段后,如若同意建立连接,就向客户端发送确认,并在OS内核中为该TCP连接分配TCP缓存和变量。在确认报文段中,SYN和ACK位都被置为1,确认号字段的值为x+1(表示希望收到的下一个字节的序号为x+1),并且服务器随机产生起始序号seq=y(确认报文不携带数据,但也要消耗掉一个序号)。在计算机里的资源就是两个东西——时间和空间(时间是指处理机的时间,而空间就是硬盘,内存等空间)。这个分配资源的时间很好理解,如若是在第三次握手时才分配资源,那对客户端请求响应肯定会变慢。了解了这个分配资源的问题后,假如,一个黑客想攻击一台服务器,他可以怎么做?首先他伪造地址对服务器发起SYN请求,服务器回应(SYN+ACK)包,而真正的IP并没有做出相应的请求,当然不会回应。服务器没有收到回应,这样的话,服务器会认为(SYN+ACK)丢了,默认情况下会重试5次。在这种状态下,服务器会一直维护刚才所分配的资源,可是这些资源并不能被真正的用户所利用。在这个过程中,黑客只需要做到浪费服务器的资源,使得服务器无法响应多数客户端的请求,就能达到攻击服务器的目的了。这就是三次握手存在的缺陷,也是SYN flood攻击的原理。
accpet函数调用的时间
还有一个问题就是accept函数是在那个阶段调用的。之前我一直以为是第二次握手的时候就完成这项工作了。可是没想到啊,最近查看资料后发现自己是大错特错(要不然我也不会整理这两个知识点)。因为服务器在创建Socket、Bind、Listen之后就要接收客户端的连接请求。而且,服务器就是用accept()函数返回的socket文件描述符与客户端通信。我自然而然的认为accept函数是在服务器分配资源的时候完成的。现在再整理一遍思路,假如accept函数在第二次握手就被调用,这时有许多客户端都和该服务端进行连接,发送SYN报文,服务器收到之后,这些客户端又不理会服务器,但此时服务端的资源已经被accept函数分配了。是不是感觉又回到了第一个问题?为了解决这个问题,accept函数被放在三次握手之后。虽然accept函数被放到了三次握手后,但是服务器接收客户端的请求是不会受到影响的。从另一方面分析这个问题,服务器在收到了客户端的请求后发送的是同步报文,即服务器不需要(也没必要)向客户端传递消息,所以服务器没有用到accept()函数返回的socket文件描述符与客户端通信。
我上网查阅了相关资料,就针对SYN防御的措施,可以通过以下方式:
(1)无效连接监视释放:这种方法不停的监视系统中半开连接和不活动的连接,当达到一定阈值时就释放这些连接,从而回收系统的资源。这种绝对公平的方法往往也会将正常的连接的请求也会被释放掉。
(2)延缓TCB分配方法:SYN Flood关键是利用了SYN数据报文一到,服务器立即分配TCB资源,从而占用了服务器资源。可以用两种技术来解决这一问题。①Syn Cache技术:它的思想是在收到SYN时不急着去分配TCB,而是先回应一个ACK报文,并在一个专用的HASH表中(Cache)中保存这种半开连接,直到收到正确的ACK报文再去分配TCB。②Syn Cookie技术:完全不使用任何存储资源,它使用一种特殊的算法生成Sequence Number,这种算法考虑到了对方的IP、端口、己方IP、端口的固定信息,以及对方无法知道而己方比较固定的一些信息,如MSS、时间等,在收到对方 的ACK报文后,重新计算一遍,看其是否与对方回应报文中的(Sequence Number-1)相同,从而决定是否分配TCB资源。
(3)使用SYN Proxy防火墙:其原理是对试图穿越的SYN请求进行验证之后才放行。