ISN
A -------------------> B
SYN/ACK
A <------------------- B
ACK
A -------------------> B
在 A 向 B 发出 TCP 请求的时候,它发出一个随机的 ISN (Initial Sequence Number),B 收到后给 A 回复一个 ACK = ISN + 1,同时再回复一个自己的 SYN 号,接着会保存 A 发来的这些信息,同时再内存中开辟缓冲区进行保存,然后 A 再给 B 回复一个 ACK。经历过这三次之后,一个端到端的 TCP 连接已经建立起来了,这是正常的情况。但是,考虑这种情况,如果在 A 向 B 发出请求,B 给 A 回复并且开辟了资源之后,A 不再进行第三次的回复,会怎么办?这就好比说,张三收到钱了,也不给我打电话,我一等 2 个月,按照常理的话张三早该收到钱了,但是他还没来电话,没办法,我只有再去汇钱了,那么如果每一次都这样,我这里的钱是不是很快就汇完了?TCP 中也是这样,如果 A 一直在向B 发起 TCP 请求,B 也按照正常情况进行响应了,但是 A 不进行第三次的握手,造成半连接,那么 B 分配出去的内存资源就一直这么耗着,直到资源耗尽。
对于这种攻击,似乎是没有办法防范的,因为 TCP 的三次握手是协议规定死的,所有使用 TCP 协议的软件都必须遵循其规定,否则无法通信。但是,有一种办法,似乎可以防范,那就是限制通信源的 TCP 并发连接数,例如:如果 A 在 1 秒钟之内连续产生 100 个 TCP 半连接,那么 B 就丢弃 A 所有的 TCP 信息,并且在一定时间内不再响应攻击者的释放内存资源。这看起来似乎似乎一种行之有效的办法,可是实际并非这么简单,因为在第三层的 IP 协议是一个不可靠的协议,它的源地址可以被伪造,如果一个攻击者制造大量的伪造源地址来对受害者进行攻击,而每一个 IP 地址的 TCP 半连接只建立 3~5 次,这个时候如何防范?
基于此,一种新型的防御方式产生了—— TCP Cookie,TCP Cookie 技术针对 TCP 协议的软肋,做出了一些改进。仍以上面的通信过程为例,在 A 向 B 发出一个 TCP 请求之后,B 并不立即为 A 的 TCP 请求分配资源,而是利用 A 发来的连接信息计算出一个 Cookie 值——取 Client 端的 IP、端口,以及 Server 端的 IP、端口,再进行一种散列算法,得到一个 Cookie,取该 Cookie 的前 24 位作为 SYN 值对对方进行回复。当对方对这个 SYN/ACK 再次进行 ACK (ACK=SYN+1)回复的时候,利用某种算法和这个 ACK 来倒推回原来的 Cookie,如果在一定范围内符合,即认为是合法的 TCP 请求,对它进行响应,如果不符合,则认为其是非法的 TCP 请求,丢弃。为什么说是一定范围内呢,因为 Cookie 的变化和时间有关,那么在 TCP 超时之内的所有的 ACK 都应该是合法的,那么在倒推回去的时候,只要得到的 Cookie 和原来的 Cookie 在一个合法的时间段内相符,就认为是合法的。