TCP三次握手中的数据传输

三次握手过程中哪些阶段可以携带数据

问题

TCP 三次握手过程中可以携带数据吗?如果可以,是哪个阶段?

解答

结论:第一次、第二次握手不能携带数据,第三次握手可以携带数据。

三次握手流程

客户端                                服务端
  |                                     |
  |  -------- SYN (seq=x) --------->    |  第一次握手:不能携带数据
  |                                     |
  |  <--- SYN+ACK (seq=y, ack=x+1) ---  |  第二次握手:不能携带数据
  |                                     |
  |  ---- ACK (seq=x+1, ack=y+1) --->   |  第三次握手:可以携带数据
  |                                     |

为什么前两次不能携带数据?

主要是出于安全考虑,防止 SYN 洪泛攻击

如果第一次握手就能携带数据:

  1. 攻击者可以在 SYN 包中塞入大量数据
  2. 服务端收到后需要分配资源处理这些数据
  3. 攻击者伪造大量不同 IP 的 SYN 请求
  4. 服务端资源被耗尽,无法响应正常请求
攻击者                               服务端
  |                                    |
  |  -- SYN + 大量数据 (伪造IP1) -->   |  分配资源处理
  |  -- SYN + 大量数据 (伪造IP2) -->   |  分配资源处理
  |  -- SYN + 大量数据 (伪造IP3) -->   |  分配资源处理
  |  ...                               |  资源耗尽

为什么第三次可以携带数据?

第三次握手时:

  1. 客户端已经处于 ESTABLISHED 状态
  2. 客户端已确认服务端的收发能力正常
  3. 连接已经建立,携带数据是合理的优化
// 第三次握手时的状态
客户端:ESTABLISHED(已确认双方通信能力)
服务端:SYN_RCVD(等待最后确认)

// 客户端发送 ACK 时可以顺便带上请求数据
// 减少一次 RTT,提高效率

实际应用:TCP Fast Open (TFO)

TCP Fast Open 是一种优化机制,允许在 SYN 包中携带数据:

首次连接:
客户端 -- SYN + Cookie请求 --> 服务端
客户端 <-- SYN+ACK + Cookie -- 服务端
(客户端缓存 Cookie)

后续连接:
客户端 -- SYN + Cookie + 数据 --> 服务端  // 第一次握手就带数据
服务端验证 Cookie 后直接处理数据

这需要双方都支持 TFO,且通过 Cookie 机制保证安全。

关键点

  • 第一、二次握手不能携带数据,第三次可以
  • 前两次不带数据是为了防止 SYN 洪泛攻击
  • 第三次握手时客户端已处于 ESTABLISHED 状态,带数据可减少 RTT
  • TCP Fast Open 通过 Cookie 机制允许首次握手带数据
  • SYN 包虽然不带数据,但会消耗一个序列号