WebRTC作为浏览器中的一个组件,在设计的时候考虑了大量了安全问题,比如要求getUserMedia在加密网页中才能打开摄像头, 使用MDNS来防止IP地址的泄露, 使用DTLS来加密datachannel数据,使用DTLS-SRTP来加密音视频数据等等,在带来更高的安全性的同时也带来更多的复杂性,更多的资源占用。尤其是对于开发者来说,DTLS-SRTP的引入带来很多问题,工程的复杂性,服务器资源的占用,以及音视频建立连接的延迟等,我们使用SDES来减少DTLS带来的影响,在保证兼容WebRTC协议的同时减少系统的复杂度,降低弱网下的首帧延迟。
DTLS是怎么工作的
DTLS 是指 Datagram Transport Level Security,即数据报安全协议,提供了UDP 传输场景下的安全解决方案,能防止消息被窃听、篡改、身份冒充等问题。DTLS更详细的介绍不在本文范围之类,可以查看更具体的RFC文档,我们重点看一下DTLS 握手流程:
大家可以看到,在DTLS交互过程中,要交互好几次,每交互一次要消耗掉一个RTT, 考虑掉UDP的不可靠性,在弱网情况下丢包超时重传,我们在测试50%的丢包环境下出现过DTLS 握手要消耗2-3秒的情况,这样的延迟在实时系统中是不可忍受的。
DTLS带来的另一个比较严重的问题是连接迁移, 如果发生端和服务端断开要进行重连,因为每个连接都要进行DTLS握手,是没法做到实时的媒体重连的,对WebRTC的大规模部署部署带来很多复杂性。
DTLS在WebRTC中的使用
这个图是DTLS在WebRTC网络协议栈中的位置,需要注意的是DTLS绿色部分并没有完全贯穿在ICE和SRTP/SCTP之间,这是为什么呢?
在WeRTC中使用DTLS的地方包括两部分, 一是Datachannel 数据通道,一个是音视频媒体通道。 在Datachannel数据通道中,WebRTC完全使用DTLS来进行协商和加解密,在音视频通道中WebRTC使用SRTP来进行数据的加解密,DTLS的作用仅仅是用来做密钥交换,密钥交换完就没有DTLS什么事情了,RTP/RTCP的数据加解密就交给了SRTP.
所以常说的WebRTC使用DTLS来进行加解密是不严谨的,DTLS只是用来做密钥交换。
使用SDES来代替DTLS协商
既然DTLS在WebRTC音视频传输过程中只是用来做密钥交换,那有没有其他的密钥交换方式呢? 实际上WebRTC本身也支持通过SDES的方式来交换密钥。
简单来说是把密钥交换过程中所需要的信息放入SDP中通过信令来交换,这样WebRTC和服务端在简历ICE连接之后就可以直接传输加密后的数据,而不再需要DTLS握手。
使用SDES的方式来握手的时候offer和answer的SDP中会有
'a=crypto:'
使用DTLS的方式来握手的时候SDP中会有:
'a=fingerprint:'
带来的好处
1, 更低的首帧延迟
因为不需要DTLS握手,带来的首帧延迟降低是很显著的。尤其是在弱网环境下。
2,更低的实现复杂度
服务端可以不再实现DTLS逻辑,实现的复杂度降低了不少。
3,连接迁移
因为不在需要DTLS握手,可以更容易做多服务器的连接迁移。
还有什么问题?
1,浏览器支持不好
要使用SDES的方式来协商,native端的代码并不需要修改就可以支持。老版本的WebRTC有DtlsSrtpKeyAgreement可以关闭DTLS,不确定新版本还支持这个参数。
2,数据保密性的要求
使用SDES的方式,因为你的密钥相关的信息可以通过SDP拿到,会有一定的安全隐患。但不是所有的场景都需要这个高的安全等级, CDN系统大部分都没有对数据进行加密也在全世界跑,大部门场景下音视频数据内容不加密也没有问题。