DTLS 数据报传输层安全协议:UDP 环境下的安全通信原理与实现
概述
传输层安全协议(TLS)是互联网安全通信的基石。标准 TLS 建立在 TCP 之上,依赖 TCP 提供的可靠传输特性:数据按序到达、自动重传、流量控制与拥塞控制。然而,在 UDP 环境下,这些特性不复存在:数据包可能丢失、乱序到达、或重复发送。
数据报传输层安全协议(Datagram Transport Layer Security, DTLS)正是为解决这一问题而设计的协议。DTLS 保持了 TLS 的安全语义,同时在不可靠传输之上建立了安全通道。理解 DTLS,不仅是理解 WebRTC、OpenVPN、TLS over QUIC 等现代系统的安全基础,也是评估物联网(IoT)和实时通信安全性的关键。
DTLS 的核心设计挑战在于:在不假定可靠传输的前提下,实现与 TLS 同等级别的机密性、完整性和身份认证,同时应对 DTLS 特有的数据包丢失和放大攻击风险。本文将从 DTLS 1.2(RFC 6347)和 DTLS 1.3(RFC 9147)两个版本出发,深入剖析协议设计与工程实践。
DTLS 的设计原则
DTLS 的设计哲学是「对 TLS 改动最小化」。它复用 TLS 的握手协议和密码套件定义,在此基础上仅增加最小化的机制以适应 UDP 传输。
与 TLS 的核心区别
DTLS 相对于 TLS 进行了以下结构性调整:
| 特性 | TLS (TCP) | DTLS (UDP) |
|---|---|---|
| 传输层 | 有序、可靠 | 不可靠、无顺序保证 |
| 握手消息 | 通过 TCP 流隐式排序 | 显式序列号排序 |
| 数据完整性 | TCP 保证丢失包会被重传 | 需 DTLS 自行处理丢失和重传 |
| 防 DoS 攻击 | SYN Cookie(TCP 层) | DTLS Cookie(协议层) |
| 记录格式 | Length + Payload | Epoch + Sequence Number + Length + Payload |
| 握手消息 | 不限制大小 | 必须支持分段和重组 |
- 序列号可见化:TLS 中序号隐含在 TCP 字节流中;DTLS 需要在每条记录中显式携带序列号,用于消息排序和重放检测。
- 握手消息分段:TLS 握手消息可能超过 TCP 段大小;UDP 通常受 MTU 限制(通常 1500 字节,扣除 IP/UDP 头部后约 ~1400 字节),DTLS 握手消息必须支持显式分段和重组。
- 状态机重传:DTLS 需要建立状态机来跟踪发送的消息并在超时后重传。
- DoS 防护:UDP 无连接特性使得源 IP 欺骗更容易,DTLS 采用 Cookie 握手机制防止无状态资源消耗。
DTLS 1.2 协议详解(RFC 6347,2012)
DTLS 1.2 在 TLS 1.2 的基础上添加了上述机制,是当前部署最广泛的版本。
记录协议
DTLS 记录协议在 TLS 记录协议的基础上,在记录头部插入了两个新字段:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 类型 | 版本 | Epoch | 序列号(16 位) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序列号(续,16 位) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 长度 | |
+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 密文载荷 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段含义:
- 类型(Type):20(ChangeCipherSpec)、21(Alert)、22(Handshake)、23(Application Data)
- 版本(Version):DTLS 1.2 对应
{254, 253}(回退表示法,避免与 TLS 混淆) - Epoch(时代):每次密钥更新(KeyUpdate)或握手完成后递增,用于隔离不同密钥的代
- 序列号(Sequence Number):64 位,由 Epoch(高 16 位)和 Record Sequence Number(低 48 位)组成,用于重放检测和消息排序
- 长度(Length):载荷长度(不包含头部)
握手机制(Handshake Protocol)
DTLS 1.2 的握手流程在 TLS 1.2 的基础上增加了两个关键阶段:
客户端 服务器
| |
| --- ClientHello --> |
| |
| HelloVerifyRequest (含 Cookie) |
| <-- 无状态,不分配资源 |
| |
| --- ClientHello (含 Cookie) --> |
| |
| ServerHello |
| Certificate |
| ServerKeyExchange |
| CertificateRequest |
| ServerHelloDone |
| <-- |
| |
| --- Certificate (可选) --> |
| --- ClientKeyExchange --> |
| --- CertificateVerify --> |
| --- ChangeCipherSpec --> |
| --- Finished --> |
| |
| ChangeCipherSpec |
| Finished |
| <-- |
| |与 TLS 1.2 的三个关键差异:
#### 1. HelloVerifyRequest 防 DoS 攻击
TLS 1.2 握手中,服务器在收到 ClientHello 后就开始分配状态(随机数、Diffie-Managed 参数等)。在 UDP 源 IP 可伪造的环境下,攻击者可以发起海量 ClientHello 请求,迫使服务器不断分配内存和计算资源。
DTLS 的解决方案是:无状态 Cookie 交换:
- 客户端发送 ClientHello(无 Cookie)
- 服务器不立即分配状态,而是生成一个 Stateless Cookie(包含客户端 IP、端口和时间的 HMAC 签名),通过 HelloVerifyRequest 发回
- 客户端重新发送 ClientHello,携带此前收到的 Cookie
- 服务器验证 Cookie 有效性后,才真正开始握手流程
#### 2. 握手消息的分段
UDP 要求单个数据报尽量不超过 MTU(通常 1400 字节,保守值 - DTLS 规范建议初始使用 1024 字节)。TLS 握手消息(如 CertificateServer 证书链)可能远超此限制。
DTLS 握手消息引入了分段字段:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 握手类型 | 消息长度(24 位) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 分片偏移(24 位) | 分片长度 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 分片载荷 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+消息长度:整个握手消息的完整长度(含所有分片的数据)分片偏移:当前分片在完整消息中的零起偏移量分片长度:当前分片的长度
#### 3. 重传定时器
与 TLS 依赖 TCP 自动重传不同,DTLS 必须在超时后主动重传。DTLS 定义了指数退避重传策略:
- 初始重传超时:1 秒(RFC 6347 建议值)
- 每次超时后,将超时时间翻倍
- 当达到最大重传超时(默认 60 秒)后,持续使用最大值
- 收到对端消息后,重置定时器到初始状态
密钥调度
DTLS 复用 TLS 1.2 的密钥调度:
- Premaster Secret → Master Secret → Key Block
- Key Block 派生:Client Write MAC Key、Server Write MAC Key、Client Write IV、Server Write IV
ChangeCipherSpec 协议
DTLS 保留 TLS 的 ChangeCipherSpec 协议(独立消息类型 20),但需要注意:
- 在 DTLS 中,ChangeCipherSpec 的发送和接收不受握手消息分段的限制
- Future Epoch(下一个加密代)的密钥消息必须在当前条记录层安全队列中进行原子交换
DTLS 1.3 协议详解(RFC 9147,2022)
DTLS 1.3 基于 TLS 1.3 协议构建,借鉴了 TLS 1.3 的简化设计哲学,同时保留了 DTLS 特有的 UDP 适配机制。
主要改进
#### 1. 更紧凑的握手与重试机制
DTLS 1.2 的 HelloVerifyRequest 是一个独立的协议消息。DTLS 1.3 将其整合到 ServerHello 消息中:
客户端 服务器
| |
| --- ClientHello (无 Cookie) --> |
| HelloRetryRequest |
| (= ServerHello + Cookie extension) |
| <-- |
| |
| --- ClientHello (含 Cookie) --> |
| ServerHello |
| {EncryptedExtensions} |
| {Certificate} |
| {CertificateVerify} |
| {Finished} |
| <-- |
| |
| --- {Finished} --> |HelloRetryRequest 本质上是 TLS 1.3 的 HelloRetryRequest 扩展,内嵌了 Cookie extension。这减少了了一次消息往返,也简化了状态机设计。
#### 2. 序列号与 Epoch 设计
DTLS 1.3 不再区分握手阶段(handshake epoch)和应用数据阶段(application epoch)。每条记录都携带独立的 64 位序列号。加密 nonce 由序列号与固定的 IV 写入密钥(write_iv)异或生成(类似 TLS 1.3 的方式)。
序列号规则:
- 对每个写入密钥(写保护):从 0 开始逐记录递增
- 达到序列号最大值后,必须触发密钥更新(KeyUpdate)
- 序列号低于预期值的数据包被丢弃(提供隐式重放保护)
DTLS 1.3 握手完成后,双方保护性地计算 verify_data 并包含在 Finished 消息中。verify_data 包含完整的 ClientHello(含 extensions 如 supported_versions),防止了中间人篡改协商的协议版本。
#### 4. 0-RTT 数据
DTLS 1.3 支持 0-RTT(Zero Round Trip Time)数据发送:
- 客户端在首次握手后,从 Early Data extension 获得 PSK(预共享密钥)
- 下次连接时,客户端在 ClientHello 中将 PSK 和 0-RTT 数据一起发送
- 服务器选择接受或拒绝 0-RTT 数据,回退到 1-RTT 握手
DTLS 1.3 密钥调度
DTLS 1.3 的密钥调度完全遵循 TLS 1.3 的 TLS 1.3 Key Schedule:
0
|
HKDF-Extract = Early Secret
|
+----------+----------+
| |
Derive-Secret Derive-Secret
("ext binder" / ("res master",
"res binder") ...)
| |
PSK -> binder_key master_secret
| |
+----------+----------+
|
Derive-Script(handshake, ...)
|
handshake_traffic_*
|
Derive-Script(application, ...)
|
application_traffic_*与 TLS 1.3 不同之处在于:
- 密钥派生完成后,需要计算
client_handshake_traffic_secret和server_handshake_traffic_secret以保护加密的握手消息 - 握手完成后使用
client_application_traffic_secret和server_application_traffic_secret保护应用数据 - 握手阶段的 Finished 消息使用握手阶段密钥加密,而非应用阶段密钥
DTLS 密钥派生细节
DTLS 1.3 的加密套件定义与 TLS 1.3 保持一致:
| TLS 1.3 密码套件 | 密钥交换 | 认证 | 加密 | 哈希 |
|---|---|---|---|---|
| TLS_AES_128_GCM_SHA256 | ECDSA/Ed25519 | ECDSA/Ed25519 | AES-128-GCM | SHA-256 |
| TLS_AES_256_GCM_SHA384 | ECDSA/Ed25519 | ECDSA/Ed25519 | AES-256-GCM | SHA-384 |
| TLS_CHACHA20_POLY1305_SHA256 | ECDSA/Ed25519 | ECDSA/Ed25519 | ChaCha20-Poly1305 | SHA-256 |
DTLS 的应用场景
WebRTC
WebRTC(Web Real-Time Communication)是 DTLS 最广泛应用的场景。在 WebRTC 中:
- 媒体流通过 DTLS-SRTP(SRTP Protection via DTLS)协议保护
- DTLS 握手在 ICE(Interactive Connectivity Establishment)建立连接后进行
- 握手成功后,DTLS 派生 SRTP 密钥材料,后续媒体数据使用 SRTP/SRTCP 传输
- 支持 P2P 通信,无需服务器中转加密密钥
- 广泛用于视频会议(如 Google Meet、Microsoft Teams、Zoom Peer-to-Peer)、语音通话和实时文件传输
- ICE STUN 绑定请求建立 NAT 穿透后的 UDP 连接
- DTLS 握手(同时发送 ClientHello 或通过 STUN 的 parallel check)
- SRTP 密钥导出:
DTLS-SRTP Key Derivation(RFC 5764) - 媒体流加密传输(AES-128-CM-HMAC-SHA1-80 或 AES-256-CM-HMAC-SHA1-80)
OpenVPN
OpenVPN 默认使用 UDP 模式。它利用 DTLS 建立隧道密钥:
- 使用
--tls-auth和--tls-crypt选项提供额外的 HMAC 认证层 - 数据信道(data channel)使用协商的对称密钥加密
- 支持密钥重协商(renegotiation)以刷新会话密钥
- 支持用户名/密码证书的多因素认证
QUIC / HTTP3
QUIC(RFC 9000)虽然不直接使用 DTLS,但复用了 TLS 1.3 握手协议:
- QUIC 集成 TLS 1.3 用于加密握手
- QUIC 使用 DTLS 类似的思路处理丢包和重序(自建可靠传输层)
- HTTP/3 依赖 QUIC 提供 HTTPS 级别的安全保障
物联网与受限环境
DTLS 是物联网安全协议的核心组件:
- DTLS-PSK(预共享密钥):适用于受限设备,无需证书握手,减少计算和带宽开销
- CoAP over DTLS:RFC 7252 定义的应用层协议结合 DTLS,适用于低功耗有损网络(LLN)
- OSCORE(Object Security for Constrained RESTful Environments):RFC 8613 提供应用层安全,绕过 DTLS 逐跳加密的中间节点信任问题
- DTLS 记录头相比 TLS 约增加 8 字节(epoch + sequence number + explicit IV)
- 在 IPv6 / UDP 环境下,MTU 限制对短消息的影响需要考虑
安全分析与已知攻击
DoS 放大攻击(Amplification Attack)
攻击者伪造受害者的 IP 地址向 DTLS 服务器发送 ClientHello,服务器随后发送大得多的 ServerHello + Certificate + ServerKeyExchange 消息给受害者。由于证书消息通常远大于 ClientHello(放大因子可达 20-50 倍),攻击者可以以少量带宽消耗目标服务器的计算和网络资源。
防护措施:
- HelloVerifyRequest(1.2)/ HelloRetryRequest(1.3)的 Cookie 机制:最直接的防护
- 初始连接速率限制(Rate Limiting)
- MTU 限制:初始 ClientHello ≤ MTU(约 1400 字节),Certificate 链长度受限
重放攻击
冒落者捕获并重放此前发送的 handshake 消息或 application data 消息。
DTLS 的防护机制:
- 序列号检查:每条记录携带的序列号,接收方维护一个滑动窗口(类似 IPsec ESP 的 replay window),检测并丢弃重复序列号
- Finished 消息验证:包含整个握手消息的 HMAC 验证,防止握手消息插入
- Epoch 边界隔离:密钥更新后,新记录的 Epoch 加 1,防止跨 Epoch 重放
分片攻击
攻击者构造恶意分片以绕过检测:
- 微小分片攻击:将握手消息分成极小的段,迫使目标分配大量内存存储不完整的分片
- 重叠分片攻击:发送偏移量重叠的分片,目标重组行为因操作系统而异
- 分片超时:收到一个分片后,设定超时(默认 60 秒),超时后丢弃所有部分分片
- 分片内存限制:单个握手消息的所有分片占用内存上限
- 重叠检测:同一偏移量只保留最新收到的分片
密码套件降级
攻击者篡改 ClientHello 中的 cipher_suites 列表,迫使双方使用较弱的密码套件。
DTLS 1.3 的 Finished 消息验证机制完全阻止了此类攻击。DTLS 1.2 依赖于 MAC 验证(包含在 CertificateVerify 和 Finished 消息中),但如果客户端不验证服务器的签名权限,中间人仍可能进行降级攻击。
最佳实践:
- 服务器配置优先选择 AEAD 密码套件(如 AES-GCM、ChaCha20-Pylult)
- 禁用 CBC 模式和 RC4 等已知脆弱的密码套件
- 客户端和服务器的密码套件列表使用 ACL(访问控制列表)集中管理
DTLS 1.2 vs DTLS 1.3:设计演进
| 维度 | DTLS 1.2(RFC 6347) | DTLS 1.3(RFC 9147) |
|---|---|---|
| 基础 TLS 版本 | TLS 1.2 | TLS 1.3 |
| 握手消息分片 | 显式 divide 字段 | 类似,但更简化 |
| 防 DoS | 独立 HelloVerifyRequest | 集成到 HelloRetryRequest |
| 最少往返数 | 3 次(含 Cookie) | 2 次(1-RTT) |
| 握手消息加密 | 仅 Finished 后握手密钥加密 | 服务端握手消息加密 |
| 重传策略 | 指数退避,固定上限 | 指数退避,PLPMTUD-aware |
| 0-RTT 数据 | 不支持 | 支持(需 PSK resume) |
| 序列号空间 | 48 位(2 个 24 位段) | 64 位统一空间 |
| 密钥派生 | TLS 1.2 PRF | TLS 1.3 HKDF-Expand-Label |
| 安全握手 | 可选签名 + 证书验证 | 强制服务器认证(+ PSK 可选) |
| 最大明文记录 | 2^14 bytes | 2^14 bytes |
DTLS 工程实践建议
1. MTU 与分片策略
DTLS 手持设备或卫星链路场景下,MTU 可能远小于 1500 字节。建议:
- 初始握手消息分片大小不超过 1024 字节(保守值,适应 IPv6 路径)
- 支持 Path MTU Discovery(PMTUD)以避免 IP 层分片
- Certificate 链尽可能使用较短的证书层级(Root CA → Server,而非 Root → Intermediate → Server)
2. 证书验证与指纹
在 WebRTC 场景中,DTLS 证书指纹(fingerprint)通过 SDP(Session Description Protocol)传递,用于 DTLS 握手时服务器身份验证:
a=fingerprint:sha-256 AB:CD:EF:...这种模式绕过了传统的 PKI 信任链验证,适用于 P2P 通信场景。但需要确保 SDP 交换通道本身的安全(如通过 HTTPS 获取 SDP)。
3. 密钥更新(KeyUpdate)
DTLS 支持按需密钥更新(KeyUpdate 握手协议),通常在以下时机触发:
- 加密数据量达到阈值(如 AES-GCM 的 2^64 字节上限前)
- 序列号空间耗尽前
- 定期刷新以限制密钥泄露的影响
4. 与 QUIC 的选择
对于新项目,评估安全传输协议时:
- 需要 P2P 通信或已使用 UDP 选 → DTLS
- 需要集成 HTTP 语义 → QUIC(TLS 1.3 over QUIC)
- 需要兼容性(现有 UDP 基础设施) → DTLS 1.2 + 向前兼容
总结
DTLS 协议通过在 TLS 之上叠加序列号、重传、分段和 Cookie 等机制,成功将安全通信扩展到 UDP 传输环境。DTLS 1.2 提供了成熟稳定的安全通信基础,DTLS 1.3 则通过协议简化进一步提升了性能和安全性。
理解 DTLS,对于构建 WebRTC 实时通信、OpenVPN 安全隧道、以及受限环境下的物联网安全通信都具有核心价值。随着 5G 和物联网的发展,DTLS 作为 UDP 安全传输标准的地位将更加稳固。
参考来源
- RFC 6347 - Datagram Transport Layer Security Version 1.2(2012 年 1 月)
- RFC 9147 - The Datagram Transport Layer Security (DTLS) Version 1.3 Protocol(2022 年 4 月)
- RFC 5764 - DTLS-SRTP(SRTP 密钥管理)
- RFC 9146 - DTLS Connection ID(连接标识)
- RFC 3711 - The Secure Real-time Transport Protocol (SRTP)
- W3C WebRTC 1.0(浏览器实时通信标准)
相关实践
- 国密 TLS 协议详解(GM/T 0024 与 RFC 8998) — 国密 TLCP 协议及其在 TLS 框架内的应用
- OCSP 与 CRL 证书吊销验证 — DTLS 握手后证书状态验证机制