RFC: TUIC Protocol Specification Version 0x05 Category: Informational Date: April 2026
TUIC 协议规范 (TUIC Protocol Specification)¶
备忘录状态 (Status of This Memo)¶
本文档为互联网社区指定了 TUIC 协议版本 0x05。本规范定义了一种多路复用、经 TLS 加密的流式协议,旨在基于 QUIC 传输层实现高效的网络中继。
摘要 (Abstract)¶
TUIC 协议提供了一个命令驱动的框架,用于在加密的 QUIC 连接上进行 TCP 和 UDP 流量中继。它支持连接多路复用、具有零往返时间 (0-RTT) 建立机制的高效 UDP 会话管理,以及针对大型数据报的健壮的分片机制。本文档描述了协议结构、命令格式、操作流程和实现注意事项。
目录 (Table of Contents)¶
- 简介 (Introduction)
- 约定和术语 (Conventions and Terminology)
- 协议架构 (Protocol Architecture)
- 消息格式 (Message Format)
- 命令定义 (Command Definitions)
- 地址编码 (Address Encoding)
- 协议操作 (Protocol Operations)
- 标头大小计算 (Header Size Calculations)
- 安全注意事项 (Security Considerations)
- 参考资料 (References)
1. 简介 (Introduction)¶
1.1. 目的 (Purpose)¶
TUIC 协议旨在通过 QUIC 传输层提供安全、多路复用的 TCP 和 UDP 流量中继。该协议解决了以下需求:
- 在单个传输连接上的高效连接多路复用
- 零往返时间 (0-RTT) UDP 会话建立
- 对 TCP 流和 UDP 数据报的透明处理
- 针对大型 UDP 数据包的健壮的分片与重组
1.2. 协议版本 (Protocol Version)¶
本文档描述了 TUIC 协议版本 0x05。
1.3. 与其他协议的关系 (Relation to Other Protocols)¶
TUIC 被设计为将 QUIC [RFC9000] 作为主要传输层运行,但保持了传输无关的设计原则。该协议可以集成到现有服务中,包括 HTTP/3 [RFC9114]。
2. 约定和术语 (Conventions and Terminology)¶
2.1. 要求语言 (Requirements Language)¶
本文档中的关键词“必须”(MUST)、“绝对不能”(MUST NOT)、“要求”(REQUIRED)、“将”(SHALL)、“绝对不将”(SHALL NOT)、“应该”(SHOULD)、“不应该”(SHOULD NOT)、“建议”(RECOMMENDED)、“可以”(MAY) 和“可选”(OPTIONAL) 需按照 RFC 2119 [RFC2119] 中的描述进行解释。
2.2. 术语 (Terminology)¶
- 客户端 (Client): 发起 TUIC 连接和中继请求的端点。
- 服务端 (Server): 接受 TUIC 连接并执行中继操作的端点。
- 命令 (Command): 具有特定类型和载荷的协议控制消息。
- 关联 (Association): 由唯一 16 位标识符标识的 UDP 会话。
- 分片 (Fragment): 划分以进行传输的 UDP 数据包的一部分。
- 目标 (Target): 中继流量的最终目的地。
2.3. 数字约定 (Numeric Conventions)¶
除非另有明确说明,本协议中的所有多字节数字字段均使用网络字节序(大端序)。
字段大小表示如下: - 1B = 1 字节 (8 bits) - 2B = 2 字节 (16 bits) - 4B = 4 字节 (32 bits) - 16B = 16 字节 (128 bits)
3. 协议架构 (Protocol Architecture)¶
3.1. 分层模型 (Layering Model)¶
+---------------------------+
| 应用数据 (App Data) |
+---------------------------+
| TUIC 协议 |
+---------------------------+
| QUIC (包含 TLS 1.3) |
+---------------------------+
| UDP |
+---------------------------+
3.2. 连接模型 (Connection Model)¶
TUIC 连接在单个 QUIC 连接上运行。多个中继操作(TCP 连接和 UDP 关联)可以 (MAY) 在此单一连接上多路复用。
3.3. 流使用 (Stream Usage)¶
- 单向流 (Unidirectional streams): 用于不需要响应的命令(例如:Authenticate、Packet、Dissociate)。
- 双向流 (Bidirectional streams): 用于通过 Connect 命令进行的 TCP 中继。
- QUIC 数据报 (QUIC datagrams): 可以 (MAY) 用于 UDP 数据包中继以减少延迟。
4. 消息格式 (Message Format)¶
4.1. 基础命令结构 (Base Command Structure)¶
所有 TUIC 命令共享一个公共的标头结构:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | Type | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| 特定类型的载荷 (Type-Specific Payload)... |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
版本 (Version, 1 字节): 协议版本标识符。本规范定义了版本 0x05。
类型 (Type, 1 字节): 命令类型标识符(见第 4.2 节)。
特定类型载荷 (Type-Specific Payload): 变长载荷,其格式取决于 Type 字段。
4.2. 命令类型注册表 (Command Type Registry)¶
| 值 | 命令名称 | 参考 |
|---|---|---|
| 0x00 | Authenticate | 第 5.1 节 |
| 0x01 | Connect | 第 5.2 节 |
| 0x02 | Packet | 第 5.3 节 |
| 0x03 | Dissociate | 第 5.4 节 |
| 0x04 | Heartbeat | 第 5.5 节 |
所有其他值保留供将来使用。
5. 命令定义 (Command Definitions)¶
5.1. Authenticate (认证) 命令¶
Authenticate 命令用于建立客户端身份和授权。
Type: 0x00
格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | 0x00 | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ UUID (16 字节) +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ TOKEN (32 字节) +
| |
+ +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
UUID (16 字节): 客户端标识符,表示为 UUID [RFC4122]。
TOKEN (32 字节): 身份验证令牌,使用 TLS 密钥材料导出器 (Keying Material Exporter) [RFC5705] 并采用以下参数派生: - Label (标签): 客户端的 UUID 值 - Context (上下文): 原始密码字节 - Length (长度): 32 字节
流程: 1. 客户端必须 (MUST) 在任何其他命令之前,通过单向流发送 Authenticate 命令。 2. 服务端必须 (MUST) 验证 TOKEN 与预期的凭据是否匹配。 3. 如果验证失败,服务端必须 (MUST) 终止连接。 4. 如果验证成功,服务端启用后续命令的处理。
注: 服务端可以 (MAY) 在认证完成前接受命令标头,并在认证成功前暂停处理。
5.2. Connect (连接) 命令¶
Connect 命令用于启动到指定目标地址的 TCP 中继。
Type: 0x01
格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | 0x01 | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| 目标地址 (Target Address, 变长) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
目标地址 (Target Address): 编码方式见第 6 节。
流程: 1. 客户端打开一个双向 QUIC 流。 2. 客户端发送带有目标地址的 Connect 命令。 3. 服务端建立与目标的 TCP 连接。 4. 开始在 QUIC 流和 TCP 连接之间进行双向数据中继。 5. 任何方向的流关闭都会终止中继。
5.3. Packet (数据包) 命令¶
Packet 命令用于中继 UDP 数据报,并支持分片机制。
Type: 0x02
格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | 0x02 | 关联 ID (Assoc ID) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet ID | Frag Total | Frag ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 载荷大小 (Size) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| 目标地址 (Target Address, 变长) |
+ +
| 载荷 (Payload)... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
关联 ID (Association ID, 2 字节): UDP 会话标识符。见第 7.3 节。
Packet ID (2 字节): 用于标识属于同一个 UDP 数据包的所有分片的序列号。
Frag Total (1 字节): 该数据包的分片总数。必须 (MUST) 至少为 1。最大值为 255。
Frag ID (1 字节): 从零开始的分片序号。必须 (MUST) 小于 Frag Total。
载荷大小 (Payload Size, 2 字节): 此分片中载荷部分的长度。
目标地址 (Target Address): 编码方式见第 6 节。对于非首个分片 (Frag ID > 0),这应该 (SHOULD) 使用 "None" (空) 地址类型 (0xFF)。
载荷 (Payload): UDP 数据包的分片数据。
分片规则: - 具有相同 Association ID 和 Packet ID 的分片属于同一个 UDP 数据包。 - 所有分片必须 (MUST) 具有相同的 Frag Total 值。 - Frag ID 必须 (MUST) 从 0 到 (Frag Total - 1)。 - 接收方必须 (MUST) 在转发之前按 Frag ID 顺序重组分片。 - 不完整的分片集合应该 (SHOULD) 在超时时间后丢弃(建议:30秒)。
5.4. Dissociate (取消关联) 命令¶
Dissociate 命令用于终止 UDP 关联。
Type: 0x03
格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | 0x03 | 关联 ID (Assoc ID) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
关联 ID (Association ID, 2 字节): 要终止的 UDP 会话标识符。
流程: 1. 客户端在单向流上发送 Dissociate 命令。 2. 服务端关闭相关的 UDP 套接字。 3. 服务端释放与该关联 ID 相关的所有资源。 4. 随后带有该关联 ID 的 Packet 命令应该 (SHOULD) 被忽略或拒绝。
5.5. Heartbeat (心跳) 命令¶
Heartbeat 命令用于保持连接存活。
Type: 0x04
格式:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | 0x04 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Heartbeat 命令除了基本标头外不包含任何载荷。
流程: - 任何一端都可以 (MAY) 定期发送 Heartbeat 命令。 - Heartbeat 命令应该 (SHOULD) 通过 QUIC 数据报发送,以最小化开销。 - 建议间隔:在活跃中继期间为 30-60 秒。 - 不需要或预期没有任何响应。
6. 地址编码 (Address Encoding)¶
目标地址使用类型-长度-值 (TLV) 格式编码。
6.1. 地址格式¶
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 地址类型 | 地址 (Address, 变长) |
+-+-+-+-+-+-+-+-+ +
| 端口 (Port, 2 字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6.2. 地址类型注册表¶
| 值 | 类型 | 地址长度 | 总大小 |
|---|---|---|---|
| 0x00 | Domain | 1 + N 字节 | 4 + N 字节 |
| 0x01 | IPv4 | 4 字节 | 7 字节 |
| 0x02 | IPv6 | 16 字节 | 19 字节 |
| 0xFF | None | 0 字节 | 1 字节 |
6.3. 地址类型规范¶
Domain (0x00, 域名):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x00 | 长度 | 域名 (Domain Name, 变长)... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 端口 (Port, 2 字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPv4 (0x01):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x01 | IPv4 地址 (4 字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IPv4 地址 | 端口 (Port, 2 字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPv6 (0x02):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x02 | |
+-+-+-+-+-+-+-+-+ +
| |
+ IPv6 地址 (16 字节) +
| |
+ +
| |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 端口 (Port, 2 字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
None (0xFF, 无地址):
- 用于 Packet 命令的非首个分片,以减少开销。 - 绝对不能 (MUST NOT) 用于 Connect 命令或首个分片中。7. 协议操作 (Protocol Operations)¶
7.1. 连接建立¶
- 客户端建立与服务端的 QUIC 连接。
- 客户端在新的单向流上发送 Authenticate 命令。
- 服务端验证身份验证令牌。
- 如果成功,连接准备就绪以进行中继操作。
7.2. TCP 中继¶
客户端到服务端方向: 1. 客户端打开双向 QUIC 流。 2. 客户端发送带有目标地址的 Connect 命令。 3. 服务端建立与目标的 TCP 连接。 4. 客户端在流上发送应用程序数据。 5. 服务端将数据转发到目标 TCP 连接。
服务端到客户端方向: 1. 服务端从目标 TCP 连接接收数据。 2. 服务端在双向 QUIC 流上发送数据。 3. 客户端接收并处理数据。
连接终止: - 任一端都可以 (MAY) 关闭流来发出连接终止信号。 - 服务端必须 (MUST) 在 QUIC 流关闭时关闭目标 TCP 连接。
7.3. UDP 中继¶
建立关联: 1. 客户端生成唯一的 16 位 Association ID。 2. 客户端发送包含该 Association ID 的首个 Packet 命令。 3. 服务端创建 UDP 套接字并将其与该 Association ID 关联。 4. 双方均维护 Association ID 到 UDP 套接字的映射。
数据包转发: - 客户端到服务端: 客户端发送 Packet 命令;服务端从 ADDR 字段中提取目标地址,并转发到该目标。 - 服务端到客户端: 服务端接收 UDP 数据包;服务端发送包含源地址在 ADDR 字段中的 Packet 命令。
完全圆锥型 NAT 行为 (Full Cone NAT): 本协议实现了 Full Cone NAT 语义: - 一旦关联,UDP 套接字可以从任何来源接收数据包。 - 接收到的所有数据包都会连同编码后的源地址一起转发给客户端。
终止关联: 1. 客户端发送 Dissociate 命令。 2. 服务端关闭 UDP 套接字并移除关联映射。
7.4. UDP 分片¶
何时分片: 当 UDP 数据包大小超过以下阈值时,必须 (REQUIRED) 进行分片:
分片流程: 1. 发送方计算最大分片载荷大小(见第 8 节)。 2. 发送方将 UDP 数据包分割为多个分片。 3. 发送方为此 UDP 数据包分配唯一的 Packet ID。 4. 发送方将 Frag Total 设置为分片数量。 5. 对于每个分片: - 将 Frag ID 设置为分片索引(从 0 开始)。 - 首个分片 (Frag ID = 0) 包含完整目标地址。 - 随后的分片可以 (MAY) 使用 None (0xFF) 地址类型。 6. 将每个分片作为单独的 Packet 命令发送。
重组流程: 1. 接收方收集匹配 (Association ID, Packet ID) 的分片。 2. 一旦收到所有分片(Frag ID 0 到 Frag Total - 1): - 按 Frag ID 顺序拼接分片载荷。 - 从首个分片提取目标地址。 - 转发重组后的 UDP 数据包。 3. 如果在超时(建议:30s)后分片仍不完整: - 丢弃部分分片。 - 释放相关资源。
7.5. 错误处理¶
本协议遵循失败即静默 (fail-silent) 的错误模型:
无效命令: - 接收方应该 (SHOULD) 默默丢弃带有未知 Type 值的命令。 - 接收方可以 (MAY) 因为畸形命令而终止连接。
认证失败: - 服务端必须 (MUST) 立即终止连接。 - 服务端应该 (SHOULD) 发送 QUIC CONNECTION_CLOSE 帧。
网络错误: - 流错误导致流关闭,且不发出通知。 - 连接错误导致 QUIC 连接终止。
实现建议: - 为诊断目的记录所有错误。 - 针对严重的认证失败使用连接重置。 - 针对可恢复的流错误,实现优雅降级。
8. 标头大小计算 (Header Size Calculations)¶
了解标头开销对实现至关重要,特别是在确定分片 UDP 数据包的最大载荷大小时。
8.1. 基础命令标头¶
所有命令均包含一个 2 字节的基础标头:
8.2. Packet 命令开销¶
Packet 命令的标头(不含地址)为 10 字节:
Version (1 字节)
Type (1 字节)
Assoc ID (2 字节)
Packet ID (2 字节)
Frag Total (1 字节)
Frag ID (1 字节)
Size (2 字节)
----------------------------
合计: 10 字节
8.3. 地址字段大小¶
| 地址类型 | 大小计算 | 示例大小 |
|---|---|---|
| None (0xFF) | 1 | 1 字节 |
| IPv4 (0x01) | 1 + 4 + 2 | 7 字节 |
| IPv6 (0x02) | 1 + 16 + 2 | 19 字节 |
| Domain (0x00) | 1 + 1 + N + 2 (N≤255) | 4+N 字节 |
8.4. 总的 Packet 命令开销¶
首个分片 (包含完整地址):
| 地址类型 | 总开销 |
|---|---|
| IPv4 | 17 字节 |
| IPv6 | 29 字节 |
| Domain "example.com" | 25 字节 |
随后的分片 (使用 None 地址):
8.5. 最大载荷计算¶
对于给定的 QUIC 最大数据报大小 D:
单个数据包 (不分片):
以 D=1200 为例: | 地址类型 | 最大载荷 | |------------------|-------------| | IPv4 | 1183 字节 | | IPv6 | 1171 字节 | | Domain (11 字符) | 1175 字节 |
8.6. 分片大小计算¶
统一分片大小 (简化方法):
优化的分片大小 (首分片含地址,其余含 None):
首分片大小 = D - (10 + 地址大小)
后续分片大小 = D - 11
首分片后剩余大小 = 总载荷 - 首分片大小
额外分片数 = ceil(首分片后剩余大小 / 后续分片大小)
分片数量 = 1 + 额外分片数
8.7. 实现限制¶
- 分片数量绝对不能 (MUST NOT) 超过 255 (Frag Total 为 1 字节)。
- 可分片 UDP 数据包的最大大小:
- 实现中应该 (SHOULD) 使用饱和算术 (saturating arithmetic) 以防止下溢。
- 实现中必须 (MUST) 将额外的 QUIC 和 TLS 帧开销计算在内。
9. 安全注意事项 (Security Considerations)¶
9.1. 身份验证¶
身份验证机制依赖于 TLS 密钥材料导出器 [RFC5705]: - 提供与 TLS 会话绑定的双向认证。 - 防止跨不同 TLS 会话的重放攻击。 - 要求安全的密码存储和传输。
实现必须 (MUST): - 使用具有足够熵的强密码。 - 对身份验证尝试实施速率限制。 - 在身份验证失败后终止连接。
9.1.1. 0-RTT 与身份验证¶
会话恢复可能允许客户端在首个飞行中发送早期数据 (0-RTT)。然而 Authenticate 的 TOKEN 派生自 TLS 密钥材料导出器,而该导出器只有在 TLS 握手完成后才可用 (RFC 8446)。因此客户端无法在握手前计算令牌,也就无法将 Authenticate 命令作为早期数据发送。
启用 0-RTT (zero_rtt_handshake / reduce-rtt) 的实现:
- 可以 (MAY) 通过 0-RTT 恢复建立连接,但必须 (MUST) 等待握手完成后再发送 Authenticate。
- 必须 (MUST NOT) 在握手完成前尝试导出密钥材料;rustls 等后端会拒绝该操作,而发送 rustls 服务端尚无法派生的令牌会导致认证失败。
- 在 0.5-RTT 接受连接的服务端必须 (MUST) 在验证令牌前等待握手完成。
- 必须 (MUST NOT) 依赖 0-RTT 提供重放保护;早期数据本质上可被重放。
9.2. 加密¶
所有 TUIC 流量均由 QUIC 提供的底层 TLS 1.3 层进行加密: - 命令和载荷数据均受到保护,防止窃听。 - QUIC 提供了内置的防止篡改和重放的保护。
9.3. 拒绝服务 (DoS) 攻击¶
潜在的 DoS 攻击向量和缓解措施:
资源耗尽: - 限制每个连接的最大并发关联数。 - 对未完成的分片重组实施超时。 - 强制实施最大分片数量限制。
放大攻击: - UDP 中继功能可被用于放大攻击。 - 服务端应该 (SHOULD) 对 UDP 转发实施速率限制。 - 服务端可以 (MAY) 限制目标地址以防止滥用。
9.4. 隐私注意事项¶
- 目标地址在 QUIC 连接内被加密。
- 尽管经过加密,但流量分析仍可能泄露连接模式。
- 实现应该 (SHOULD) 考虑流量填充以抵抗分析。
10. 参考资料 (References)¶
10.1. 规范性引用文件 (Normative References)¶
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC4122] Leach, P., Mealling, M., and R. Salz, "A Universally Unique Identifier (UUID) URN Namespace", RFC 4122, July 2005.
[RFC5705] Rescorla, E., "Keying Material Exporters for Transport Layer Security (TLS)", RFC 5705, March 2010.
[RFC9000] Iyengar, J., Ed., and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, May 2021.
10.2. 资料性引用文件 (Informative References)¶
[RFC9114] Bishop, M., Ed., "HTTP/3", RFC 9114, June 2022.
附录 A. 数据包编码示例 (Appendix A. Example Packet Encodings)¶
A.1. Authenticate 命令示例¶
Version: 0x05
Type: 0x00
UUID: 550e8400-e29b-41d4-a716-446655440000
TOKEN: [32 bytes of derived key material]
Hex 编码 (前 20 个字节):
05 00 55 0e 84 00 e2 9b 41 d4 a7 16 44 66 55 44
00 00 [32 字节 TOKEN...]
A.2. Connect 命令示例 (IPv4)¶
A.3. Packet 命令示例 (首个分片)¶
Version: 0x05
Type: 0x02
Association ID: 0x0001
Packet ID: 0x0042
Frag Total: 2
Frag ID: 0
Size: 1183
地址类型: 0x01 (IPv4)
地址: 203.0.113.1
端口: 53
Hex 编码 (仅标头):
05 02 00 01 00 42 02 00 04 9f 01 cb 00 71 01 00 35
[载荷随附在后...]
A.4. Packet 命令示例 (后续分片)¶
Version: 0x05
Type: 0x02
Association ID: 0x0001
Packet ID: 0x0042
Frag Total: 2
Frag ID: 1
Size: 500
地址类型: 0xFF (None)
Hex 编码 (仅标头):
05 02 00 01 00 42 02 01 01 f4 ff
[载荷随附在后...]
附录 B. 实现检查表 (Appendix B. Implementation Checklist)¶
实现者应该 (SHOULD) 验证其实现是否正确处理:
- [ ] 识别协议版本 0x05
- [ ] 所有五种命令类型 (Authenticate, Connect, Packet, Dissociate, Heartbeat)
- [ ] 所有四种地址类型 (Domain, IPv4, IPv6, None)
- [ ] 所有多字节字段使用大端字节序 (Big-endian)
- [ ] 用于身份验证的 TLS 密钥材料导出器
- [ ] 在双向流上进行的 TCP 中继
- [ ] 带有会话关联管理的 UDP 中继
- [ ] 超过 MTU 时生成分片
- [ ] 带有超时的分片重组
- [ ] 分片计数限制 (≤255)
- [ ] 正确的标头大小计算
- [ ] 防止下溢的饱和算术
- [ ] 认证验证及连接终止机制
- [ ] 资源限制和 DoS 攻击缓解