![4ec702cc02cf1d48d1963b351f13c969.png](https://i-blog.csdnimg.cn/blog_migrate/b8af8652bdf3e54cdd0591deb475b1eb.jpeg)
我们已经看到在讨论TCP三次握手的时候,服务器分配并初始化变量和缓冲区以响应收到的SYN,然后服务器发送一个SYNACK作为响应,并等待一个来自客户端的ACK报文段。如果客户端没有发送一个ACK来完成三次握手的第三步,最终(通常一分钟或更久以后)服务器会终止这个半开的连接并收回分配的资源。
这个TCP连接管理协议为一种典型的被称为SYN泛洪攻击的拒绝服务攻击(DoS)提供了舞台。在这个攻击中,攻击者发送大量的TCP SYN报文段,不完成第三次握手的步骤。随着SYN报文段的大量涌入,服务器的连接资源在分配给(但从未使用)半开连接时会耗尽。然后合法的用户就被拒绝服务了。幸运的是,一种称为SYN cookie的有效防御现在已部署在大多数主要的操作系统中。SYN cookie 的工作原理如下:
- 当服务器收到SYN报文段时,他不知道该段是来自合法用户还是属于SYN泛洪攻击的一部分。因此,服务器不会为此SYN创建半开连接,而是创建初始TCP序列号,该序列号是由一个复杂的散列函数将 源和目标的IP地址和SYN报文段中的端口号,以及只有该服务器知道的secret number,作为输入得到的。这个精心设计的初始序列号就是所谓的“cookie”。服务器然后向客户端发送带有这个特殊序列号的SYNACK报文段。重要的是服务器不用记住cookie或者与SYN相对应的任何状态和信息。cookie = hash(src_ip, dest_ip, src_port, dest_port, secret_number)
- 合法的客户端将返回ACK报文段。当服务器收到此ACK时,它必须验证ACK是否与之前发送的某些SYN相对应。但是服务器并没有记住SYN报文段,这怎么办?正如你可能已经猜到的那样,他是通过cookie完成的。回想一下,对于合法的ACK,确认字段中的值等于SYNACK中的初始序列号(本例中为cookie值)加一。然后,服务器可以使用ACK中的源和目标IP地址和端口号和secret number运行相同的散列函数。如果函数的结果加1与客户端的ACK中的确认字段的值相同,则服务器断定ACK段与之前的SYN段时相对应的,因此是有效的。然后服务器会创建一个完全打开的连接。
- 另一方面,如果客户端没有返回ACK段,那么原始SYN没有对服务器造成任何伤害,因为服务器没有分配任何资源来响应原始的加SYN。