webrtc-candidate形成分析
背景
由于NAT的限制,NAT后的设备无法直接P2P通信,出现了ICE(Interactive Connectivity Establishment)技术来进行通信。WebRTC就使用了ICE技术进行通信。
ICE过程会在通信的两端形成各自的Candidate
,每个Candidate
代表了一个候选的通信端点。两端各自创建通信端口,通常每个网卡对创建一个UDP
通信端口,每个网卡针对每个TURN
服务器创建一个TURN
通信端口,在端口上收集对应类型Candidate
,通信的两端通过信令交换各自的Candidate
,然后用本端的的每个通信端口的Candidate
和对方的每个Candidate
进行两两配对尝试通信(注意通信端口并不等价于Candidate
,一个UDP通信端口上可能会有多个Candidate
,UDP端口用host
类型的Candidate用于配对),最终挑选一对可用的Candidate
用于传输数据。每两个Candidate
配对会形成一条传输通道,这个传输通道webrtc的代码中叫做Connection
,在webrtc-internals
调试界面中叫做Candidate-Pair
。通信端自己的这方的Candidate
叫做Local-Candidate
,对方的Candidate
叫做Remote-Candidate
。当然在对端的视角就是反过来。
由于ICE中大部分情况都是使用UDP协议,所以本文仅讨论UDP协议通信
Candidate形成
Candidate
在形成的过程中根据网络情况会形成4种Candidate
:
host(Host Candidate)
host
类型的Candidate
就是本机地址,即网卡绑定的地址,所以每个端一定会有自己的host
类型Candidate
,如果有多个网卡,那么就会形成多个host
类型Candidate
。
host
类型的Candidate
代表的是未经NAT转换的原始地址,所以这种类型的Candidate
通常只在局域网内才会联通(不排除一些特殊网络情况)。
srflx(Sever Reflexive Candidate)
srflx
类型Candidate
就是本机的NAT映射地址,本机发送UDP数据经过NAT的转换后,会被NAT映射一个NAT外的地址,本端通过使用STUN
协议和STUN
服务器通信,STUN
服务器通过查看STUN
协议请求包的来源地址来获取这个地址并通过STUN
将此地址添加在XOR_MAPPED_ADDRESS
属性中回复给来源端。因为通常本机的不同网卡会被映射为不同的地址,所以如果有多个网卡,也会形成多个srflx
类型Candidate
。
srflx
类型Candidate
地址不会用做Local-Candidate
配对,只会发往对端口,对端用来作为Remote-Candidate
进行配对尝试,因为这个地址本就是NAT外部看到的地址,只有对NAT外部的端才有意义,本机处于NAT内部,使用此地址无实际的意义。
但是有时会看到Local-Candidate
的类型是srflx
,这种情况是在配对的过程中本端向某一个Remote-Candidate
发送STUN
请求后收到了对端的STUN
回复,STUN
回复中会使用STUN
协议的XOR_MAPPED_ADDRESS
属性标明对端之前收到的STUN
请求的来源地址,如果本端发现STUN
回复中的XOR_MAPPED_ADDRESS
属性值和本端之前收集的某一个Local-Candidate
一致,那么说明对端是通过本端在NAT映射后的地址(既srflx
类型Candidate
的地址)通信的,这种情况将这个配对的Local-Candidate
更新为匹配到的srflx
类型Candidate
。
prflx(Peer Reflexive Candidate)
prflx
类型Candidate
是一种比较特殊的Candidate
,它的特殊之处在于它不是主动收集而来,而是直接用户填写或者在配对尝试过程中形成的。prflx
类型Candidate
和srflx
类型Candidate
有些类似,它也是经过NAT映射之后的地址,区别在于,它并不是通过STUN
服务器提前收集得到的,而是直接收到的数据包中。
从webrtc的源码分析可知,有3中情况会形成prflx
类型Candidate
:
-
webrtc开始通信后,本端开始自动收集
Candidate
,然后将收集到的Candidate
发送到对端作为Remote-Candidate
,同样对端也会把收集到的Candidate
发过来,作为Remote-Candidate
,如果提前能够确定在当前网络中对端有一个可用的映射地址可用,那么此时可以手动构造一个Remote-Candidate
,加入本端webrtc连接的Remote-Candidate
列表。当然这中情况非常罕见,只有及其特殊的网络情况才适用。 -
当配对的过程中本端向某一个
Remote-Candidate
发送STUN
请求后收到了对端的STUN
回复,STUN
回复中会使用STUN
协议的XOR_MAPPED_ADDRESS
属性标明对端之前收到的STUN
请求的来源地址,如果本端发现STUN
回复中的XOR_MAPPED_ADDRESS
属性值没有和当前接收数据的端口已经收集到的任何Local-Candidate
地址相符,那么就认为出现了一个prflx
类型Local-Candidate
,其地址为XOR_MAPPED_ADDRESS
属性的值。因为XOR_MAPPED_ADDRESS
属性标明对端之前收到的STUN
请求的来源地址,也就是说对端之前收到了这个地址发送的STUN
请求,那么说明本端发送的数据被映射到了从这个地址发出,但这个地址并不是之前通过STUN
服务器探测到的NAT映射地址,这可能是NAT将目的地不同的请求映射为不同的地址(对称性NAT)。 -
当收到未知来源(即UDP包来源地址不匹配任何
Remote-Candidate
或可能得服务器地址)的STUN
请求,那么就认为出现了一个prflx
类型Remote-Candidate
。这可能是对端NAT将目的地不同的请求映射为不同的地址(对称性NAT)。这个新的prflx
类型Remote-Candidate
仅可以用于和收到此请求的端口的Local-Candidate
用于配对。
relay(Relayed Candidate)
relay
类型Candidate
是转发类型的Candidate
,所有的数据都先发送到TURN
服务器,再由服务器进行转发发送和接收到时如此。相当于TURN
服务器成为了一个代理。
当Webrtc创建连接时传入了TURN
服务器的信息,那么每个网卡针对每个TURN
都会认证后分配一个中继地址,这个中继地址就是一个relay
类型Candidate
,当使用relay
类型Candidate
作为Local-Candidate
时,将数据发送给TURN
服务器,TURN
服务器使用中继地址转发至目的地,当使用relay
类型Candidate
作为Remote-Candidate
时,将要发往对端的将数据发往中继地址,TURN
服务器由中继地址接收数据转发给对端。