概述
QUIC
(Quick UDP Internet Connections
)是一种基于UDP
的传输层协议,由Google
于2012
年提出,旨在解决TCP
和TLS
的性能瓶颈,提供更快的连接建立、更低的延迟和更强的可靠性2018
年,QUIC
被标准化为IETF QUIC
(RFC 9000
),并成为HTTP/3
的底层协议
设计目标
- 减少延迟:消除
TCP
的三次握手和TLS
的额外往返时间(RTT
) - 避免队头阻塞(
Head-of-Line Blocking
):通过多路复用独立的数据流 - 连接迁移:在网络切换(如
Wi-Fi
到4G
)时保持连接 - 改进拥塞控制:灵活支持多种算法(如
BBR
、CUBIC
) - 默认加密:所有数据均加密传输,整合
TLS 1.3
QUIC
的核心特性
基于 UDP
- 绕过操作系统和中间设备对
TCP
的优化限制,直接在UDP
上实现可靠传输 - 避免
TCP
的队头阻塞问题(TCP
将数据视为单一有序流)
多路复用(Multiplexing
)
- 在单个连接上并行传输多个独立的流(
Stream
),每个流的数据包丢失不会阻塞其他流 - 例如:网页加载时,图片、
CSS
、JavaScript
可以并行传输
0-RTT
和 1-RTT
连接建立
1-RTT
连接:- 首次连接时,客户端和服务端通过一次往返完成密钥协商(
TLS 1.3
)
- 首次连接时,客户端和服务端通过一次往返完成密钥协商(
0-RTT
连接:- 后续连接时,客户端可直接发送加密数据,无需握手(类似
TCP Fast Open
)
- 后续连接时,客户端可直接发送加密数据,无需握手(类似
连接迁移
- 使用连接
ID
(Connection ID
)标识连接,而非传统的IP
+ 端口。 - 即使设备切换网络,连接仍可保持
前向纠错(FEC
)
- 发送冗余数据包(如
XOR
编码),在部分丢包时无需重传即可恢复数据(可选功能)
灵活的拥塞控制
- 默认使用
CUBIC
或BBR
算法,并允许动态调整策略
QUIC
协议结构
概述
QUIC
数据包分为两个层次:QUIC
数据包(Packet
):包含头部和负载QUIC
帧(Frame
):负载中的最小数据单元,承载实际信息
数据包头部
- 长头部:用于初始握手,包含版本、连接
ID
等信息 - 短头部:用于已建立的连接,仅包含连接
ID
和包号
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-+-+-+-+-+-+-+-+ |1| 版本 (32) | +-+-+-+-+-+-+-+-+ | 目标连接ID | +-+-+-+-+-+-+-+-+ | 源连接ID | +-+-+-+-+-+-+-+-+ | 令牌(Token) | +-+-+-+-+-+-+-+-+ | 包号(可变长度)| +-+-+-+-+-+-+-+-+ | 负载(Payload)| +-+-+-+-+-+-+-+-+ |
帧类型
STREAM
:传输流数据
1 2 3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 类型 (0x08) | 流ID (变长) | 偏移量 (变长) | 长度 (变长) | 数据... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
ACK
:确认接收到的包
1 2 3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 类型 (0x02) | 最大确认包号 | 确认延迟 | 包范围计数 | 包范围... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
CRYPTO
:传输TLS
握手数据CONNECTION_CLOSE
:关闭连接
流
- 单向或双向,支持优先级设置
- 每个流独立处理,保证数据有序性和可靠性
QUIC
协议核心机制拆解
QUIC
协议连接过程
首次连接
Client Hello
:客户端生成临时密钥(Ephemeral Key
),发送Client Hello
(包含支持的TLS
版本、密钥参数等)Server Hello
:服务端生成密钥,返回Server Hello
、证书和加密的Finished
消息- 密钥计算:双方通过
HKDF
算法生成会话密钥,后续通信加密 QUIC
细节:所有握手消息通过CRYPTO
帧传输,而非传统的TLS Record
层
0-RTT
连接
Session Resumption
:客户端使用之前缓存的会话密钥(PSK
)直接发送加密数据- 防重放攻击:服务端通过限制
0-RTT
数据的有效期和一次性令牌(Token
)防御重放
关键问题
- 如何保证
0-RTT
安全性?- 服务端需验证客户端
Token
的有效性,且0-RTT
数据不应用于敏感操作(如支付)
- 服务端需验证客户端
流(Stream
)与多路复用
流类型
- 单向流(
Unidirectional
):客户端到服务端或反之,用于推送数据 - 双向流(
Bidirectional
):两端可同时读写,用于请求-响应模式
流标识符
- 编码为
62
位整数,支持超过4 亿
个并发流 - 奇偶性规则:客户端发起的流
ID
为偶数,服务端为奇数,避免冲突
流控制
- 流量窗口(
Flow Control
):每个流独立控制接收窗口(类似HTTP/2
) - 动态调整:通过
MAX_STREAM_DATA
帧通知对端窗口大小
队头阻塞的彻底解决
- 流间独立:每个流的数据包独立传输和重传
- 示例:流
1
的数据包丢失不会阻塞流2
的数据处理
可靠传输与丢包恢复
包编号(Packet Number
)
- 每个
QUIC
包有独立的递增编号,不因网络路径变化重置 - 加密保护:包号在加密后被隐藏,防止中间设备篡改
确认机制(ACK Frames
)
- 显式确认:接收方通过
ACK
帧告知已接收的包范围 - 延迟确认:允许接收方批量确认多个包,减少开销
快速重传(Fast Retransmit
)
- 基于包号的空洞检测:若发现包号不连续,立即触发重传
- 示例:若包
3
、4
、5
中丢失了包4
,接收方会在收到包5
时触发重传请求
连接迁移与 NAT 穿透
连接 ID
(Connection ID
)
- 由服务端分配,用于唯一标识连接(替代传统
TCP
的4
元组) - 动态更新:支持在连接过程中切换
Connection ID
以增强隐私
NET
穿透
Keep-Alive
机制:定期发送探测包维持NAT
映射表- 端口跳跃(
Port Hopping
):通过Connection ID
保持连接,即使客户端IP
或端口变化
QUIC
安全性
- 默认加密:所有头部和负载均加密(除少量公共字段)
TLS 1.3
整合:密钥协商与传输层协议深度集成,减少握手步骤- 防重放攻击:
0-RTT
数据通过限制重放窗口和单次使用令牌(Token
)增强安全性
QUIC
应用场景
HTTP/3
:QUIC
是HTTP/3
的传输层协议,提升网页加载速度- 实时通信:视频会议、在线游戏等低延迟场景
- 移动网络:应对频繁的网络切换和高丢包率
CDN
优化:通过多路复用和快速重传提升内容分发效率
QUIC
相关库与调试
quiche
Rust
实现,支持HTTP/3
lsquic
C
语言实现,轻量高效
Neqo
Rust
实现,用于Firefox
Google QUIC
C++
实现,Chrome
浏览器底层- 关键目录
1 2 |
net/quic/ # QUIC 核心逻辑 net/third_party/quiche/src/quiche/quic/ # Google 原始 QUIC 实现 |
- 核心类
QuicSession
:管理连接生命周期、流控制和多路复用QuicStream
:单个流的实现,处理数据的收发和有序性QuicPacketCreator
:构建 QUIC 数据包,处理包编号和帧封装
调试
Wireshark
- 需安装
QUIC
插件,过滤udp.port == 443
- 需安装
qlog
:QUIC
专用日志格式,记录连接事件和状态变化
1 2 |
# 过滤 QUIC Initial Packet udp.port == 443 && quic.long.packet_type == 0x00 |
QUIC
的底层问题与优化
QUIC
的性能挑战
UDP
缓冲区限制:操作系统默认UDP
接收缓冲区较小,需手动调优
1 2 3 |
# 调整 Linux UDP 缓冲区 sysctl -w net.core.rmem_max=2500000 sysctl -w net.core.wmem_max=2500000 |
CPU
密集型加密:通过硬件加速(如AES-NI
)优化TLS 1.3
计算
对抗网络干扰
PMTUD
(路径MTU
发现):QUIC
支持动态MTU
探测,避免分片FEC
(前向纠错):通过XOR
冗余包在丢包时快速恢复数据(需权衡带宽开销)
相关文档
RFC9000
RFC9114
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ KWP2000协议04/14
- ♥ RFB 协议05/25
- ♥ Linux 高性能服务器编程:TCP二11/24
- ♥ WebSocket协议相关学习一03/24
- ♥ TCP 协议11/13
- ♥ Linux 高性能服务器编程:网络基础编程一11/27