WebRTC学习(十一)实时数据传输网络协议详解

一:浏览器协议栈

左侧为http协议的协议栈,右侧为WebRTC协议栈

(一)http协议栈

API层:提供了XHR、SSE、WebSocket

应用层:提供了http1.x/2.0https协议

会话层:使用了TLS协议(可选),对于https需要这个协议,对于http并不需要

传输层:底层使用TCP传输,流传输

网络层:IP协议

(二)WebRTC协议栈

API层:提供了RTCPeerConnection和DataChannel

应用层:对于PeerConnection使用了SRTP协议,对于DataChannel使用了SCTP协议(流控传输协议)

会话层:使用了DTLS协议(仿照TLS),对于SRTP可选,对于SCTP为必须

链路检测层:ICE/STUN/TURN检测端到端之间的通路,进行连通性检测

传输层:底层使用UDP传输,报文传输

网络层:IP协议

二:WebRTC传输协议分析

 

1.RTP/SRTP:区别在于传输内容是否加密,同样对于RTCP/SRTCP一样。

2.RTP/RTCP:RTP协议定义流媒体数据在互联网上传输的数据包格式而RTCP协议则负责可靠传输、流量控制和拥塞控制等服务质量保证。

3.DTLS:在对SRTP/SRTCP数据进行加密之前,需要对证书进行检测,算法协商,通过DTLS实现。

(一)RTP协议

FFmpeg学习(六)H264流媒体协议解析中提及过

前12字节固定 + (0~15)个32位的CSRC标识符

 

V (2bits):   RTP协议的版本号,当前协议版本号为2。
P (1bit):    填充标志,如果设置填充位P=1,在包尾将包含附加填充字节,它不属于有效载荷。填充的最后一个八进制包含应该忽略的八进制计数。某些加密算法需要固定大小的填充字节,或为在底层协议数据单元中携带几个RTP包。
X (1bit):    扩展标志,如果X=1,则在RTP报头后跟有一个扩展报头
CC(4bits):     CSRC计数器,指示CSRC 标识符的个数。

M (1bit):    标记位(不同载荷含义不同,视频标记一帧的最后一个分片slice则=1,其他=0)标识帧边界
PT (7bits)载荷类型RTP_PAYLOAD_RTSP,记录后面资料使用哪种 Codec , receiver 端找出相应的 decoder 解碼出來。例如H264=96---用于区分不同的编解码器
序列号(16bits): 用于标识发送者所发送的 RTP 报文的序列号(初始值随机),每发送一个报文,序号增加 1

时间戳(32bits): 时间戳反映了该 RTP 报文的第一个八位组的采样时刻。 接受者使用时间戳来计算延迟和抖动, 并进行同步控制。如果帧分包后,如何组合?通过时间戳和序列号判断,同一个帧的timestamp相同,并且序列号连续。还可以通过M标记位
SSRC(32bits): 区分是在和谁通信。值随机选择,参加同一视频会议的两个同步信源的SSRC要相同。音视频源各有自己的ssrc,如果已经存在一个SSRC,则后面产生的不允许重复,后面的需要重新更改SSRC
贡献源(CSRC)标识符(32bits):每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源。
应用场景:多路混音、混流时使用,多人通信时,将音频进行混音后,其贡献者有多人,每一个的ssrc都放入一个CSRC当中去

注意:P填充标志,为1表示后面有填充字节,那么具体填充了多少字节呢?由填充的字节数中的最后一个字节来计算,比如最后一个字节数为5,则填充了5个字节(包含了最后一个字节本身)!!

RTP 协议实际上是由实时传输协议RTP(Real-time Transport Protocol)实时传输控制协议RTCP(Real-time Transport Control Protocol)两部分组成。

RTP 协议基于多播或单播网络为用户提供连续媒体数据的实时传输服务;  
RTCP 协议是 RTP 协议的控制部分,用于实时监控数据传输质量,为系统提供拥塞控制和流控制。

(二)RTCP协议https://winddoing.github.io/post/32277.html

1.RTCP包格式如下(与RTP格式一致):

一般情况下:RTP端口为偶数

