TCP 协议是可靠的,而 IP 是一种无连接、不可靠的协议。IP 协议尽最大可能将数据报从发送者传输给接受者,但并不保证包到达的顺序会与它们被传输的顺序一致,也不保证包是否重复,甚至都不保证包是否会到达接受者。TCP 要想在 IP 的基础上构建可靠的传输层协议,必须有一个复杂的机制来保障可靠性,主要有:对每个包提供校验和、包的序列号解决了接收数据的乱序、重复问题、超时重传机制以及流量控制、拥塞控制。
SYN 洪水攻击就是客户端伪造 IP 发送 SYN 包,服务端回复的 ACK+SYN 去到了一个未知的 IP 地址,势必会造成服务端大量连接处于 SYN_RCVD 状态。而服务器的半连接队列大小也是有限的,如果半连接队列满了,也会出现无法处理正常请求的情况。解决 SYN Flood 攻击的办法是 SYN Cookie 机制,它的原理其实很简单,就是在三次握手的最后阶段才分配连接资源。服务端在收到 SYN 包后不马上分配内存资源,而是根据这个 SYN 包计算出一个 Cookie 值,作为握手第二步的序列号回复 SYN+ACK,等对方回应 ACK 包时校验回复的 ACK 是否合法,如果合法握手成功,分配资源。
在实际情况下,四次挥手过程会变成三次,即第二步和第三步合并了。在客户端发送 FIN 包之后,会进入半关闭状态,表示自己不会再给对方发送数据了,但是服务端还是可以给自己发送数据的,在这种情况下,如果不及时发送 ACK,死等服务端这边发送数据,可能会造成客户端不必要的重发 FIN 包。如果服务端确定没有什么数据需要发送给客户端,当然就可以把 FIN 和 ACK 合并成一个包发送,四次挥手的过程也就变成了三次。
第一个原因是:数据报文可能在发送途中延迟但最终会到达。如果客户端在发送完 ACK 包后不等待直接进入 CLOSE 状态,过一段时间相同的 IP 和端口号又建立一个新的连接,这样收到的数据包就无法知道到底是旧连接的包还是新连接的包了,造成新连接数据的混乱。如果等待时间是 2 个 MSL,已经足够让一个方向上的包最多存活 MSL 秒就被丢弃,保证了在新创建的 TCP 连接以后,老连接姗姗来迟的包已经在网络中被丢弃消逝,不会干扰新连接。
由此引入两个状态,TCP window full 与 TCP zero window。TCP Window Full 是站在发送端角度说的,表示在途字节数等于对方接收窗口的情况,此时发送端不能再发数据给对方直到发送的数据包得到 ACK。TCP zero window 是站着接收端角度来说的,是接收端接收窗口满,告知对方不能在发送数据给自己。