WebRTC学习(⼆):WebRTC传输协议
我们知道WebRTC要解决的是两个浏览器之间如何进⾏实时⾳视频互动的问题。从底层来看,就是要解决两个点之间如何进⾏⾼效的⽹络传输。这就涉及要很多重要的传输协议,下⾯我们针对涉及到的协议进⾏梳理和说明。
⼀、NAT(Network Address Translator)
NAT主要做的事情就是地址映射,其作⽤就是将内⽹的主机经过NAT的映射⽣成外⽹的ip地址和端⼝,如下图所⽰:
NAT产⽣的原因如下:
IPV4的地址不够。
处于安全考虑,保证某局域⽹下的设备的安全。
NAT的种类有以下⼏种:
完全锥型NAT:所有从同⼀个内⽹IP和端⼝号发送过来的请求都会被映射成同⼀个外⽹IP和端⼝号,并且任何⼀个外⽹主机都可以通过这个映射的外⽹IP和端⼝号向这台内⽹主机发送包。
地址限制锥型NAT:它也是所有从同⼀个内⽹IP和端⼝号发送过来的请求都会被映射成同⼀个外⽹IP和端⼝号。与完全锥形不同的是,外⽹主机只能够向先前已经向它发送过数据包的内⽹主机发送包。
端⼝限制锥型NAT:端⼝限制锥形NAT与限制锥形NAT很相似,只不过它包括端⼝号。也就是说,⼀台IP地址X和端⼝P的外⽹主机想给内⽹主机发送包,必须是这台内⽹主机先前已经给这个IP地址X和端⼝P发送过数据包。
对称型NAT:所有从同⼀个内⽹IP和端⼝号发送到⼀个特定的⽬的IP和端⼝号的请求,都会被映射到同⼀个IP和端⼝号。如果同⼀台主机使⽤相同的源地址和端⼝号发送包,但是发往不同的⽬的地,NAT将会使⽤不同的映射。此外,只有收到数据的外⽹主机才可以反过来向内⽹主机发送包。
⼆、STUN(Session Traversal Utilities for NAT)
STUN即NAT会话穿透实⽤⼯具[RFC5389],⽤于进⾏UAT穿透,采⽤的是典型的客户端/服务端模式。客户端发送请求,服务端进⾏响应。STUN是⼀个C/S架构的协议,⽀持两种传输类型。⼀种是请求/响应类型,由客户端给服务端发送请求并等待服务端响应;另⼀种是指⽰类型,由服务器或者客户端发送指⽰,另⼀⽅不产⽣响应。两种类型的传输都包含⼀个96位的随机数作为事务ID(transaction ID),对于请求/响应类型,事务ID允许客户端将响应和产⽣响应的请求连接起来;对于指⽰类型,事务ID通常作为debugging aid使⽤。
STUN报⽂和⼤多数⽹络类型的格式⼀样,是以⼤端编码(big-endian)的,即最⾼有效位在左边。所有的STUN报⽂都以20字节(160位)的头部开始,后⾯跟着若⼲个属性。
2.1 STUN报⽂头部
STUN头部包含了STUN消息类型,magic cookie,事务ID和消息长度,如下:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0|    STUN Message Type    |        Message Length        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Magic Cookie                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                              |
|                    Transaction ID (96 bits)                  |
|                                                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
下⾯来说明⼀下报⽂头部的各个数据的意义:
前两位必须设置为00,这样可以在当STUN和其他协议复⽤的时候,⽤来区分STUN包和其他数据包,如RTP数据的报头前两位为01。
Message Length 字段存储了信息的长度,以字节为单位,不包括20字节的STUN头部。由于所有的STUN属性都是都是4字节对齐
(填充)的,因此这个字段最后两位应该恒等于零,这也是辨别STUN包的⼀个⽅法之⼀。
STUN Message Type 是14位是消息类型,其中包括消息类型和消息主⽅法。
Magic Cookie 字段包含固定值0x2112A442,这是为了前向兼容RFC3489,因为在classic STUN中,这⼀区域是事务ID的⼀部分。另外选择固定数值也是为了服务器判断客户端是否能识别特定的属性。还有⼀个作⽤就是在协议多路复⽤时候也可以将其作为判断标志之⼀。
Transaction ID 字段是个96位的标识符,⽤来区分不同的STUN传输事务。对于request/response传输,事务ID由客户端选择,服务器收到后以同样的事务ID返回response;对于indication则由发送⽅⾃⾏选择。事务ID的主要功能是把request和response联系起来,同时也在防⽌攻击⽅⾯有⼀定作⽤。服务端也把事务ID当作⼀个Key来识别不同的STUN客户端,因此必须格式化且随机在0~2^(96-1)之间。重发同样的request请求时可以重⽤相同的事务ID,但是客户端进⾏新的传输时,必须选择⼀个新的事务ID。
2.2 STUN 属性
在STUN报⽂头部之后,通常跟着0个或者多个属性,每个属性必须是TLV编码的(Type-Length-Value)。
其中Type字段和Length字段都是16位,如下:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Type                  |            Length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Value (variable)                ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2.3 STUN 通信过程
webrtc浏览器1. 产⽣⼀个Request或Indication
当产⽣⼀个Request或者Indication报⽂时,终端必须根据上⽂提到的规则来⽣成头部,class字段必须是
Request或者Indication,⽽method 字段为Binding或者其他⽤户拓展的⽅法。属性部分选择该⽅法所需要的对应属性。
2. 发送Requst或Indication
⽬前,STUN报⽂可以通过UDP,TCP以及TLS-over-TCP的⽅法发送,其他⽅法在以后也会添加进来。STUN的使⽤者必须指定其使⽤的传输协议,以及终端确定接收端IP地址和端⼝的⽅式。
下⾯说明⼀下使⽤不同⽅式发送报⽂的通信机制:
通过UDP发送:当使⽤UDP协议运⾏STUN时,STUN的报⽂可能会由于⽹络问题⽽丢失。可靠的STUN请求/响应传输是通过客户端重发request请求来实现的,因此,在UDP运⾏时,Indication报⽂是不可靠的。STUN客户端通过RTO(Retransmission TimeOut)来决定是否重传Requst,并且在每次重传后将RTO翻倍。具体重传时间的选取可以参考相关⽂章,如RFC2988。重传直到接收到Response才停⽌,或者重传次数到达指定次数Rc,Rc应该是可配置的,且默认值为7。
通过TCP或者TCP-over-TLS发送:对于这种情景,客户端打开对服务器的连接。在某些情况下,此TCP链接只传输STUN报⽂,⽽在其他拓展中,在⼀个TCP链接⾥可能STUN报⽂和其他协议的报⽂会进⾏多路复⽤(Multiplexed)。数据传输的可靠性由TCP协议本⾝来保证。值得⼀提的是,在⼀次TCP连接中,
STUN客户端可能发起多个传输,有可能在前⼀个Request的Response还没收到时就再次发送了⼀个新的Request,因此客户端应该在确认所有STUN事务都已完成之前保持TCP链接打开。
3. 接受STUN消息
当STUN终端接收到⼀个STUN报⽂时,⾸先检查报⽂的规则是否合法,即前两位是否为0,magic cookie是否为0x2112A442,报⽂长度是否正确以及对应的⽅法是否⽀持。
如果消息类别为Success/Error Response,终端会检测其事务ID是否与当前正在处理的事务ID相同。如果使⽤了FINGERPRINT拓展的话还会检查FINGERPRINT属性是否正确。
完成⾝份认证检查之后,STUN终端会接着检查其余未知属性。
3.1 处理Request
如果请求包含⼀个或者多个强制理解的未知属性,接收端会返回error response,错误代码420(ERROR-CODE属性),
⽽且包含⼀个UNKNOWN-ATTRIBUTES属性来告知发送⽅哪些强制理解的属性是未知的。服务端接着检查⽅法和其他指定要求,如果所有检查都成功,
则会产⽣⼀个Success Response给客户端。
3.1.1 ⽣成Success Response或Error Response
如果服务器通过某种验证⽅法(authentication mechanism)通过了请求⽅的验证,那么在响应报⽂⾥最好也加上对应的验证属性。
服务器端也应该加上指定⽅法所需要的属性信息,另外协议建议服务器返回时也加上SOFTWARE属性。
对于Binding⽅法,除⾮特别指明,⼀般不要求进⾏额外的检查。当⽣成Success Response时,服务器在响应⾥加上XOR-
MAPPED-ADDRESS属性。
对于UDP,这是其源IP和端⼝信息,对于TCP或TLS-over-TCP,这就是服务器端所看见的此次TCP连接的源IP和端⼝。
3.1.2 发送Success Response或Error Response
发送响应时候如果是⽤UDP协议,则发往其源IP和端⼝,如果是TCP则直接⽤相同的TCP链接回发即可。
3.2 处理Indication
如果Indication报⽂包含未知的强制理解属性,则此报⽂会被接收端忽略并丢弃。如果对Indication报⽂的检查都没有错误,则服务端会进⾏相应的处理,
但是不会返回Response。对于Binding⽅法,⼀般不需要额外的检查或处理。收到信息的服务端仅需要刷新对应NAT的端⼝绑定。
由于Indication报⽂在⽤UDP协议传输时不会进⾏重传,因此发送⽅也不需要处理重传的情况。
3.3 处理Success Response
如果Success Response包含了未知的强制理解属性,则响应会被忽略并且认为此次传输失败。客户端对报⽂进⾏检查通过之后,就可以开始处理此次报⽂。
以Binding⽅法为例,客户端会检查报⽂中是否包含XOR-MAPPED-ADDRESS属性,然后是地址类型,如果是不⽀持的地址类型,则这个属性会被忽略掉。
3.4 处理Error Response
如果Error Response包含了未知的强制理解属性,或者没有包含ERROR-CODE属性,则响应会被忽略并且认为此次传输失败。
随后客户端会对验证⽅法进⾏处理,这有可能会产⽣新的传输。
到⽬前为⽌,对错误响应的处理主要基于ERROR-CODE属性的值,并遵循如下规则:
如果error code在300到399之间,客户端被建议认为此次传输失败,除⾮⽤了ALTERNATE-SERVER拓展;
如果error code在400到499之间,客户端认为此次传输失败;
如果error code在500到599之间,客户端可能会需要重传请求,并且必须限制重传的次数。
任何其他的error code值都会导致客户端认为此次传输失败。
三、TURN(Traversal Using Replays around NAT)
TURN的全称为Traversal Using Relays around NAT,是STUN/RFC5389的⼀个拓展,主要添加了Rela
y功能。如果终端在NAT之后,那么在特定的情景下,有可能使得终端⽆法和其对等端(peer)进⾏直接的通信,这时就需要公⽹的服务器作为⼀个中继,对来往的数据进⾏转发。这个转发的协议就被定义为TURN。TURN和其他中继协议的不同之处在于,它允许客户端使⽤同⼀个中继地址(relay address)与多个不同的peer进⾏通信。
如果TURN使⽤于ICE协议中,relay地址会作为⼀个候选,由ICE在多个候选中进⾏评估,选取最合适的通讯地址。⼀般来说中继的优先级都是最低的。TURN协议被设计为ICE协议(Interactive Connectivity Establishment)的⼀部分,⽽且也强烈建议⽤户在他们的程序⾥使⽤ICE,但是也可以独⽴于ICE的运⾏。值得⼀提的是,TURN协议本⾝是STUN的⼀个拓展,因此绝⼤部分TURN报⽂都是STUN类型的,作为STUN的⼀个拓展,TURN增加了新的⽅法(method)和属性(attribute)。
操作概述
在典型的情况下,TURN客户端连接到内⽹中,并且通过⼀个或者多个NAT到达公⽹,TURN服务器架设在公⽹中,不同的客户端以TURN 服务器为中继和其他peer进⾏通信,如下图所⽰:
Peer A
Server-Reflexive    +---------+
Transport Address  |        |
192.0.2.150:32102  |        |
|              /|        |
TURN              |            / ^|  Peer A |
Client’s              Server            |          /  ||        |
Host Transport        Transport        |        //  ||        |
Address              Address          |      //    |+---------+
10.1.1.2:49721      192.0.2.15:3478    |+-+  //    Peer A
|              |              ||N| /      Host Transport
|  +-+        |              ||A|/        Address
|  | |        |              v|T|    192.168.100.2:49582
|  | |        |              /+-+
+---------+|  | |        |+---------+  /              +---------+
|        ||  |N|        ||        | //              |        |
| TURN    |v  | |        v| TURN    |/                |        |
| Client  |----|A|----------| Server  |------------------|  Peer B |
|        |    | |^        |        |^                ^|        |
|        |    |T||        |        ||                ||        |
+---------+    | ||        +---------+|                |+---------+
| ||                    |                |
| ||                    |                |
+-+|                    |                |
|                    |                |
|                    |                |
Client’s                  |            Peer B
Server-Reflexive    Relayed            Transport
Transport Address  Transport Address  Address
192.0.2.1:7000      192.0.2.15:50000    192.0.2.210:49191
在上图中,左边的TURN Client是位于NAT后⾯的⼀个客户端(内⽹地址是10.1.1.2:49721),连接公⽹的TURN服务器(默认端⼝3478)后,服务器会得到⼀个Client的反射地址(Reflexive Transport Address, 即NAT分配的公⽹IP和端⼝)192.0.2.1:7000,此时Client会通过TURN命令创建或管理ALLOCATION,allocation是服务器上的⼀个数据结构,包含了中继地址的信息。服务器随后会给Client分配⼀个中继地址,即图中的192.0.2.15:50000,另外两个对等端若要通过TURN协议和Client进⾏通信,可以直接往中继地址收发数据即可,TURN服务器会把发往指定中继地址的数据转发到对应的Client,这⾥是其反射地址。
Server上的每⼀个allocation都唯⼀对应⼀个client,并且只有⼀个中继地址,因此当数据包到达某个中继地址时,服务器总是知道应该将其转发到什么地⽅。但值得⼀提的是,⼀个Client可能在同⼀时间在⼀个Server上会有多个allocation,这和上述规则是并不⽭盾的。
传输
在协议中,TURN服务器与peer之间的连接都是基于UDP的,但是服务器和客户端之间可以通过其他各种连接来传输STUN报⽂,⽐如
TCP/UDP/TLS-over-TCP. 客户端之间通过中继传输数据时候,如果⽤了TCP,也会在服务端转换为UDP,因此建议客户端使⽤UDP来进⾏传输.⾄于为什么要⽀持TCP,那是因为⼀部分防⽕墙会完全阻挡UDP数据,⽽对于三次握⼿的TCP数据则不做隔离.
分配(Allocations)
要在服务器端获得⼀个中继分配,客户端须使⽤分配事务. 客户端发送分配请求(Allocate request)到服务器,然后服务器返回分配成功响应,并包含了分配的地址.客户端可以在属性字段描述其想要的分配类型(⽐如⽣命周期).由于中继数据实现了安全传输,服务器会要求对客户端进⾏验证,主要使⽤STUN的 long-term credentail mechanism.
发送机制(Send Mechanism)
client和peer之间有两种⽅法通过TURN server交换应⽤信息,第⼀种是使⽤Send和Data⽅法(method),第⼆种是使⽤通道(channels),两种⽅法都通过某种⽅式告知服务器哪个peer应该接收数据,以及服务器告知client数据来⾃哪个peer.
Send Mechanism使⽤了Send和Data指令(Indication).其中Send指令⽤来把数据从client发送到server,⽽Data指令⽤来把数据从server发送到client.
四、ICE(Interactive Connectivity Establishment)
ICE跟STUN和TURN不⼀样,ICE不是⼀种协议,⽽是⼀个框架(Framework),它整合了STUN和TURN。
其模型如下:
如上图所⽰,如果A想与B通信,那么其过程如下:
1). A收集所有的IP地址,并出其中可以从STUN服务器和TURN服务器收到流量的地址;
2). A向STUN服务器发送⼀份地址列表,然后按照排序的地址列表向B发送启动信息,⽬的是实现节点间的通信;
3). B向启动信息中的每⼀个地址发送⼀条STUN请求;
4). A将第⼀条接收到的STUN请求的回复信息发送给B;
5). B接到STUN回复后,从中出那些可在A和B之间实现通信的地址;
6). 利⽤列表中的排序列最⾼的地址进⼀步的设备间通信。
由于该技术是建⽴在多种NAT穿透协议的基础之上,并且提供了⼀个统⼀的框架,所以ICE具备了所有这些技术的优点,同时还避免了任何单个协议可能存在的缺陷。因此,ICE可以实现在未知⽹络拓扑结构中实现的设备互连,⽽且不需要进⾏对⼿配置。另外,由于该技术不需要为VoIP流量⼿动打开防⽕墙,所以也不会产⽣潜在的安全隐患。
五、参考⽂章:
1). P2P通信标准协议(⼀)之STUN:
2). STUN和TURN技术浅析:
3). P2P技术详解(四):P2P技术之STUN、TURN、ICE详解:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。