作者|泰一
审校|进学、莫战
前言最近在做 J 和 G 这两套 RTC 系统的 DTLS-SRTP 握手加密工作,要求使用 CA 机构颁发的证书。在本机调试的过程中发现:G 系统使用 CA 证书,DTLS 握手成功,而 J 系统则握手失败。
经过几番调试与分析,定位到了原因:J 系统相较于 G 系统多了一个 TURN 转发模块,该模块设置的接收缓冲区的上限值为 1600 字节,而 CA 证书的大小则有近 3000 字节,因此 TURN 模块转发给客户端的证书不完整,导致 DTLS 握手失败。
大家都知道, WebRTC 的 DTLS 使用的是自签名的证书,这个证书一般不会太大,如下图所示,只有 286 字节。
然而,如果要使用 CA 颁发的证书,那么这个证书可能会很大,如下图所示,竟达到了 2772 字节,显然超出了 TURN 模块的接收缓冲区的大小。
上图中,你可能注意到了这个 CA 证书被分成了两片(two fragments),这其实是 DTLS 协议层做的。不过值得思考的是,CA 证书的每一片的大小都未超出 TURN 模块接收缓冲区的 1600 字节的限制,但是为什么 J 系统的 TURN 转发模块依然会接收失败呢?
这是因为证书虽然被分片,但是在发送到 TURN 模块时并没有按照分片独立发送,仍然是全部打包到了同一个 UDP 数据报中进行发送,所以接收肯定会失败。
下面,我们将一起了解下 DTLS Fragment 的机制。首先要理清几个概念。
Message、Record、FlightDTLS 协议分为两层:底层的 record protocol 和上层的 handshake protocol、change cipher spec protocol、alert protocol 以及 application data protocol。
Remark:握手协议、密码规格变更协议、警告协议、应用数据协议均在 DTLS 记录协议的上层,这四种协议统称为 DTLS 握手协议。
Note:关于记录和握手这两层协议各自的作用,这里就不再赘述,可以参考: 详解 WebRTC 传输安全机制:一文读懂 DTLS 协议。
DTLS Message 是一条 完整的 DTLS 消息。比如握手消息:Client Hello、Certificate、Client Key Exchange 等;比如密码规格变更消息:Change Cipher Spec。
DTLS Record 是记录层(Record Layer)的概念,可以认为它是一个壳子,里面装载着 DTLS Message,如下图:
Message 和 Record 是一对一或者一对多的关系。也就是说,一个 Record 不一定装了一条完整的 Message。因为有可能是多个 Record 组成一个完整的 Message。
如果 Message 很小,未超过 MTU 的限制,那么一个 Record 足以装下一条 Message;如果 Message 很大,超过 MTU 的限制,那么就需要多个 Record 来装这条 Message。即这条 DTLS Message 会被分割为多个 Fragment,然后分别装入多个 Record。
Remark:最大传输单元(Maximum transmission Unit, MTU)是数据链路层的概念,MTU 限制的是数据链路层的 payload 大小,也就是其上层协议的大小,比如 IP、ICMP。在以太网中,链路层的 MTU 是 1500 字节。
比如,Certificate 这个握手消息,证书大小很容易就超过 MTU 的限制,那么这个消息就会被分割为多个 Fragment 并被分别存放到多个 DTLS Record,每个 Fragment 的大小要保证不超过 MTU 的限制(PS:导读的第二张图就是一个实际的例子)。
Flight 中文解释为 “航班” 或者 “航程”,是一个或者一组打包好的 Message,这组 Message 属于同一个 “航程”,视为一个整体,通过单个 UDP 数据报发送。
如上图所示,本次 DTLS 握手一共有 4 个 Flight。Flight2 是 Server Hello、Certificate、Server Hello Done 这三条 Message 的组合,其中 Certificate 这条 Message 被分割为两个 Fragment,装到两个 Record 中。Flight2 通过大小为 2969 字节的 UDP 数据报发送出去。
Remark:Flight2 这个 2969 字节的 UDP 包是在本机环境下调试、抓包得到的,并不代表 MTU 有这么大,在实际的网络中,不会出现这种远超 MTU 限制的数据包。
到这里,关于 Message、Record、Flight 的概念就讲完了,三者之间的关如下图:
下面我们谈谈,DTLS 为什么要对 DTLS Message 做分片。
我们知道,受以太网 MTU 影响,UDP 数据报最大为 1500 字节,超出这个限制就会被 IP 层分片(PS:以太网 MTU 设置为 1500 字节是为了最大化信道传输利用率)。
但是如果 IP 层分片机制被禁止呢?这就会导致大于 1500 字节的 UDP 数据报在 IP 层被丢弃。因此,DTLS 要对消息做分片,来满足 IP 层对报文大小的要求。DTLS1.2: Message Size 这一节解释了这个原因。
By contrast, UDP datagrams are often limited to
- 【限时领奖】消息队列MNS训练营重磅来袭,边学习充电,边领充电宝~
- 「开源人说」第二期重磅上线!一起走进《从开源中来,到开源中去》
- 阿里云ES全观测引擎TimeStream时序增强功能重磅发布,助力时序场景实现最佳实践
- 免费下载! 冬季实战营第三期:MySQL数据库进阶实战
- 独家下载|《阿里云MaxCompute百问百答》 解锁SaaS模式云数据仓库尽在本电子手册!
- 开发者评测局第六期——ModelScope开源模型社区评测征集令
- CIKM 2022 AnalytiCup Competition: 联邦异质任务学习
- 阿里大淘系模型治理阶段性分享
- 投稿有礼,双社区签约博主名额等你赢!
- 阿里本地生活全域日志平台 Xlog 的思考与实践


微信扫码登录