在 WebRTC 中,为了保障媒体传输的安全性,引入了 DTLS 来对通信过程进行加密。DTLS 的作用、原理与 SSL/TLS 相似,都是为了使得本来不平安的通信过程变得平安。它们的区别点是 DTLS 实用于加密 UDP 通信过程,SSL/TLS 实用于加密 TCP 通信过程,正是因为应用的传输层协定不同,造成了它们实现下面的一些差别。
基本概念
对称密钥加密技术
对称密钥加密的含意是加密过程和解密过程应用的是同一个密钥。常见的对称加密算法有 DES、3DES、AES、Blowfish、IDEA、RC5、RC6。
非对称加密密钥加密技术
非对称密钥加密的含意是加密过程和解密过程应用了不同的密钥,别离称为公开密钥和公有密钥。公钥是家喻户晓的,然而密钥只能为报文的指标主机所持有。相比对称加密技术,它的长处是不必放心密钥在通信过程中被别人窃取;毛病是解密速度慢,耗费更多的 CPU 资源。常见的非对称加密算法有 RSA、DSA、DH 等。
数字签名
数字签名是附加在报文上的非凡加密校验码,即所谓的校验和,其中利用了非对称加密密钥加密技术。数字签名的次要作用是避免报文被篡改,一旦报文被攻击者篡改,通过将其与校验和进行匹配,能够立即被接收者发现。数字签名的过程如下图所示:
发送者 A 将报文摘要(报文通过 SHA-1 等哈希算法生成摘要)通过公有密钥加密生成签名,与明文报文一起发给接收者 B,接收者 B 能够通过对收到的信息进行计算后失去两份报文摘要,比拟这两份报文摘要是否相等能够验证报文是否被篡改:
- 明文报文通过应用与发送端雷同的哈希算法生成摘要 1;
- 签名通过公开密钥解密后生成摘要 2。
数字证书
数字证书是由一些公认可信的证书颁发机构签发的,不易伪造。包含如下内容:
- 证书序列号
- 证书签名算法
- 证书颁发者
- 有效期
- 公开密钥
- 证书签发机构的数字签名
数字证书能够用于接收者验证对端的身份。接收者(例如浏览器)收到某个对端(例如 Web 服务器)的证书时,会对签名颁发机构的数字签名进行查看,一般来说,接收者当时就会事后装置很多罕用的签名颁发机构的证书(含有公开密钥),利用事后的公开密钥能够对签名进行验证。以 Google 为例,在浏览器中拜访 Google 首页,点击左上角的感叹号就能够看到 Google 证书的残缺信息,包含以上提到的所有内容:
参考资料
https://zhangbuhuai.com/post/…
SSL/TLS 协定
简介
要理解 DTLS,首先从咱们比拟相熟的 SSL/TLS 开始讲起。SSL(Secure Socket Layer)和 TLS(Transport Layer Security)简略了解就是同一件货色的两个演进阶段,同样都是在应用层和传输层之间退出的平安层,最早的时候这个平安层叫做 SSL,由 Netscape 公司推出,起初被 IETF 组织标准化并称之为 TLS。SSL/TLS 的作用是为了解决互联网通信中存在的三种危险:
- 窃听危险:第三方能够获知通信内容;
- 篡改危险:第三方能够批改通信内容;
- 假冒危险:第三方能够假冒别人身份参加通信。
SSL/TLS 协定可能做到以下这几点,从而解决上述的三种危险:
- 所有信息通过加密流传,第三方无奈窃听;
- 具备数据签名及校验机制,一旦被篡改,通信单方立即能够发现;
- 具备身份证书,避免其他人假冒。
协定栈
SSL/TLS 建设在 TCP 传输层上,最常应用 SSL/TLS 的场景是在 HTTPS 中,通过在 HTTP 和 TCP 中加了一层 SSL/TLS,使得不平安的 HTTP 成为了平安的 HTTPS。协定栈如下图所示:
SSL/TLS 加密是通过动静密钥对数据进行对称加密实现的,而动静密钥通过握手流程协商制订。在 SSL/TLS 握手过程中须要协商的信息包含:
- 协定版本号;
- 加密算法,包含非对称加密算法、动静密钥算法;
- 数字证书,传输单方通过替换证书及签名校验来验证对方身份;
- 动静密钥,因为非对称加密对性能耗费较大,因而次要的通信过程都是应用动静密钥进行对称加密的;对称加密应用的动静密钥则在握手过程中通过非对称加密来传输。
握手过程
以 TLS 1.2 为例:
握手过程如上图所示,大体来说分成三个过程:明文通信过程、非对称加密通信过程、对称加密通信过程;
-
明文通信过程:在通信两端首次向对方发送 Hello 音讯时,因为单方都没有协商好要应用哪种加密形式,因而这个过程中的音讯都是应用明文进行发送的。
a. Client Hello:客户端首先向服务端发动握手,在握手音讯中通知对方本人反对的 SSL/TLS 版本、加密套件(包含非对称加密时应用的算法与、非对称加密时应用的算法、产生密钥的伪随机函数 PRF)与数据压缩算法(TLS1.3 之后就曾经没有这个字段)等;还会携带一个 Session ID,因为握手流程的开销比拟大,应用 Session ID 能够在下一次与 TLS 握手的过程跳过后续繁琐的握手流程,重用之前的握手后果(如版本号、加密算法套件、master-key 等);并产生一个随机数 A,也通知给对方;
b. Server Hello:服务端响应一个 Server Hello 音讯,携带协商进去的 TLS/SSL 版本号、加密套件和数据压缩算法,如果服务端批准客户端重用上次的会话,就返回一个雷同的 Session ID,否则就填入一个全新的 Session ID;
c. Server Certificate(可选):携带服务端数字证书(CA)以验证服务端身份,外面携带了服务端非对称加密所应用的公钥;大部分状况下这步都是须要的,除非客户端和服务端协商应用了某些匿名密钥协商算法(如 匿名 DH 算法);
d. Server Key Exchange(可选):在应用某些非对称加密算法(例如 DH 算法)的状况下,Server Certificate 里的信息是不足够的,或者 Server Certificate 在某些通信过程中间接被省略了(没有验证服务端身份),须要 Server Key Exchange 里的额定信息来帮忙客户端生成 pre-master key;
e. Client Sertificate Request(可选):在有些安全性要求高的场景,例如银行领取等,不仅须要验证服务端的身份,还须要验证客户端的身份,这时候服务端就会要求客户端提供客户端的身份证书;
f. Server Hello Done:表明 Server Hello 完结;
g. Client Certificate(可选):如果服务端要求客户端提供数字证书以验证身份,则客户端发送本人的身份证书给服务端;
-
非对称加密通信过程:因为非对称加密通信的性能较差,在理论的通信过程中其实应用的是对称加密通信,为了保障对称加密通信过程的安全性,也就是须要防止对称加密密钥被窃取,这个密钥在协商过程中应用非对称加密来进行加密。
a. Client Key Exchange:客户端在验证服务端的身份证书后,会取出其中的服务端公钥,产生一个随机数 C,作为 pre-master key,在本地应用之前的随机数 A、B 和这次生成的 C 独特生成对称加密密钥 master-key;应用服务端公钥对 pre-master key 加密后发送给服务端;
b. Certificate Verify(可选):如果服务端要求客户端提供客户端证书,那么客户端在发送 Client Key Exchange 之后必须马上发送 Certificate Verify,其中的内容是客户端应用本人的私钥加密的一段数据,提供给服务端用客户端的公钥来进行解密验证。之所以须要这一步是为了确保客户端发送的证书的确是它本人的证书;
c. Client Change Cipher Spec:提醒服务端随后应用 master key 来进行对称加密通信;
d. Client Handshake Finished: 表明客户端侧 SSL/TLS 握手完结;
e. Server Change Cipher Spec:提醒客户端随后应用 master key 来进行对称加密通信;
f. Server Handshake Finished:表明服务端侧 SSL/TLS 握手完结;
- 对称加密通信过程:通过上述握手过程协商出对称加密算法及应用的对称加密密钥之后,随后的通信过程,也就是理论的利用通信过程,都应用的是对称加密。
握手音讯格局
SSL/TLS 的握手音讯格局如下所示,音讯类型曾经在上文握手过程中别离进行了解释;构造体中蕴含 音讯类型、音讯长度、音讯体。
enum {hello_request(0), client_hello(1), server_hello(2),
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20)
(255)
} HandshakeType;
struct {
HandshakeType msg_type;
uint24 length;
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case certificate: Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done: ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished;
} body;
} Handshake;
每种音讯都会有本人独立的音讯体,音讯体中的内容就是握手过程中提到的音讯中须要携带的一些信息,以 ClientHello 为例,其中须要蕴含 SSL/TLS 版本号、随机数、Session ID、可选的加密套件、可选的压缩算法:
struct {
ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites<2..2^16-1>;
CompressionMethod compression_methods<1..2^8-1>;
} ClientHello;
答疑
- 什么时候握手过程中不须要 Server Certificate 的步骤?
如果服务端和客户端协商进去的密钥替换算法是匿名算法,例如匿名 DH 算法。所以如果应用如下加密套件都会省略 Server Certificate 的步骤:
CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 = {0x00,0x18};
CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = {0x00,0x1B};
CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA = {0x00,0x34};
CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA = {0x00,0x3A};
CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA256 = {0x00,0x6C};
CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA256 = {0x00,0x6D};
TLS RFC 也明确指出应用这些匿名算法是不平安的,因为客户端没有验证服务端的身份,容易蒙受中间人攻打。
参考资料
RFC:
https://tools.ietf.org/html/r… TLS 1.0
https://tools.ietf.org/html/r… TLS 1.1
https://tools.ietf.org/html/r… TLS 1.2(本文次要参考)
https://tools.ietf.org/html/r… TLS 1.3
论坛材料:
https://www.cnblogs.com/littl…
https://segmentfault.com/a/11…
https://halfrost.com/https_tl…
DTLS 协定
简介
DTLS 的全称为 Datagram Transport Layer Security,从名字上就能够看出它和 TLS 的区别就在于多了一个“Datagram”,因为咱们把应用 UDP 传输的报文叫做“Datagram”,所以这个名字也就意味着 DTLS 是实用于 UDP 传输过程的加密协议。
DTLS 在设计上尽可能复用 TLS 现有的代码,并做一些小的批改来适配 UDP 传输。DTLS 与 TLS 具备了同样的平安机制和防护等级,同样可能避免音讯窃听、篡改,以及身份假冒等问题。在版本上,DTLS 和 TLS 也有肯定的对应关系,如下:
- DTLS 1.0 对应 TLS 1.1
- DTLS 1.2 对应 TLS 1.2
- DTLS 1.3 对应 TLS 1.3
没有 DTLS 1.1 该当是为了和 TLS 版本号相一致。
协定栈
在 WebRTC 中,通过引入 DTLS 对 RTP 进行加密,使得媒体通信变得平安。通过 DTLS 协商出加密密钥之后,RTP 也须要降级为 SRTP,通过密钥加密后进行通信。协定栈如下图所示:
握手过程
TLS 1.2 及之前都没有尝试解决 DoS 攻打的问题,直到 TLS 1.3 才通过退出了 HelloRetryRequest 和 Cookie 来解决 DoS 攻打的问题(并且在 TLS 1.3 的 RFC 中提到次要用于非面向连贯的通道,也就是 UDP 连贯)。绝对 TCP 来说,UDP 连贯对 DoS 攻打更加敏感,因而 DTLS 在 1.0 版本就退出了 HelloVerifyRequest 和 Cookie,用于服务端对客户端的二次校验,防止 DoS 攻打。
同样以 DTLS 1.2 举例(TLS 1.3 和 DTLS 1.3 的流程曾经很靠近了),相比 TLS 1.2,DTLS 1.2 大部分步骤都是一样的,只是在服务端多了一步 HelloVerifyRequest,客户端因而也多了第二次的 ClientHello,如下图所示:
服务端在首次收到客户端发送的 Client Hello 之后,只会生成一个 Cookie,不进行任何其余的操作,并给客户端发送 HelloVerifyRequest 音讯,带上这个 Cookie。只有当客户端从新发送一次 Client Hello,并带上服务端发送的这个 Cookie 后,服务端才会持续握手过程。
握手音讯格局
DTLS 的握手音讯格局如下所示,能够看到相比 SSL/TLS 的握手协定,DTLS 在音讯类型中多了 HelloVerifyRequest 这种音讯(在握手过程中介绍过),在构造体中多了 message_seq、fragment_offset、fragment_length 三个字段。
SSL/TLS 基于 TCP,因而不须要操心重放、乱序、丢包的问题,牢靠传输由 TCP 做了保障;而 DTLS 基于 UDP,UDP 是一种尽力而为的协定,因而 DTLS 须要本人解决重放、乱序、丢包的问题。DTLS 在复用大部分 TLS 的根底上做了一些小改变,在握手音讯中减少了三个字段 message_seq、fragment_offset、fragment_length 三个字段,具体的性能在下一节中讲述。
enum {hello_request(0), client_hello(1), server_hello(2),
hello_verify_request(3), // New field
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20), (255) } HandshakeType;
struct {
HandshakeType msg_type;
uint24 length;
uint16 message_seq; // New field
uint24 fragment_offset; // New field
uint24 fragment_length; // New field
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case hello_verify_request: HelloVerifyRequest;// New field
case certificate:Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done:ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished;
} body; } Handshake;
每种音讯同样都会有本人独立的音讯体,音讯体中的内容就是握手过程中提到的音讯中须要携带的一些信息,大部分的音讯体内容与 SSL/TLS 雷同,区别有两点:
-
多了 HelloVerifyRequest 音讯,须要携带 Cookie,音讯体如下所示:
struct { ProtocolVersion server_version; opaque cookie<0..32>; } HelloVerifyRequest;
-
ClientHello 多了 Cookie 字段,因为第二次 ClientHello 须要携带 Cookie 信息:
struct { ProtocolVersion client_version; Random random; SessionID session_id; opaque cookie<0..32>; // New field CipherSuite cipher_suites<2..2^16-1>; CompressionMethod compression_methods<1..2^8-1>; } ClientHello;
与 SSL/TLS 在实现上的区别
在上文的握手过程和握手协定中曾经讲述了一些 DTLS 与 SSL/TLS 的区别。此外,DTLS 针对反复、乱序、丢包等问题减少了一些防护机制。
握手防护机制
重传
TCP 人造的重传机制保障了音讯不会失落,而 UDP 对此没有任何保障。因而 DTLS 额定减少了超时重传机制来确定握手音讯达到,流程如下:
以握手的第一阶段举例,客户端发送 Client Hello(不带 Cookie,区别于握手流程中的第二次 Client Hello)之后,启动一个定时器,期待服务端返回 HelloVerifyRequest,如果超过了定时器工夫客户端还没有收到 HelloVerifyRequest,那么客户端就会晓得要么是 Client Hello 音讯丢了要么是 Hello Verify Request 音讯丢了,客户端就会再次发送雷同的 Client Hello 音讯,即便服务端的确发送了 Hello Verify Request 还是收到了 Client Hello 音讯,它也晓得是须要重传,并再次发送 Hello Verify Request 音讯,同样地,服务端也会启动定时器来期待下一条音讯。
序列号
TCP 音讯中自带了序列号 seq,并解决了乱序的问题,而 UDP 对乱序问题也没有任何保障。为了保障握手音讯的有序性,DTLS 在握手报文中减少了 message_seq 字段便于接管方解决乱序音讯。接管方间接解决属于以后步骤的音讯,提供一个缓存队列来缓存提前达到的音讯。
报文大小限度
TCP 面向字节流,而 UDP 面向报文。因而 TCP 会主动将报文进行拆分和组装,无需下层操心;而 UDP 报文如果超过了 MTU(链路层的最大传输单元)限度,会在 IP 层被强制分片,使得每一片大小都小于 MTU,接管方 IP 层须要进行数据报的重组,这样就会多做许多工作,更麻烦的中央在于只有其中一片失落就会造成重组失败,造成整个 UDP 报文失落。
因而 DTLS 间接在 UDP 之上就对握手音讯做了分段,握手报文中的 fragment_offset 和 fragment_length 就是为了这个目标,别离代表这段报文绝对音讯起始的偏移量以及这段报文的长度。
Cookie
在上文的握手过程中 TLS 1.2 及之前都没有尝试解决 DoS 攻打的问题,直到 TLS1.3 才通过退出了 HelloRetryRequest 和 Cookie 来解决 DoS 攻打的问题(并且在 TLS 1.3 的 RFC 中提到次要用于非面向连贯的通道,也就是 UDP 连贯)。绝对 TCP 来说,UDP 连贯对 DoS 攻打更加敏感,因为 TCP 能够应用 SYN Cookie 的机制来防备 DoS 攻打。
如果在 UDP 上间接应用 TLS 的握手形式,就可能产生以下两种状况:
- 攻击者能够通过发送一系列握手启动申请来耗费服务器上的资源,例如服务端可能会为此调配缓冲区,并且加密过程也是一个十分耗费 CPU 资源的操作;
- 攻击者能够伪造受益客户端的 IP 地址向服务端发动 DTLS 握手,迫使服务端发送 Certificate 音讯给受益客户端,上文提到过 Certificate 携带了很多信息,包含数字证书等,所以这个音讯会十分大,使得受益客户端不得不承受大量无用音讯。
因而 DTLS 在 1.0 版本就退出了 HelloVerifyRequest 和 Cookie,用于服务端对客户端的二次校验,防止 DoS 攻打。具体实现形式如下:
- 当客户端首次给服务端发送 Client Hello 时,服务端只会生成一个 Cookie 并通过 HelloVerifyRequest 发送给客户端,不会执行调配缓冲区等操作,直到收到带上雷同 Cookie 的 Client Hello 才会持续握手,能够使得伪造 IP 的攻打难以实现(应用实在 IP 的 DoS 攻打无能为力);
- HelloVerifyRequest 足够小,即便服务端被攻击者当枪使来攻打其余机器,也不会造成大量数据发送。
加密形式
因为 SSL/TLS 依赖 TCP,所以 SSL/TLS 有如下几个个性:
- SSL/TLS 不能独立解密单个封包,SSL/TLS 对于封包的认证须要序号作为输出,在 SSL/TLS 中并未间接传递序号,因为 TCP 是牢靠的,所以 SSL/TLS 的两端各自保护本身的收发序号;
- SSL/TLS 的某些加密算法不是独立解密的,须要依赖上个封包,典型的就是 RC4 流加密算法。
因为 UDP 自身的不牢靠,为了解决下面提到的第一个问题,DTLS 在每条记录中显式携带的序号作为解码的输出;而对于第二个问题,DTLS 的现状是不能反对 RC4 等流式加密算法。
音讯重放检测
音讯重放也是 DoS 攻打的一种,攻击者能够截取发送者发送的数据,并间接一成不变地发给接管方,来达到坑骗接管方的目标。
DTLS 减少了相似 IPsec AH/ESP 的音讯重放检测,应用一个 bitmap 滑动窗口来接管音讯,联合音讯自身的序号,bitmap 能够判断该音讯是否是太老的音讯,是的话则间接摈弃。这个性能在 DTLS 中是可选的,因为某些 UDP 报文的反复只是单纯因为网络谬误。
答疑
- DTLS 是否须要用户本人实现?
OpenSSL 中有对 DTLS 的反对,在 WebRTC 中收到包并判断是 DTLS 包后,会通过 OpensslStreamAdaptor 将剩下的步骤交给 OpenSSL 来做,根本不须要用户自行实现。
- 攻击者做重放攻打的收益是什么?为什么 DTLS 要做重放检测?如果不是中间人,而是发送端一直反复发送某条音讯,是否也会引起同样的问题?
https://www.pcmag.com/encyclo…
https://www.kaspersky.com/res…
参考网上的一些案例:
a. 用户 A 登录某个网站,而后攻击者间接把登录过程记录下来重放,尽管攻击者不晓得用户 A 的明码,但通过重放攻击者也能够胜利登录,达到了盗号的目标;b. 用户 A 登录某领取平台给 B 转账 100 元,B 把 A 和领取平台的通信过程记录下来重放,这样领取平台就会给 B 转十分多的钱。
DTLS 其实不仅是给 WebRTC 媒体传输用的,例如 OpenSSL 间接收录了 DTLS,DTLS 有可能被用到一些十分重要的场合。作为一种标准协议,DTLS 须要思考本身的安全性,因而 DTLS 须要在设计时思考防备重放攻打。
对于第二个问题,发送端一直反复发送某条音讯,不是重放攻打。当然歹意客户端可能想要耗费服务端的资源,疯狂调用某些 API,DTLS 无奈避免这种问题,须要靠下层业务来保障。
参考资料
RFC:
https://tools.ietf.org/html/r… SRTP
https://tools.ietf.org/html/r… DTLS 1.0
https://tools.ietf.org/html/r… DTLS 1.2(本文次要参考)
https://tools.ietf.org/id/dra… DTLS 1.3
论坛材料:
https://www.bbsmax.com/A/RnJW…
https://yq.aliyun.com/article…
https://juejin.cn/post/684490…