RTCP也是用UDP来传送的,但RTCP封装的仅仅是一些控制信息,因而分组很短,所以可以将多个RTCP分组封装在一个UDP包中。类似于RTP信息包,每个RTCP信息包以固定部分开始,紧接着的是可变长结构单元,最后以一个32位边界结束。

注意:在WebRTC中,需要进行NAT穿越。为了简便,一般使用单个端口,所以一般情况下RTP与RTCP会复用同一个端口

2.RTCP负载类型:根据所携带的控制信息不同RTCP信息包可分为RR(接收者报告包)、SR(源报告包)、SEDS(源描述包)、BYE(离开申明)和APP(特殊应用包)五类:

1、SR:发送端报告包,用于发送和接收活动源的统计信息;本身即是发送者也是接收者,在发送数据的时候发送接收到的报文报告给对端,一个报文兼顾了两个功能

2、RR:接收者报告包,用于接收非活动站的统计信息;

3、SDES:源描述包,用于报告和站点相关的信息,包括CNAME(可识别),同一个CNAME可以对应多个SSRC,因为SSRC可能产生冲突,SSRC会更改,但是CNAME不会修改

4、BYE:断开RTCP包,是站点离开系统的报告,表示结束;关闭队员路径,不再发送RTP数据

5、APP:应用特定函数。

除了以上5种之外,在WebRTC中还经常使用其他类型,比如FIR关键帧请求、NACK丢包重传处理...见:https://blog.csdn.net/wanglf1986/article/details/52674378

1.FIR:请求一个完整的I帧,防止花屏

2.NACK:丢包重传(废弃)

3.RTPFB:RTP反馈包(传输层对RTP数据控制、payload内容编解码器、应用层3种反馈包),这里是传输层反馈包

4.PSFB:编解码器反馈包

3.RTCP Header

字段说明:

P:填充字节,同RTP的P填充标识字段!
RC:Receiver Report Block的个数,当负载类型为SDES时,可以为0
PT:负载类型
length:包长度,由于存放时为N-1,所以我们读取以后使用N+1变为真实长度进行计算
SSRC of sender:接收者收到之后,知道是谁发送过来的

4.SR类型 RTCP Sender Report:包含以下两部分:发送者自己的信息块以及接收者信息块(前提是自己既是发送者,又是接收者)

Sender Information block:记录了发送者发送了多少报文,多少字节

NTP timestamp, most significant word:64位时间戳的前32位高字节
NTP timestamp, least significant word:64位时间戳的后32位低字节,NTP用于不同源之间的同步,比如音视频同步。
RTP timestamp:RTP数据包的相对时间戳
sender's packet count:发送者发送包数,当SSRC发生变化时会被重置
sender's octet count:发送者发送的字节数,接受方会进行对比,检查是否数据丢失

Receiver Report block: (多个)因为作为多方通讯的一方来说,很可能接受到好几路音视频流(最少一个音频、一个视频,音视频不共用),对于每一个SSRC都会收到一个Report Block

其中jitter字段可以用于检测网络拥塞!

Sender Information block与Receiver Report block在RTCP协议中的表现:

0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=SR=200   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         SSRC of sender                        |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender |              NTP timestamp, most significant word             |
info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             NTP timestamp, least significant word             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         RTP timestamp                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     sender's packet count                     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      sender's octet count                     |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1    | fraction lost |       cumulative number of packets lost       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           extended highest sequence number received           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      interarrival jitter                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         last SR (LSR)                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                   delay since last SR (DLSR)                  |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_2 (SSRC of second source)                |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2    :                               ...                             :
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
       |                  profile-specific extensions                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

5.RR类型 RTCP Receiver Report:只包含Receiver Report block这一个部分

Receiver Report block在RTCP协议中的表现:

0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=RR=201   |             length            |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                     SSRC of packet sender                     |
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1    | fraction lost |       cumulative number of packets lost       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |           extended highest sequence number received           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                      interarrival jitter                      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         last SR (LSR)                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                   delay since last SR (DLSR)                  |
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_2 (SSRC of second source)                |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2    :                               ...                             :
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     |                  profile-specific extensions                  |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

6.RTCP SR/RR发送时机:SR/RR都是为了上报数据

