QUIC协议详解2

QUIC协议详解2

本篇:QUIC 系列 ③/④ · QUIC协议详解2 · 系列总览见 QUIC协议系列导读

Connection ID 把 连接身份IP:Port 解耦,手机换网可不断连;Stream 在连接内提供 多路独立字节流 ;TLS 1.3 经 CRYPTO 帧 嵌入 QUIC,无传统 TLS Record。本篇覆盖:连接迁移StreamTLS over QUIC关闭与版本协商

速览

  • CID 查表定位连接;迁移后更新对端地址,密钥与 PN 空间保留
  • Stream ID 低 2 bit:发起方 + 单向/双向;HTTP/3 每请求一条双向流。
  • 无 TLS Record;握手走 CRYPTO + Initial/Handshake 包。
  • CONNECTION_CLOSE 分传输/应用;Idle Timeout 常静默丢弃。

目录

一、连接与迁移

  • [1. 为何 TCP 不能迁移](#1. 为何 TCP 不能迁移)
  • [2. Connection ID 与迁移流程](#2. Connection ID 与迁移流程)
  • [3. 迁移期的丢包与乱序](#3. 迁移期的丢包与乱序)

二、Stream 模型

  • [4. Stream ID 与方向](#4. Stream ID 与方向)
  • [5. 生命周期与 HTTP/3 映射](#5. 生命周期与 HTTP/3 映射)

三、TLS 与连接生命周期

  • [6. TLS over QUIC 与 CRYPTO](#6. TLS over QUIC 与 CRYPTO)
  • [7. 0-RTT 重放防护](#7. 0-RTT 重放防护)
  • [8. 关闭、空闲与版本协商](#8. 关闭、空闲与版本协商)

1. 为何 TCP 不能迁移

TCP 用 四元组 标识连接:

text 复制代码
(源 IP, 源 Port, 目的 IP, 目的 Port)

Wi-Fi → 蜂窝时 源 IP 变 ,内核视为新连接,必须 TCP + TLS 重握手

QUIC 用 Connection ID(CID) :与 IP/Port 无关的 opaque 标识(RFC 9000 至少 64 bit ,常 8~20 字节)。收包 查 CID → 连接对象,IP/Port 只是投递地址。


2. Connection ID 与迁移流程

2.1 双端 CID

方向 含义
客户端 → 服务端 Destination CID = 服务端分配的 Client-facing CID
服务端 → 客户端 Destination CID = 客户端分配的 Server-facing CID

2.2 客户端主动迁移(典型:换网)

RFC 9000:仅客户端可主动迁移 (例外:Server Preferred Address------服务端在握手参数里通告优选地址,客户端可迁往该地址)。

text 复制代码
① 初始:Client(IP1:Port1) ←QUIC→ Server;Destination CID = 已协商 CID
② 换网:出口变为 (IP2, Port2)
③ 路径验证(推荐):新路径发 PATH_CHALLENGE → 对端 PATH_RESPONSE
④ 正式迁移:新四元组发普通 QUIC 包,CID 不变(或换预分配新 CID)
   服务端按 CID 匹配 → 更新对端地址 → 密钥/Stream/未 ACK 数据保留
⑤ 拥塞:RFC 9000 建议重置 cwnd;具体策略由实现决定(有的保守继承)

Server Client Server Client Wi-Fi IP1 → 4G IP2 按 CID 匹配,更新对端地址 PATH_CHALLENGE(新路径,可选) PATH_RESPONSE 普通包,CID 不变,源地址 IP2

步骤 行为
检测换网 本地出口变为新四元组
路径验证 PATH_CHALLENGE / PATH_RESPONSE(防伪造迁移)
正式迁移 新地址发 QUIC 包,CID 不变(或换预分配新 CID,见下)
服务端 更新连接记录的 对端地址
拥塞控制 RFC 建议 重置 cwnd;实现可不同;Stream/TLS/未 ACK 数据保留

NAT Rebinding:同 CID、新源端口到达 → 服务端视为 NAT 重绑定 → 验证 → 更新地址。

Server Preferred Address :握手 preferred_address 参数携带服务端另一 IP:Port;客户端验证后可迁往,仍靠 CID 标识同一连接。

2.3 换 CID 与 NEW_CONNECTION_ID

长期固定 CID 可被跨网络关联。握手时双方通过 NEW_CONNECTION_ID预分配 CID 列表 ;主动迁移时可 换新 CID (仍映射同一连接),外部观察者难关联。对端不再使用的 CID 用 RETIRE_CONNECTION_ID 退役。

作用
NEW_CONNECTION_ID 下发 Sequence + CID + 可选 Stateless Reset Token
RETIRE_CONNECTION_ID 通知对端某 Sequence 的 CID 已停用

负载均衡常从 SCID 嵌入 server_id,对 Destination CID 做 consistent hash(见 QUIC应用实践)。

项目 TCP QUIC
连接标识 四元组 CID
IP 变化 断连重连 保持(+ 路径验证)
密钥 新连接新密钥 沿用

3. 迁移期的丢包与乱序

迁移 ≠ 新连接 :PN 空间、密钥、Stream、发送缓冲 不变 ;变的是 对端地址 与常见 拥塞窗口

3.1 丢包

未 ACK 的包:与普通丢包相同 ------PTO 或判 lost 后,帧内容封装进新 PN ,从 当前生效路径 发出。QUIC 不区分「迁移导致」与「普通」丢包。

3.2 新旧路径交叉

情况 处理
旧路径包晚到(正确 CID) 可接收、回 ACK;不再从旧地址发数据
新先到、旧后到 PN 单调 + 已 ACK 的 PN 不重复执行;Stream Offset 保证应用有序
未验证新路径 可收包;不更新对端地址;防 off-path 伪造

PATH_CHALLENGE 丢失 → PTO 重发,与数据重传机制一致。

3.3 迁移期丢包 + 乱序时序(示例)

text 复制代码
旧路径(IP1)              新路径(IP2)
   |                        |
   | PKN=100 (STREAM) ----->|  (未 ACK,切网)
   |                        |-- PKN=101 PATH_CHALLENGE -->
   |                        |<-- PATH_RESPONSE
   |<-- ACK PKN=100 --------|  (旧路径迟到 ACK,可接受)
   |                        |-- PKN=102 (重封装 PKN=100 数据 + 新数据)
  • PKN=100 疑似丢失 → 时间阈值或 PTO → 新 PN 重封装,从 当前生效路径 发出。
  • 旧路径迟到 ACK 仍记录,不再从旧地址发数据 ;Stream 靠 Offset 保证应用有序。

4. Stream ID 与方向

Stream = 连接内 单向或双向逻辑字节流CID + Stream ID 唯一标识。

Stream ID 编码(低 2 bit)

Bit 含义
Bit 0 发起者:0=Server,1=Client
Bit 1 方向:0=双向 ,1=单向
Stream ID 含义
0 Client 发起 · 双向
1 Server 发起 · 双向
2 Client 发起 · 单向
3 Server 发起 · 单向
4,8,12... Client 双向递增(步长 4)

双向流 :双方可读写;单向流:仅发起方可写(Control、QPACK 等)。

类比:一条 QUIC 连接 ≈ 多路 mini-TCP ,且 无连接级队头阻塞(丢包只挡含该数据的 Stream)。


5. 生命周期与 HTTP/3 映射

HTTP/3 不再依赖 TCP 上的多路复用 ,而是天然基于 QUIC 独立 Stream(与入门篇「无队头阻塞」呼应)。

5.1 正常关闭

text 复制代码
发送方:STREAM(FIN=1, Offset=end) → 对端 ACK → 流结束
接收方:读 EOF → 消费完毕

5.2 异常

作用
RESET_STREAM 发送方放弃该 Stream
STOP_SENDING 接收方要求对端停止发送

5.2.1 Stream 状态机(发送侧,简化)

text 复制代码
Open → Data Sent → Data Recvd → Closed
       ↓
    Reset Sent → Reset Recvd → Closed

(接收侧镜像对称;RFC 9000 §3.4 有完整状态图。)

5.3 HTTP/3 如何用 Stream(预览)

用途 Stream 类型
每个 HTTP 请求/响应 Client 双向(0,4,8...)
Control(SETTINGS/GOAWAY) 单向 type=0x00
QPACK Encoder/Decoder 单向 type=0x02 / 0x03

详细帧格式见 QUIC应用实践

text 复制代码
QUIC Connection
 ├── 双向 Stream 0  → GET /
 ├── 双向 Stream 4  → POST /api
 ├── 单向 Stream 2  → Client Control
 └── 单向 Stream 3  → Server Control

6. TLS over QUIC 与 CRYPTO

QUIC 用 AEAD 加密包;TLS 只负责 密钥协商、证书、导出密钥不用 TLS Record Layer

项目 HTTPS/TCP HTTP/3/QUIC
握手载体 TCP 字节流 CRYPTO 帧 in Initial/Handshake
记录加密 TLS Record QUIC AEAD
顺序 TCP 有序 CRYPTO Offset 连续;应用数据走 STREAM

CRYPTO 帧Offset + Length + Crypto Data(TLS Handshake 消息片段),按 Offset 重组后送 TLS 状态机。

握手阶段映射

阶段 QUIC 包 内容
Initial Client→Server ClientHello
Initial/Handshake Server→Client ServerHello、Cert、Finished...
Handshake Client→Server Client Finished
--- Server→Client HANDSHAKE_DONE

HANDSHAKE_DONE :服务端通知 握手已确认 ;Client 收到后才认为 handshake confirmed,再全面使用 1-RTT 密钥。TLS Finished 发出 ≠ QUIC 层握手结束。

6.1 密钥更新(Key Update)

握手完成后,任一方可在 1-RTT 阶段发起 Key Update :Short Header 的 Key Phase(C bit) 在「当前密钥 / 下一密钥」间切换,双方确认后完成轮换。CRYPTO 帧仅出现在握手阶段,不随 Key Update 再出现。


7. 0-RTT 重放防护

0-RTT 数据用 early key 加密,可被截获重放

缓解 说明
仅幂等请求 GET/HEAD;禁止盲目重放 POST
NEW_TOKEN 服务端可在 Initial 响应中发 NEW_TOKEN;Client 下次 Initial 携带,服务端校验区域/IP,减轻重放
Anti-replay Retry Token、限流、直接 拒绝 0-RTT
应用语义 写操作等 handshake confirmed 后再发

QUIC协议入门 中 0-RTT 预告一致;工程上默认 谨慎启用 0-RTT 写。


8. 关闭、空闲与版本协商

8.1 CONNECTION_CLOSE

Type 含义
0x1c 传输层 协议错误,立即不可用
0x1d 应用层 业务主动关闭,可排空

流程:发 CLOSE → Draining (可能 重发 CLOSE 防 UDP 丢)→ 超时销毁。

HTTP/3 推荐:GOAWAY → 等 Stream 结束 → CONNECTION_CLOSE(app)

8.2 Idle Timeout

协商 max_idle_timeout (取双方较小值)。超时 静默丢弃 ,常不发 CLOSE。保活可用 PING

8.3 Version Negotiation

服务端不支持 Client 版本 → 回 VN 包 (版本列表、无 Long/Short Header、无加密、无 PN )。Client 换版本主动重试 ;VN 包 不能被 ACK

QUIC 不会自动降级到 TCP ;TCP fallback 由 Happy Eyeballs 等应用层策略处理(见 QUIC应用实践)。

8.4 连接关闭状态机(简化)

text 复制代码
Established
     ├─ 发出/收到 CONNECTION_CLOSE → Draining(可重发 CLOSE 防 UDP 丢)
     └─ drain 超时 → Destroyed

(Closing:已发 CLOSE 等 drain;Draining:主要收包触发 CLOSE 重发,不处理新数据。)
收到/发出 CONNECTION_CLOSE
drain 超时
Established
Draining
Destroyed


一句话QUIC协议详解2连接是谁(CID)数据分哪条路(Stream)密钥怎么来(CRYPTO/TLS)怎么收尾(CLOSE/Idle/VN)------迁移与 Stream 是 HTTP/3 移动端体验的核心。

相关推荐
技术硬汉7 小时前
Ai帮我找问题-路由器拨号问题-SIM卡不识别
网络·智能路由器
帅次7 小时前
Android 高级工程师面试:网络与数据层 近1年高频追问 18 题
android·网络·okhttp·面试·retrofit·gilde
网络小白不怕黑7 小时前
11.虚拟机模拟路由器实验
linux·运维·服务器·网络
ylscode15 小时前
OpenSSH 10.4 正式发布:后量子加密落地,多项高危漏洞得到修复
网络·安全·网络安全
DianSan_ERP16 小时前
电商架构演进:如何在高并发场景下实现多平台API的标准化履约?
运维·前端·网络·安全·架构·自动化
阿成学长_Cain16 小时前
Linux ipcs 命令超全详解:查看共享内存 / 消息队列 / 信号量,IPC 运维必备
linux·运维·服务器·网络·数据库
青瓦梦滋17 小时前
协议定制/序列化-反序列化(Linux视角)
linux·服务器·网络·c++
驭渊的小故事21 小时前
网络原理01(两千字解析)
网络
KaMeidebaby1 天前
卡梅德生物技术快报|小 RNA 适配体合成 + 多方法亲和力表征全流程标准化操作手册
前端·网络·数据库·人工智能·算法
阿成学长_Cain1 天前
Linux telinit 命令详解:运行级别切换|关机重启|系统维护一站式掌握
linux·运维·前端·网络