WebRTC 的安全机制:DTLS-SRTP加密、证书指纹验证、安全最佳实践
聊到WebRTC,很多人第一反应是“实时通信”、“P2P”、“低延迟”。但有个问题常被忽略——你的音视频数据在传输过程中安全吗?
我刚开始接触WebRTC时,也天真地以为“反正数据走的是UDP,别人抓包也看不懂”。后来在一次内部测试中,我用Wireshark抓了自己的通话包,发现RTP数据几乎是明文……那一刻我意识到,没有加密的实时通信,就像在明信片上写情书。
WebRTC在设计之初就把安全放在了首位。它强制使用加密,不允许任何“明文模式”。今天我们就来拆解它的安全体系:DTLS-SRTP加密、证书指纹验证,以及一些我踩过的坑。
1. DTLS-SRTP:音视频数据的“防弹衣”
先问一个问题:SRTP(安全实时传输协议)本身是支持加密的,为什么还要引入DTLS?
答案很简单——密钥交换。SRTP虽然能加密,但它不负责“怎么把密钥安全地告诉对方”。传统做法是用SIP信令带一个密钥,但信令本身可能被劫持。WebRTC的做法是:用DTLS(基于UDP的TLS)来完成密钥协商,然后派生密钥给SRTP使用。
这个过程叫DTLS-SRTP。说白了,就是先握个手,确认对方身份,再悄悄把钥匙递过去。
核心流程:
- 双方通过信令交换DTLS指纹(后面会细讲)
- 建立DTLS连接,完成双向认证
- 从DTLS会话中派生SRTP密钥
- 后续音视频数据全部走SRTP加密通道
我在项目中遇到过一个问题:某次升级后,部分Android设备无法通话。排查了半天,发现是DTLS握手超时。原因是这些设备的老版本OpenSSL不支持某些密码套件。嗯,从那以后我养成了一个习惯——在SDP中显式指定密码套件。
2. 证书指纹验证:防止中间人攻击
DTLS握手时,双方会出示证书。但WebRTC不使用传统的CA证书链验证,而是用指纹(fingerprint)。
为什么?因为WebRTC是P2P场景,没有中央CA给你签发证书。每个Peer都自己生成一个自签名证书,然后把证书的哈希值(指纹)通过信令通道告诉对方。对方收到DTLS连接中的证书后,计算其指纹,与信令中收到的比对。一致,则通过;不一致,则拒绝。
你想想看,如果中间人想篡改数据,他必须伪造证书,但指纹已经在信令中约定好了,他改不了。这就构成了一个带外验证的安全闭环。
我个人习惯:在信令服务器端对指纹做一次持久化缓存。这样即使客户端重连,也能快速比对,避免重复握手带来的延迟。
这里有个细节要注意:指纹算法通常是SHA-256。在SDP中长这样:
a=fingerprint:sha-256 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB:4B:6B:BF:1E:7E:DB:04:42:03:58:B0:3F
我曾经见过有人把指纹写错一位,结果两边指纹对不上,连接一直失败。排查了整整两个小时……所以,指纹字符串一定要做严格的格式校验。
3. 安全最佳实践:我踩过的坑和总结
理论说完了,来点实战经验。下面这几条是我在多个项目中沉淀下来的,每一条都对应过线上事故。
3.1 强制使用DTLS 1.2以上版本
DTLS 1.0基于TLS 1.1,存在已知漏洞。WebRTC规范要求至少DTLS 1.2。但有些老旧的库默认还是1.0。我建议在代码中显式设置:
// 在PeerConnection配置中
const config = {
sdpSemantics: 'unified-plan',
iceTransportPolicy: 'relay', // 强制走TURN时更安全
// 注意:DTLS版本由底层库控制,但可以通过SDP协商限制
};
// 在SDP中检查是否有"DTLS 1.0"字样,如果有,拒绝连接
3.2 不要信任任何未验证的ICE候选者
ICE候选者中可能包含恶意构造的地址。我见过一个案例:攻击者伪造了一个TURN候选者,诱导对方将流量发到恶意服务器。解决方案是对ICE候选者做白名单过滤,只允许已知的STUN/TURN服务器地址。
3.3 定期轮换证书
自签名证书虽然没有过期时间,但长期使用同一个证书会增加泄露风险。我建议每次会话都生成新的证书。在浏览器中,可以通过RTCPeerConnection.generateCertificate()来生成:
// 生成新的ECDSA证书
const cert = await RTCPeerConnection.generateCertificate({
name: 'ECDSA',
namedCurve: 'P-256'
});
const pc = new RTCPeerConnection({ certificates: [cert] });
这样做的好处是:即使某个会话的证书泄露,也不会影响其他会话。
3.4 信令通道本身也要加密
很多人只关注媒体通道的加密,却忘了信令通道。如果信令被篡改,攻击者可以替换指纹或SDP,从而绕过DTLS验证。所以,信令一定要走WSS(WebSocket Secure)或HTTPS。
警告:不要在生产环境中使用ws://或http://传递SDP。我曾经在客户现场见过这种配置,结果被安全扫描工具直接标记为高危漏洞。
4. 知识体系总览
下面这张图总结了WebRTC安全机制的核心逻辑。我把它画成了流程图,方便你理解各组件之间的关系。
5. 总结
WebRTC的安全机制不是可选项,而是强制要求。DTLS-SRTP保证了媒体数据的机密性,证书指纹验证防止了中间人攻击,而最佳实践则帮我们堵住那些容易被忽视的漏洞。
我个人觉得,安全这件事,做得再多也不为过。尤其是实时通信,一旦出问题,泄露的是用户的语音、视频、甚至身份信息。嗯,每次上线前,我都会把安全清单再过一遍——指纹对不对、DTLS版本够不够新、信令是不是加密的……
这些习惯,都是踩坑踩出来的。希望你不用踩同样的坑。