彼此要了解对方的网络情况,这样才有可能找到一条相互通讯的链路。需要做以下两个处理。

  1. 获取外网IP地址映射。
  2. 通过信令服务器(signal server)交换“网络信息”。

理想的网络情况是每个浏览器的电脑都是公网IP,可以直接进行点对点连接。如图所示。

WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN_WebRTC

实际情况是我们的电脑和电脑之间都是在某个局域网中并且有防火墙,需要NAT(Network Address Translation,网络地址转换),如图所示。
WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN_WebRTC_02

在解决WebRTC使用过程中的上述问题的时候,我们需要用到STUN和TURN。

NAT

NAT(Network Address Translation,网络地址转换)简单来说就是为了解决IPV4下的IP地址匮乏而出现的一种技术。
举例就是通常我们处在一个路由器之下,而路由器分配给我们的地址通常为192.168.1.1 、192.168.1.2如果有n个设备,可能分配到192.168.1.n,而这个IP地址显然只是一个内网的IP地址,这样一个路由器的公网地址对应了n个内网的地址,通过这种使用少量的公有IP 地址代表较多的私有IP 地址的方式,将有助于减缓可用的IP地址空间的枯竭。如图所示。

WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN_WebRTC_03

NAT技术会保护内网地址的安全性,所以这就会引发个问题,就是当我采用P2P之中连接方式的时候,NAT会阻止外网地址的访问,这时我们就得采用NAT穿透了。
于是我们就有了如下的思路:我们借助一个公网IP服务器,Peer-A与Peer-B都往公网IP/PORT发包,公网服务器就可以获知Peer-A与Peer-B的IP/PORT,又由于Peer-A与Peer-B主动给公网IP服务器发包,所以公网服务器可以穿透NAT-A与NAT-B并发送包给Peer-A与Peer-B。
所以只要公网IP将Peer-B的IP/PORT发给Peer-A,Peer-A的IP/PORT发给Peer-B。这样下次Peer-A与Peer-B互相消息,就不会被NAT阻拦了。
WebRTC的NAT/防火墙穿越技术,就是基于上述的一个思路来实现的。在WebRTC中采用ICE框架来保证RTCPeerConnection能实现NAT穿越。

ICE

ICE(Interactive Connectivity Establishment,互动式连接建立)是一种框架,使各种NAT穿透技术(STUN,TURN…)可以实现统一。该技术可以让客户端成功地穿透远程用户与网络之间可能存在的各类防火墙。

STUN

NAT 的UDP简单穿越(Session Traversal Utilities for NAT)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间建立UDP通信。如图2-7所示,STUN服务器能够知道Peer-A以及Peer-B的公网IP及端口。

WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN_WebRTC_04

即使透过 STUN 服务器取得了公用 IP 位址,也不一定能建立连线。因为不同的NAT类型处理传入的UDP分组的方式是不同的。四种主要类型中有三种是可以使用STUN穿透:完全圆锥型NAT、受限圆锥型NAT和端口受限圆锥型NAT。但大型公司网络中经常采用的对称型 NAT(又称为双向NAT)则不能使用,这类路由器会透过NAT布署所谓的“Symmetric NAT限制”。也就是说,路由器只会接受你之前连线过的节点所建立的连线。这类网络就需要TURN技术。

TURN

TURN(Traversal Using Relays around NAT)是STUN/RFC5389的一个拓展,主要添加了Relay功能。如果终端在NAT之后, 那么在特定的情景下,有可能使得终端无法和其对等端(peer)进行直接的通信,这时就需要公网的服务器作为一个中继,对来往的数据进行转发。这个转发的协议就被定义为TURN。
在STURN服务器的基础上,再架设几台TURN服务器。在STUN分配公网IP失败后,可以通过TURN服务器请求公网IP地址作为中继地址。媒体数据由TURN服务器中转。如图所示。

WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN_WebRTC_05

当媒体数据走TURN中转,这种方式的带宽由服务器端承担。所以在架设中转服务时要考虑硬件及带宽。
提示:ICE跟STUN、TURN不一样,ICE不是一种协议,而是一个框架,它整合了STUN和TURN。

以上是WebRTC中经常用到的协议,STUN和TURN服务器我们使用coturn开源项目来搭建,地址为:https://github.com/coturn/coturn。也可以使用Golang技术开发的服务器来搭建,地址为:https://github.com/pion/turn。