WebRTC 是2011年谷歌开源的媒体框架,可以在浏览器中进行实时音视频通信,它是为P2P通信设计的,开发者也可以自己搭建服务器作为通信的一端。在下面这些网络条件限制严格的场景下不能直接建立通信,需要借助中转服务器TURN(Traversal Using Relays around NAT)转发。
- 一端是对称型NAT,另一端是端口限制锥形NAT或者也是对称型NAT,无法建立P2P。这个工具可以检测自己网络的NAT类型https://github.com/aarant/pynat
- 对网络出口限制严格的环境,比如银行、政府单位,要求访问的外网IP地址需要加到其网关白名单。可以独立部署TURN服务器,将TURN的公网IP地址加到白名单。
- 对安全要求极端严格的防火墙,不允许UDP通信,甚至只允许TLS over 443端口的流量。
TURN 流程分析
协议分为三部分
1. 在TURN服务器上创建传输 资源,称为 allocation
2. indication 方式传输数据
3. channel 方式传输数据
要注意的是,这两种传输数据的方式是并列关系。三部分的流程时序图如下(图片链接 https://justme0.com/assets/pic/turn/seq.svg ),client参考WebRTC代码,server参考pion/turn代码。
1. 创建 allocation 资源
allocation是TURN服务器分配给客户端的资源,数据结构如下,列了主要的字段(详见 https://github.com/pion/turn/blob/master/internal/allocation/allocation.go#L23 )。以五元组 fiveTuple <clientIP, clientPort, svrIP, svrPort, protocol>标识一个allocation,protocol 最新的RFC文档规定有TCP/UDP/TLS/DTLS,pion暂未支持DTLS,服务端监听端口 svrPort 默认是3478 for TCP/UDP, 5349 for TLS/DTLS。
// FiveTuple is the combination (client IP address and port, server IP
// address and port, and transport protocol (currently one of UDP,
// TCP, or TLS)) used to communicate between the client and the
// server. The 5-tuple uniquely identifies this communication
// stream. The 5-tuple also uniquely identifies the Allocation on
// the server.
type FiveTuple struct {
Protocol
SrcAddr, DstAddr net.Addr
}
type Allocation struct {
RelayAddr net.Addr
Protocol Protocol
TurnSocket net.PacketConn
RelaySocket net.PacketConn
fiveTuple *FiveTuple
permissionsLock sync.RWMutex
permissions map[string]*Permission
channelBindingsLock sync.RWMutex
channelBindings []*ChannelBind
lifetimeTimer *time.Timer
}
allocation结构
特别关注数据结构中的 permissions 和 channelBindings 字段,permissions的key是peer端地址,channelBindings是数组,也是以peer端地址标识。下面对照时序图介绍流程。
1.1 STUN bind request
和STUN功能一样,返回client的IP和port,用于告知端上自己的出口地址,收集local candidate,服务端无状态。
1.2 allocation request
请求分配资源,请求参数中标识了在TURN和peer之间是UDP还是TCP,WebRTC client写死的UDP,注意RFC文档是规范&#x