Skip to content
Kurisu
Go back

TCP 三次握手

TCP 协议概述

TCP 是面向连接、可靠的传输层协议:传输前三次握手建连,结束后四次挥手释放。

TCP 报文段关键字段

字段位数作用
序列号(Seq)32本段数据第一个字节的序号
确认号(Ack)32期望收到对方下一段的序号
SYN1同步标志,建立连接
ACK1确认标志,确认号有效
FIN1结束标志,发送方无数据
RST1复位标志,异常终止连接

三次握手(连接建立)

客户端                                         服务端
  |                                               |
  | —— [SYN]   Seq=x, Ack=0 ——→                   |  第一次
  | CLOSED → SYN-SENT                            |  LISTEN → SYN-RCVD
  |                                               |
  | ←—— [SYN+ACK] Seq=y, Ack=x+1 ——              |  第二次
  | SYN-SENT → ESTABLISHED                        |
  |                                               |
  | —— [ACK]   Seq=x+1, Ack=y+1 ——→              |  第三次
  |                                               |  SYN-RCVD → ESTABLISHED

三次报文:① 客户端发 SYN=1、随机序列号 Seq=x → SYN-SENT;② 服务端分配缓冲区回 SYN=1, ACK=1, Seq=y, Ack=x+1 → SYN-RCVD;③ 客户端回 ACK=1, Seq=x+1, Ack=y+1,双方 ESTABLISHED。第三次握手可携带数据。

为什么不是两次? 两次只能验证客户端发送、服务端接收;第三次让服务端确认自身发送与客户端接收能力,并防过期 SYN 误建连接。


四次挥手(连接释放)

TCP 全双工,每个方向必须独立关闭:

客户端(主动关闭)                              服务端(被动关闭)
  ESTABLISHED                                     ESTABLISHED
      |                                                |
      | —— [FIN]   Seq=u, Ack=v ——→                   |  第一次
      | → FIN-WAIT-1                                  |  → CLOSE-WAIT
      |                                                |
      | ←—— [ACK]   Seq=v, Ack=u+1 ——                |  第二次
      | → FIN-WAIT-2                                   |
      |                                                |
      | ←—— [FIN+ACK] Seq=w, Ack=u+1 ——              |  第三次
      |                                                |  → LAST-ACK
      |                                                |
      | —— [ACK]   Seq=u+1, Ack=w+1 ——→              |  第四次
      | → TIME-WAIT (等 2MSL ≈ 60s)                    |  → CLOSED
      | → CLOSED                                       |

四次报文:① 客户端发 FIN=1(“我没数据了”)→ FIN-WAIT-1;② 服务端确认 → CLOSE-WAIT,客户端 → FIN-WAIT-2;③ 服务端发完剩余数据发 FIN=1 → LAST-ACK;④ 客户端确认 → TIME-WAIT,等 2MSL 后关闭。

TIME-WAIT 为何等 2MSL? (1) 确保最后 ACK 被服务端收到;(2) 让旧连接报文消失、不干扰新连接。


状态变迁汇总

阶段客户端状态服务端状态
初始CLOSEDLISTEN
握手完成ESTABLISHEDESTABLISHED
主动关闭FIN-WAIT-1 → FIN-WAIT-2 → TIME-WAIT → CLOSED-
被动关闭-CLOSE-WAIT → LAST-ACK → CLOSED

标志位速查

阶段SYNACKFIN
握手-1100
握手-2110
握手-3010
挥手-1001
挥手-2010
挥手-3011
挥手-4010

攻击原理

SYN Flood 是典型 DoS:攻击者伪造大量不存在的 IP 发 SYN,服务端为每个 SYN 分配资源(TCB,传输控制块)、回 SYN+ACK 并进 SYN-RCVD 等 ACK;伪造 IP 的 ACK 永不到来,半连接队列占满,正常用户无法建连。

攻击者                      服务端
  |  —— SYN (伪造IP-A) ——→   |  分配TCB → SYN-RCVD
  |  —— SYN (伪造IP-B) ——→   |  分配TCB → SYN-RCVD
  |  —— SYN (伪造IP-C) ——→   |  分配TCB → SYN-RCVD
  |       ... (大量) ...       |  半连接队列满!
  |                            |
正常用户 —— SYN ——→            |  ❌ 丢弃,无法响应

SYN Cookie 核心:收到 SYN 不分配资源,把连接信息编码进序列号还给客户端,仅当收到合法 ACK 才分配资源。

具体流程:

流程:收到 SYN 不分配 TCB → 计算 cookie = hash(源IP, 源端口, 目的IP, 目的端口, 时间戳, 密钥) → 作为初始序列号 Seq=y 在 SYN+ACK 返回 → 真实客户端回 ACK, Ack=y+1(伪造 IP 不会回)→ 服务端验证 Ack-1 是否等于该 hash → 通过才分配 TCB 建连。

SYN Cookie 是 Linux 内核默认防御:半连接队列超阈值时自动启用。


Share this post:

Previous Post
NAT 实验
Next Post
Kali Linux 入门