20、安全机制:DTLS加密、SRTP协议、证书管理
说到WebRTC的安全机制,我其实挺感慨的。早些年做即时通讯的时候,大家总觉得加密是“锦上添花”的东西。直到有一次,我在一个公开WiFi环境下调试自己的Demo,抓包一看——音频流赤裸裸地暴露在网络上,谁都能听。嗯,从那以后,我再也不敢轻视安全这层了。
WebRTC把安全写进了规范里,不是可选项,是强制项。说白了,它要求所有媒体流必须加密传输。今天我们就来聊聊这背后的三驾马车:DTLS、SRTP,还有证书管理。
20.1 为什么需要DTLS?
先问一个问题:WebRTC的信令走的是HTTP或WebSocket,但媒体流走的是UDP。UDP本身没有加密能力,那怎么保证媒体数据不被窃听?
答案就是DTLS——Datagram Transport Layer Security。你可以把它理解成“跑在UDP上的TLS”。
我刚开始接触时也觉得奇怪:为什么不用TLS?因为TLS依赖TCP的可靠传输,而WebRTC的媒体流是基于UDP的,延迟更低,但可能丢包。DTLS专门为这种场景设计,它能在不可靠的传输层上建立安全通道。
20.2 DTLS握手流程
DTLS握手和TLS握手很像,但有几个关键区别。我画了一张图,帮你理清流程:
注意看第二步的 HelloVerifyRequest。这是DTLS独有的机制,用来防止UDP层面的DDoS攻击。客户端必须先证明自己“愿意”通信,服务端才会继续握手。我在项目中遇到过有人试图用伪造IP打UDP洪水,DTLS这个cookie机制直接挡掉了。
20.3 SRTP:媒体流的加密保镖
DTLS握手完成后,双方有了共享密钥。但DTLS本身不适合加密大量媒体数据——开销太大。这时候SRTP上场了。
SRTP(Secure Real-time Transport Protocol)是RTP的加密版本。它用DTLS协商出的密钥,对音频和视频包进行加密。而且它支持 无状态加密,每个包独立加解密,丢包不影响后续包。
SRTP的加密流程大致如下:
- 密钥派生: 从DTLS握手得到的master key,派生出加密密钥、认证密钥、盐值。
- 包加密: 使用AES-CTR或AES-GCM对RTP payload加密。
- 消息认证: 添加HMAC标签,防止篡改。
- 序号保护: 使用ROC(Rollover Counter)防止重放攻击。
你想想看,一个音频包从麦克风采集到发送出去,经过编码、打包、加密、加认证,最后才扔到网络上。这中间任何一步出问题,对方听到的就是噪音。所以SRTP的稳定性非常关键。
20.4 证书管理:谁来证明你是谁?
DTLS握手需要证书。但WebRTC场景下,我们通常不使用CA签发的公网证书。为什么?因为WebRTC是点对点通信,两端都是“临时”的,没必要花几十块钱买个证书。
WebRTC的做法是:自签名证书。每个PeerConnection在建立时,内部会自动生成一个自签名的X.509证书。这个证书只用于本次会话,用完即弃。
具体流程是这样的:
- Alice生成自签名证书,计算其SHA-256指纹。
- Alice通过信令把指纹发给Bob。
- Bob收到Alice的DTLS握手消息,拿到证书,计算指纹。
- Bob对比两个指纹,一致则握手继续。
我曾经在调试一个跨平台项目时,发现Android和iOS之间始终连不上。查了半天,原来是Android端生成的证书指纹是SHA-1,而iOS端只接受SHA-256。嗯,后来统一改成SHA-256就解决了。
20.5 证书指纹的传递
指纹通常放在SDP的 a=fingerprint 属性中。举个例子:
a=fingerprint:sha-256 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB:9B:6B:1B:3A:64:BD:B1:6C:3A:2C:0C:8C
注意,指纹必须通过信令通道安全传递。如果信令被篡改,攻击者可以替换指纹,从而实施中间人攻击。所以信令通道本身也需要加密——通常用HTTPS或WSS。
20.6 证书的生命周期
每个RTCPeerConnection对象都有自己的证书。但你可以选择复用证书:
// 生成一个证书,供多个连接复用
RTCPeerConnection.generateCertificate({
name: 'ECDSA',
namedCurve: 'P-256'
}).then(function(cert) {
const config = {
iceServers: [...],
certificates: [cert]
};
const pc = new RTCPeerConnection(config);
});
复用证书的好处是减少握手开销。但要注意,证书有有效期,默认是30天。如果连接持续超过30天,需要重新协商。
我个人习惯在移动端使用ECDSA证书,因为它比RSA证书小,握手更快。移动端CPU资源有限,能省一点是一点。
20.7 常见问题与避坑
最后分享几个我踩过的坑:
- 证书指纹不匹配: 检查两端是否使用相同的哈希算法。SHA-256是标准,别用SHA-1。
- DTLS握手超时: UDP丢包严重时,DTLS握手可能失败。建议在ICE连接稳定后再触发DTLS。
- SRTP解密失败: 确认密钥派生参数一致。特别是SSRC和ROC的同步。
- 证书过期: 长时间运行的连接要处理证书过期事件,触发重新协商。
chrome://webrtc-internals 中,可以看到DTLS和SRTP的状态。如果看到 DTLS: Failed,先检查证书指纹。
安全机制是WebRTC的基石。DTLS负责握手和密钥协商,SRTP负责媒体加密,证书管理确保身份可信。三者配合,才能保证你的音视频通话不被窃听、不被篡改。
下次调试时如果遇到加密相关的问题,记得先检查这三个环节。嗯,安全无小事,尤其是做实时通信。