7.RTCP SDES:包含头部(与前面类似)与内容,详见:https://blog.csdn.net/wanglf1986/article/details/52674378

SDES源描述包提供了直观的文本信息来描述会话的参加者,包括CNAME、NAME、EMAIL、PHONE、LOC等源描述项,这些为接收方获取发送方的有关信息提供了方便。

SDES 包由包头与数据块组成,数据块可以没有,也可有多个。包头由版本(V)、填充(P)、长度指示、包类型(PT)和源计数(SC)组成。

PT占8位,用于识别RTCP的SDES包,SC占5位,指示包含在SDES包中的SSRC/CSRC块数量,零值有效,但没有意义。

数据块由源描述项组成,Item使用TLV(type,length,value)存放数据,源描述项的内容如下:

SDES item结构:下面用CNAME举例

CNAME: 规范终端标识SDES项,在RTP会话中唯一。

类似SSRC标识,RTCP为RTP连接中每一个参加者赋予唯一一个CNAME标识。在发生冲突或重启程序时,由于随机分配的SSRC标识可能发生变化,CNAME项可以提供从SSRC标识到仍为常量的源标识的绑定。为方便第三方监控,CNAME应适合程序或人员定位源。

length:长度字段,大小可变,因为后面value存储大小可变

user and domain name:可变长度,详见:https://blog.csdn.net/wanglf1986/article/details/52674378

8.RTCP BYE:包含头部(与前面类似)与内容,详见:https://blog.csdn.net/wanglf1986/article/details/52674378

其中SC代表SSRC的个数,表示都有哪些源停止发送数据了,对于每个客户端一般会有两个:音频和视频,还有其他...

如混合器接收到一个BYE包,混合器转发BYE包,而不改变SSRC/CSRC 标识。

混合器关闭,在关闭之前它应该发出一个BYE包,列出混合器处理的所有源(省略号中表示),而不只是自己的SSRC标识

作为可选项,BYE包可包括一个8位八进制计数,后跟文本信息,表示离开原因,如:"cameramalfunction"或"RTPloop detected"。

字符串的编码与在SDES 项中所描述的相同。

如字符串信息至BYE包下32位边界结束处,字符串就不以空结尾;否则,BYE包以空八进制填充。

9.RTCP APP

APP包用于开发新应用和新特征的实验,不要求注册包类型值。带有不可识别名称的APP包应被忽略掉。测试后,如确定应用广泛,推荐重新定义每个APP包,而不用向IANA注册子类型和名称段。

10.FB反馈包:RTPFB:传输层反馈包,PSFB:payload-specific具体编解码类型反馈包

其中RTCP FB Header如下:

SSRC of packet sender:发送这个包的发送者的ssrc

SSRC of media source:发送的FB是针对哪个媒体源的(一般和上面是一致的)

Feedback Control Information:一些控制信息

其中传输层的RTPFB分为以下3类:

NACK:丢包重传

TMMBR/TMMBN: 最大媒体流比特率请求TMMBR,通过TMMBN响应最大带宽

其中负载层的PsPFB分为以下6类:

PLI:图片丢失标识,有一帧图片丢失

SLI:在H264中,一帧图像会分片为多个slice,每个slice会分成一个包,如果slice丢失,则发送标识

PRSI:参考帧丢失标识,参考帧P、I都可以作为参考帧

FIR:请求一个完整的IDR帧

TSTR/TSTN:时间空间交换请求 

补充:TLS协议(结合OpenSSL),基于TCP

1.OpenSSL==SSL==TLS

OpenSSL:开源的SSL

SSL:在原来的网络套接字的基础上,加上了安全机制,比如对称加密、非对称加密加在原来的socket之上,就变成了OpenSSL

TLS:在SSL3.0之后,标准化为TLS(重命名)

2.TLS协议(两大块)

TLS握手协议:交换证书以及其他加密信息

TLS记录协议:使用握手协议中获取的信息进行加密解密

3.OpenSSL原理

SSL_CTX:上下文,存放版本、证书、密钥...

SSL:SSL连接实例,与socket对应,基于socket传输

SSL_Write/SSL_Read:从socket中写入、读取 数据

