TCP三次握手与四次挥手的简单理解

好久没更新博客了,水一篇以前的笔记 ping 一下探活 =w=

三次握手

三次握手的流程

  • [C --> S] SYN=X
  • [C <-- S] SYN=Y; ACK=X+1
  • [C --> S] SEQ=X+1; ACK=Y+1 (此时已经可以携带数据了)
  • [C --> S] SEQ=X+1; ACK=Y+1 (如果上一个包没携带数据,则为第一个数据包)

为什么第三个握手包与第一个数据包的序列号一致?

因为……

  • ACK 不占用序列号;
  • SYN 占用一个序列号;

为什么是三次?

我的理解,有两个理由:

理由一:防止历史数据包造成的混乱

收到第二个包之后,由于客户端 SYN 包序列号的随机性,客户端可以确认服务器此时确实在响应当前请求而非历史请求;

收到第三个包之后,由于服务端 SYN 包序列号的随机性,服务器可以确认客户端此时确实在响应当前请求而非历史请求;

理由二:双方需要各自确认两方的收发能力均正常

跟踪一下三个包的过程中对收发能力的确认状态:

序号C确认C的发送能力C确认C的接收能力C确认S的发送能力C确认S的接收能力S确认S的发送能力S确认S的接收能力S确认C的发送能力S确认C的接收能力
第一次握手结束Y
第二次握手结束YYYYY
第三次握手结束YYYYYYYY
C/S在三个包的收发过程中对收发能力的确认情况

SYN 泛洪攻击

SYN 泛洪攻击是什么?

在三次握手过程中,服务器发送第二个握手包之后的连接是一种「半连接」。如果客户端在短时间内发送大量的 SYN 握手包,服务器将需要维护大量的半连接(及其所占用的资源),而且需要不断重发第二个握手包,直至超时。

如何识别 SYN 泛洪攻击?

netstat 命令可以看到大量的 SYN_RCVD 连接。

如何防御这种攻击

  • 增加半连接池的大小
  • 缩短超时时间
  • SYN Cookies
    • 在第二个握手包的序列号中隐藏信息。服务器在收到第三个握手包之后,校验序列号有效后才为连接分配资源。

四次挥手

四次挥手的流程

  • [C --> S] FIN=X
  • [C <-- S] ACK=X+1
  • [C <-- S] FIN=Y
  • [C --> S] ACK=Y+1

前两次挥手与后两次挥手是对称且独立的,因此有半关闭连接的概念。

TCP 报文段结构

TCP报文结构

TCP 头部的典型长度为 20 Bytes(一般用 4 Bytes 宽度的表格来表示时,刚好是五行)。

其他小细节

  • 序列号是构建在字节流之上的,而非报文段
  • 确认号是期望收到的下一字节的序号(所以会+1)
  • SYN、FIN 包均占用一个序列号,ACK 包不占用序列号
  • 64240 是一个常见的窗口大小,因为它是 65536 以内 MSS 的最大整数倍(44 个 MSS 典型值 1460)
题图来自 Uriel SC Unsplash

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据