当前位置: 首页 > news >正文

WebRTC(十二):DTLS

在 WebRTC 中的作用

DTLS(Datagram Transport Layer Security)是 TLS 的 UDP 版本,在 WebRTC 中用于:

  • 安全协商加密密钥
  • 对等验证(基于 X.509 证书 + fingerprint)
  • 为 SRTP/SRTCP 提供密钥材料

WebRTC 不直接用 DTLS 传输音视频,而是通过它协商出密钥后,用于 SRTP/SRTCP 加密 RTP/RTCP 流。

与 SRTP 的关系

在 WebRTC 中,音视频数据加密流程如下:

[RTP/RTCP] ─► SRTP/SRTCP ─► UDP Socket▲Key 来源于 DTLS
  • DTLS:协商密钥(SDES 替代方案)
  • SRTP:使用 DTLS 派生出的密钥加密 RTP
  • SRTCP:同理用于 RTCP 加密

DTLS 本质上是提供 密钥协商、身份认证、消息完整性保护

握手流程详解

流程图

Client                  Server| ------ ClientHello ------> || <--- HelloVerifyRequest -- || ------ ClientHello ------> |  (带 cookie)| <-------- ServerHello -----|| <----- Certificate --------|| <- ServerKeyExchange (可选)| <- CertificateRequest (可选)| <---- ServerHelloDone -----|| ---- Certificate (可选) -->|| ---- ClientKeyExchange --> || ---- CertificateVerify --> || ---- ChangeCipherSpec -->  || ---- Finished -----------> || <--- ChangeCipherSpec ---- || <-------- Finished --------|

ClientHello(第一次)

客户端发起握手,发送:

  • 协议版本(如 DTLS 1.2)
  • 随机数(Random)
  • 支持的加密套件(cipher suites)
  • 会话 ID(Session ID)
  • 扩展(如 SNI)

HelloVerifyRequest(服务器防攻击措施)

  • 目的:防止 DoS 攻击(攻击者伪造 IP,消耗服务器资源)
  • 内容:服务端返回一个 cookie 给客户端,要求客户端再发送一次 ClientHello 并带上这个 cookie
  • 此时没有任何状态被保留(无状态机制)

ClientHello(第二次,带 Cookie)

  • 客户端重新发起 ClientHello,并附上 cookie
  • 服务端验证 cookie 成功后,进入真正的握手过程

ServerHello

  • 服务端选择协议版本、加密算法
  • 提供其 Random、Session ID、压缩方法、扩展信息

Certificate(服务端证书)

  • 服务端发送其证书(如 X.509),用于客户端验证其身份

ServerKeyExchange(可选)

  • 如果所选加密套件是临时密钥交换(如 ECDHE),会发送这个报文,包含公钥参数等

CertificateRequest(可选)

  • 如果需要客户端身份认证,服务端请求客户端提供证书

ServerHelloDone

  • 服务端完成所有 hello 消息,提示客户端可以继续下一步

Certificate(客户端,若服务端请求)

  • 客户端发送证书用于身份认证(如 Mutual TLS)

ClientKeyExchange

  • 客户端发送密钥交换材料(如 DH 公钥、RSA 加密的 pre-master secret)

CertificateVerify(可选)

  • 如果客户端提供了证书,此报文包含对前面握手消息的签名,用于验证客户端拥有私钥

ChangeCipherSpec

  • 客户端通知服务端:接下来所有数据都将使用协商好的加密套件加密

Finished

  • 客户端发送已加密的 Finished 消息,包含所有握手摘要的摘要(验证握手完整性)

服务端 ChangeCipherSpec + Finished

  • 服务端也切换加密,并发送加密的 Finished 消息

特有的机制

特性说明
消息序列号(Message Sequence)每条握手消息都有编号,用于乱序重组
重传机制如果对方没有应答,会重传握手消息(无 ACK)
记录层编号(Epoch/Sequence Number)每个阶段有不同的 epochseq,用于包重放保护
HelloVerifyRequest防止 IP 伪造攻击,DTLS 专属机制

重传机制(Retransmission)

  • 为什么需要?
    UDP 不保证报文到达和顺序,DTLS 握手报文可能丢失,必须实现重传保证握手完成。
  • 机制内容:
    • DTLS 对握手消息做序列号标记;
    • 如果客户端或服务器在超时时间内未收到预期消息,会重传之前的握手消息;
    • 重传报文必须被对端识别为重复消息并正确处理,不导致状态错误。

消息序列号(Message Sequence Number)

  • 用途:
    防止握手消息乱序,保证握手阶段状态同步。
  • 特点:
    • 每个握手消息分配序列号,递增;
    • 接收端按序列号处理消息,忽略重复或乱序消息。

握手消息片段化(Fragmentation)

  • 为什么需要?
    UDP 报文大小有限,握手消息可能大于单个 UDP 报文大小。
  • 机制内容:
    • 握手消息可以被分割成多个片段(Fragment)发送;
    • 接收端负责重组片段,直到完整消息;
    • 每个片段带有片段偏移和长度信息。

Cookie 机制(HelloVerifyRequest)

  • 目的:
    防止DoS 攻击(反射放大攻击),避免服务器资源被恶意请求耗尽。
  • 流程:
    • 客户端第一次发送 ClientHello,服务器不直接响应握手,而是回复一个带有 Cookie 的 HelloVerifyRequest
    • 客户端必须带上该 Cookie 重新发送 ClientHello
    • 服务器验证 Cookie 合法后才继续握手流程。

