DTLS 握手 · 在 ICE 通路上建安全信道

DTLS 是「跑在 UDP 上的 TLS」。这一章读 g3doc/dtls_transport.md 与 dtls 源码:DtlsTransport 如何在 ICE 变 writable 后握手、怎么在同一条路上把 DTLS/SRTP/STUN 三种包多路复用区分开,以及握手产出的两样东西——SRTP 密钥材料与远端证书指纹。

作者 David更新于 第 27 篇(共 112 篇)

DTLS 握手 · 在 ICE 通路上建安全信道

安全总览说 DTLS 负责「协商密钥」。这一章看它具体怎么在刚打通的 ICE 通路上握手,建起安全信道。

DTLS = 跑在 UDP 上的 TLS

DTLS(Datagram TLS) 就是为不可靠数据报(UDP)改造过的 TLS。TLS 保护 HTTPS,但它假设底层是可靠有序的 TCP;而 WebRTC 的媒体走 UDP(为了低延迟),包会丢、会乱序。DTLS 在 TLS 基础上加了应对丢包 / 乱序的机制(重传、显式序号),让 TLS 的那套「握手 → 建立密钥 → 加密」能在 UDP 上跑。它给 WebRTC 的,正是 TLS 那套久经考验的安全。

握手时机:ICE 通了才开始

关键的时序,g3doc/dtls_transport.md 讲得很清楚:

The DTLS handshake happens after the ICE transport becomes writable and has found a valid pair.

DTLS 握手必须等 ICE 先打通一条路。 逻辑上顺理成章:握手也是要收发包的,得先有一条能通的 Connection(writable 且找到有效候选对),DTLS 的握手消息才有路可走。所以通话建立的顺序是:先 ICE 打通(第 2 部分),P2PTransportChannel SignalIceTransportStateChanged 通知「路通了」,DTLS 才在这条路上启动握手。握手本身跑在 ICE 选定的那条通路上——ICE 是 DTLS 的「承运人」。

DtlsTransport:握手的执行者

执行握手的是 DtlsTransport(W3C 的 RTCDtlsTransport 在 C++ 的落地)。它的结构(g3doc/dtls_transport.md):

  • DtlsTransport(pc/)—— 对外的包装,可注册 DtlsTransportObserverInterface 观察者,通过 DtlsTransportInformation 汇报状态(连接状态、远端证书、SRTP 套件)。
  • DtlsTransportInternal —— 接口,实现是 DtlsTransportInternalImpl(dtls/)。它通过底层的 ICE 传输收发网络包,并驱动 BoringSSL 完成握手的状态机。

握手完成后,DtlsTransport 的状态变为 connected,并携带两样至关重要的产出(下面详述)。

一条路上三种包:多路复用

这里有个精妙的工程细节。DTLS 握手、SRTP 媒体、STUN 探测——三种包全都跑在同一条 ICE 通路上(BUNDLE时更是所有媒体挤一条)。收到一个 UDP 包,怎么知道它是哪种?

靠包的第一个字节区分——这是 RFC 5764 定义的多路复用(demultiplexing)方案。 DtlsTransportInternalImpl 会「demultiplex DTLS packets and SRTP packets」(g3doc/dtls_transport.md):

  • 第一字节在某个范围 → STUN 包(连通性检查 / 保活),交给 ICE。
  • 第一字节在另一范围 → DTLS 包(握手消息),交给 DTLS。
  • 第一字节在再一个范围 → SRTP 包(加密媒体),解密后交给 RTP。

三种协议共用一个 UDP 端口、一条通路,靠首字节的取值范围岔开——既省了端口(呼应 BUNDLE 的节约哲学),又让 STUN 保活、DTLS 握手、SRTP 媒体能在同一条来之不易的路上和谐共处。这是 WebRTC「一条路承载一切」设计的又一处体现。

握手的两样产出

DTLS 握手成功,产出两样东西(g3doc/dtls_transport.md),它们是接下来两章的主题:

  1. 一套派生密钥(keying material) —— 用来给 SRTP 生成加密密钥(DTLS-SRTP)。
  2. 远端证书的指纹 —— 拿它和 SDP 里 a=fingerprint: 那行比对,确认「握手的对端,正是信令里说的那个人」——防中间人。
图表加载中…

小结与下一章

DTLS 是「跑在 UDP 上的 TLS」,给 WebRTC 提供久经考验的安全握手。它必须等 ICE 打通一条 writable 的路才开始,握手消息跑在这条 ICE 通路上。DtlsTransport / DtlsTransportInternalImpl 是执行者,驱动 BoringSSL。同一条路上,DTLS / SRTP / STUN 三种包靠首字节范围多路复用(RFC 5764)。握手产出两样:SRTP 密钥材料(下下章导出)和远端证书指纹(下一章用于防中间人)。

握手要用证书,而证书指纹是防中间人的关键。下一章看证书怎么生成、指纹怎么把 DTLS 安全和信令绑在一起。👉 证书与指纹。

参考资料

  • [1] libwebrtc 源码.g3doc/dtls_transport.md(握手时机、多路复用、DtlsTransport / DtlsTransportInternalImpl)。
  • [2] libwebrtc 源码.dtls/dtls_transport_internal_impl.h、api/dtls_transport_interface.h。
  • [3] IETF RFC 6347「DTLS 1.2」、RFC 5764「DTLS-SRTP 多路复用」。

本页目录