QUIC(Quick UDP Internet Connections)是 Google 在 2013 年提出的新一代传输层协议,2018 年 IETF 将其标准化为 RFC 9000。QUIC 最显著的特点是将加密握手与可靠传输结合在一起,实现了 0-RTT 快速连接。本文深入剖析 QUIC 的加密机制,帮助读者理解它与传统 TLS 的区别。

QUIC 加密层概述

QUIC 的加密层位于传输层之上,但与传统 TLS 有本质不同:

特性 传统 TLS QUIC
承载协议 TCP UDP
加密层位置 TLS 层在 TCP 之上 QUIC 内置加密,集成在传输层
握手次数 1-RTT 或 0-RTT 1-RTT 或 0-RTT(更高效)
头加密 可选 必须加密

QUIC 的加密设计遵循 “加密 everything” 原则,尽可能减少明文传输。

QUIC 握手与密钥派生

QUIC 使用 TLS 1.3 的握手结果,但有自己的密钥派生流程。QUIC 的密钥派生使用 HKDF(HMAC-based Key Derivation Function),与 TLS 1.3 相同。

QUIC 密钥派生流程

1
TLS Handshake → 生成 secrets → QUIC 密钥派生 → 包保护密钥
  1. Initial 密钥:使用铜钥(Destination Connection ID)派生,用于握手期间的加密
  2. Handshake 密钥:完成 TLS 握手后派生,用于保护握手数据包
  3. Application 密钥:握手完成后派生,用于保护应用数据

你可以用 OpenSSL 验证 TLS 1.3 的密钥派生过程:

1
2
# 使用 OpenSSL 测试 TLS 1.3 握手(QUIC 使用相同的握手协议)
echo | openssl s_client -connect example.com:443 -tls1_3 2>&1 | grep -E "Protocol|Cipher"

这将显示握手使用的协议版本和密码套件,验证 TLS 1.3 连接。

0-RTT 快速连接

QUIC 支持 0-RTT(Zero Round Trip Time)模式,允许客户端在第一次连接时发送加密数据,无需等待服务器握手完成。这比 TLS 1.3 的 0-RTT 更高效,因为 QUIC 整合了传输层和加密层。

1
2
3
# 查看支持 0-RTT 的 TLS 1.3 配置
# TLS 1.3 的密码套件中,以 -AESGCM 或 -CHACHA20 结尾的支持 0-RTT
openssl ciphers -tls1_3 | tr ':' '\n' | grep -E "(AESGCM|CHACHA20)"

QUIC 数据包保护

QUIC 使用 AEAD(Authenticated Encryption with Associated Data)算法保护数据包,典型配置是 AES-128-GCM 或 ChaCha20-Poly1305。

包头加密

QUIC 的数据包头分为两部分:

  • 头部保护:部分头部字段被加密,防止流量分析
  • 负载加密:数据包负载使用 AEAD 完整加密

验证命令

可以使用 Wireshark 验证 QUIC 数据包的加密情况:

1
2
# 检查系统是否支持 QUIC 协议(通过检查网络统计)
ss -ua | grep -c QUIC 2>/dev/null || echo "No QUIC sockets active"

对于 QUIC 协议分析,可以使用 Wireshark 抓包并解包:

1
2
3
# Wireshark 支持 QUIC 解密,需要在配置中设置
# Edit → Preferences → Protocols → QUIC → 设置 TLS 密钥日志文件
# 启用 TLS 密钥日志:SSLKEYLOGFILE=/tmp/ssl-keys.log

QUIC 与 TLS 1.3 的关系

QUIC 的加密层与 TLS 1.3 密切相关,但有重要区别:

  1. 密钥材料共享:QUIC 直接使用 TLS 1.3 握手的输出作为密钥源
  2. 独立的加密状态:QUIC 维护自己的加密状态机,独立于 TLS
  3. 不同的记录层:TLS 使用记录层(Record Layer),QUIC 使用数据包保护(Packet Protection)

可以用以下命令查看 OpenSSL 对 TLS 1.3 的支持:

1
2
# 查看 OpenSSL 支持的 TLS 1.3 密码套件
openssl ciphers -tls1_3 -s -v | head -10

输出显示支持的密码套件,包括 AESGCM、ChaCha20-Poly1305 等 AEAD 算法。

QUIC 连接的加密流程

完整的 QUIC 连接建立流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
客户端                                        服务器
  |                                              |
  |-------- Initial 包(加密)------------------>|
  |         (包含 TLS ClientHello)              |
  |                                              |
  |<------- Handshake 包(加密)----------------|
  |         (包含 TLS ServerHello + 证书)       |
  |                                              |
  |-------- Handshake 包(加密)--------------->|
  |         (完成 TLS 握手)                     |
  |                                              |
  |========= 1-RTT 加密隧道建立 ============>>|
  |         (应用数据加密传输)                  |

关键点:

  • Initial 包使用 Initial 密钥加密
  • Handshake 包使用 Handshake 密钥加密
  • 1-RTT 包使用 Application 密钥加密

QUIC 连接的加密隧道

传统 TLS 运行在 TCP 之上,需要处理TCP 层的丢包和重传。QUIC 将加密与可靠传输整合在一起:

  • 无队头阻塞:TLS 记录必须按顺序处理,QUIC 流独立,无队头阻塞
  • 连接迁移:QUIC 使用连接 ID,支持网络切换时的无缝迁移,加密状态保持
  • 更快的恢复:丢包后无需等待 TCP 重传,QUIC 可以独立恢复

总结

QUIC 的加密机制是现代传输层安全的重大演进:

  1. 内置加密:将 TLS 握手集成到传输层,减少握手延迟
  2. 0-RTT 支持:客户端可以立即发送加密数据
  3. AEAD 算法:使用现代认证加密,保证数据机密性和完整性
  4. 独立密钥派生:使用 HKDF 从 TLS 握手派生出独立的 QUIC 密钥

QUIC 的设计哲学是 “安全从一开始”,这使得它在性能和安全性上都优于传统的 TLS over TCP 方案。随着 HTTP/3 的普及,理解 QUIC 的加密机制对于网络工程师和安全从业者越来越重要。


参考来源