序列号和重放保护(Replay Protection)

  • 内容:
    • DTLS 为每条记录分配序列号(Record Sequence Number),确保记录不会被重放;
    • 接收端检测重复序列号,丢弃重放包;
    • 与 TLS 不同的是,DTLS 要在无连接环境下实现此功能。

无连接的记录层(Record Layer)

  • DTLS 使用和 TLS 类似的记录层结构,但消息通过 UDP 发送,没有连接状态;
  • 每条记录带有协议版本、内容类型、长度和序列号字段。

时间戳和定时器

  • DTLS 需要在握手时设置超时定时器,管理重传和超时处理;
  • 这在 TLS(基于 TCP)中不需要,因为 TCP 已经保证了可靠传输。

支持 MTU 探测与路径 MTU 发现

  • 由于 UDP 报文大小限制,DTLS 可以基于握手分片检测 MTU,以防止 IP 层分片导致性能下降。

Fingerprint(证书指纹)

DTLS Fingerprint 是对参与 DTLS 握手的 X.509 证书进行哈希计算(例如 SHA-256),生成的一串唯一字符串。

WebRTC 中不会使用 CA 机构来验证证书,而是通过交换证书指纹(fingerprint)来验证对等端。

  • SDP 协商中携带 fingerprint
  • 格式示例:
a=fingerprint:sha-256 7F:B8:33:...:9D

验证流程:

  1. 浏览器生成 DTLS 证书(X.509);
  2. 提取 fingerprint,加入 SDP;
  3. 对端在接收 DTLS 握手证书时,校验是否与 fingerprint 匹配;
  4. 若不匹配,则拒绝连接。

这确保了对端身份未被中间人篡改。

OpenSSL DTLS

#include <openssl/ssl.h>
#include <openssl/err.h>SSL_CTX *init_dtls_server_ctx() {const SSL_METHOD *method = DTLS_server_method();SSL_CTX *ctx = SSL_CTX_new(method);// 加载服务器证书和私钥SSL_CTX_use_certificate_file(ctx, "server_cert.pem", SSL_FILETYPE_PEM);SSL_CTX_use_PrivateKey_file(ctx, "server_key.pem", SSL_FILETYPE_PEM);// 设置握手重传超时和最大重试次数// DTLS 有内置超时机制,OpenSSL自动处理重传// 不用手动实现重传逻辑return ctx;
}void dtls_handshake(SSL *ssl, BIO *bio) {// 设置BIO为无连接UDP模式SSL_set_bio(ssl, bio, bio);// 阻塞握手直到成功或失败int ret = SSL_accept(ssl);if (ret <= 0) {int err = SSL_get_error(ssl, ret);if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {// 需要继续读写,可能是等待重传// 事件循环继续} else {// 握手失败处理}}// 握手成功后,调用SSL_read/SSL_write进行加密数据收发
}

DTLS 与 TLS 的关键区别

项目TLSDTLS
传输层TCPUDP
顺序有序无序
重传不需要需要(自实现)
报文格式流式数据报(data-gram)
拒绝服务防护有 HelloVerifyRequest
应用场景HTTPSWebRTC / VoIP / SRTP / IoT
http://www.lryc.cn/news/576664.html

相关文章:

  • PowerBI 柱状图显示MoM销量环比示例,以及解决相同列值时设置柱子颜色的问题
  • 【转】PostgreSql的镜像地址
  • 一个简单测试Deepseek吞吐量的脚本,国内环境可跑
  • QTreeWidget 简单使用
  • web自动化测试常见函数
  • 西门子S7-200 SMART PLC:小型自动化领域的高效之选
  • 华为云鸿蒙应用入门级开发者认证 实验部分题目及操作步骤
  • 基于Uniapp+SpringBoot+Vue 的在线商城小程序
  • AI 在金融领域的落地实践:从智能风控到量化交易的技术突破与案例解析
  • 【Docker基础】Docker容器管理:docker stats及其参数详解
  • 使用asyncio构建高性能网络爬虫
  • 华为云Flexus+DeepSeek征文|基于Dify构建AI资讯语音播报工作流
  • Python pyserial库【串口通信】全面讲解
  • 从傅立叶级数到傅里叶变换和离散傅里叶变换及其逆变换:FS FT DFT IDFT
  • 华为云Flexus+DeepSeek征文 | 华为云ModelArts Studio实战指南:创建高效的AingDesk知识库问答助手
  • Java锁机制知识点
  • Java安装与使用教程
  • FPGA设计的上板调试
  • zookeeper Curator(2):Curator的节点操作
  • 移动端日志平台EMAS
  • 在C++中#pragma“可选预处理指令的作用“。
  • OpenCV图像噪点消除五大滤波方法
  • springboot+Vue逍遥大药房管理系统
  • Redis—主从复制
  • 多径信道下移动通信信号均衡技术研究与实现
  • 常用工具库
  • 领域驱动设计(DDD)【22】之限定建模技术
  • electron中显示echarts
  • 顺序表应用实践:从通讯录实现到性能优化深度解析
  • 第6篇:中间件——Gin的请求处理管道