4.OpenSSL的使用

(三)DTLS协议:基于UDP的TLS

https://blog.51cto.com/u_15087084/2598254

https://blog.csdn.net/alwaysrun/article/details/89076492

DTLS协议在UDP提供的socket之上实现了客户机与服务器双方的握手连接,并且在握手过程中通过使用PSK或ECC实现了加密,并且利用cookie验证机制和证书实现了通信双方的身份认证,并且用在报文段头部加上序号,缓存乱序到达的报文段和重传机制实现了可靠传送。

握手过程如上图所示,大体来说分成三个过程:明文通信过程、非对成加密通信过程、对称加密通信过程;

  1. 明文通信过程:在通信两端首次向对方发送 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)以验证服务端身份,里面携带了服务端非对称加密所使用的公钥;这步虽然是可选的,但是一般来说客户端都会要求验证服务端的身份,在大多数情况下这步都会执行;

    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(可选):如果服务端要求客户端提供数字证书以验证身份,则客户端发送自己的身份证书给服务端;

  2. 非对称加密通信过程由于非对称加密通信的性能较差,在实际的通信过程中其实使用的是对称加密通信,为了保证对称加密通信过程的安全性,也就是需要避免对称加密密钥被窃取,这个密钥在协商过程中使用非对称加密来进行加密。

    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 握手结束;

  3. 对称加密通信过程:通过上述握手过程协商出对称加密算法及使用的对称加密密钥之后,随后的通信过程,也就是实际的应用通信过程,都使用的是对称加密。

补充:常见加密算法

DTLS时序图:

1.SDP交换,媒体协商。SDP内容十分重要,交换了ICE需要的Username,Password,以及后面的DTLS需要的证书的验证指纹,用来验证证书是否被中间人替换。部分SDP内容如下:

a=fingerprint也就是指纹,那指纹是用来干什么的呢?

指纹就是用来我们进行数据加密的时候,来验证这个证书的。那它首先通过信令层将SDP中的证书的指纹下发给对方,那么下次对数据加密前的它进行一下数据证书的交换,交换证书是通过DPLS进行,那么通过DPLS进行证书交换的时候,通过这个指纹去验证你这个证书的有效性,那如果这个证书验证是有效性的,然后后面你才能进行数据加密然后进行传输。如果通过指纹这个证书不匹配,那说明你这个连接也是有问题的。那这个时候就不能进行传输。通过以上这个种种方式呢,在打通的时候进行一次验证在传数据的时候在交换证书的时候也要进行验证,那么通过这个层层的安全的验证,才能保证整个webRTC传输的安全性。以上就是安全性相关的一些描述。当然最后进行算法加密的时候你可以使用这个a=crypto指定的加密算法,也可以通过DPLS交换的证书里的指定的加密算法进行加密

2.STUN/TURN服务,获取Candidate(TURN服务需要username与password),验证连通性,获取Candidate对

3.DTLS握手

4.传输加密后的数据

(四)SRTP:基于DTLS获取了对称加密所需要的密钥和对应的加密算法,使用在SRTP中,以此来对RTP数据进行加密保证安全和完整性

头部与普通RTP头一样,头部不进行加密,只有数据进行加密(黄色部分),最后的部分:

SRTP MKI:主键标识符(可选),webrtc不使用,为0

Authentication Tag:完整性验证,RTP头与加密数据进行做一次hash函数运算,得到摘要。对端通过同样方式进行验证,用来保证完整性

(五)libsrtp:开源库,可以解决大数据吞吐

 

创建Session:是在DTLS握手之后,获取了双方信息,比如协商后的加密算法、密钥...,之后可以进行加解密。

另外,session包含两个,分别对于输出流和输入流,不能共用。

三:协议数据捕获---wireshark

(一)UDP转RTP

见:http://www.360doc.com/content/18/0904/11/8335678_783756276.shtml

(二)RTP查看

 

可以看出,上面RTP数据序号连续,时间戳相同,是来自同一个帧的连续分包 

(三)RTCP查看

 

 

posted @ 2021-05-30 18:42  山上有风景  阅读(3260)  评论(2编辑  收藏  举报