WebRTC(五):TURN协议

TURN(Traversal Using Relays around NAT)协议是一个网络协议,旨在解决 NAT(网络地址转换)和防火墙 环境下的 UDP/TCP通信问题。它通常与 STUN 和 ICE 协议一起使用,广泛应用于 WebRTC、SIP 和视频会议等实时通信场景中。

为什么需要 TURN?

  1. NAT 问题

NAT 会屏蔽内网客户端的真实地址,使两个处于不同 NAT 环境的客户端 无法直接建立连接

  1. STUN 的局限

STUN 可以帮助客户端获取自己的公网 IP 和端口,但当:

  • 双方都在对称型 NAT 后面,
  • 或者存在严格的防火墙时,

STUN 穿透失败,这时就需要 TURN。

工作原理

TURN 的基本思想是:

通过中继服务器(TURN Server)转发媒体流量,绕过 NAT/防火墙。

工作流程

  • 阶段1:客户端与 TURN Server 建立连接(Allocate)

    • Step 1.1:客户端发起 Allocate 请求

      • 类型:Allocate Request
      • 内容:希望使用的传输协议(UDP/TCP)、Lifetime 等
      • 信令方式:基于 STUN over UDP/TCP
      text 复制代码
      Client A --> TURN Server
      Message: Allocate Request
      Attributes: REQUESTED-TRANSPORT=UDP
    • Step 1.2:TURN Server 分配中继地址

      • 返回:Allocate Success Response

      • 包含字段:XOR-RELAYED-ADDRESS(中继地址)、XOR-MAPPED-ADDRESS(客户端映射地址)

      text 复制代码
      TURN Server --> Client A
      Message: Allocate Success
      XOR-RELAYED-ADDRESS: 203.0.113.1:54320  ← 中继地址
  • 阶段2:建立 Permission(通信授权)

    为了安全,TURN Server 默认不允许所有对端通信,必须显式授权。

    • Step 2.1:CreatePermission 请求

      text 复制代码
      Client A --> TURN Server
      Message: CreatePermission
      XOR-PEER-ADDRESS: 对端 B 的公网地址
    • Step 2.2:成功响应

    • 若授权成功,返回 CreatePermission Success Response

    • 默认权限 300 秒失效

  • 阶段3:数据通道建立(Send Indication 或 ChannelBind)

​ TURN 支持两种数据通道:

通道方式 描述 性能
Send/Receive Indication 使用完整 STUN 消息发送数据 灵活,开销大
ChannelData 映射通道编号,提高效率 更快,推荐
  • Step 3.1:发送 ChannelBind 请求
text 复制代码
Client A --> TURN Server
Message: ChannelBind
XOR-PEER-ADDRESS: Client B
CHANNEL-NUMBER: 0x4000-0x7FFF(客户端分配)
  • Step 3.2:TURN Server 回复成功绑定

    • 之后,Client A 可以通过 ChannelData 消息直接发送媒体数据。
  • 阶段4:媒体数据中继传输

    • A → B 流程
    text 复制代码
    Client A --> TURN Server
    Message: ChannelData 或 Send Indication
    text 复制代码
    TURN Server --> Client B
    Message: UDP/TCP 数据包
    • B → A 反向流

      text 复制代码
      Client B --> TURN Server(发往分配的 relayed address)
      TURN Server --> Client A(通过 Channel 或 Data Indication)
  • 阶段5:Refresh 保活

    • TURN allocation 默认 600秒过期

    • 客户端需周期性发送 Refresh Request 保活

      text 复制代码
      Client A --> TURN Server
      Message: Refresh Request
      LIFETIME: 600

流程时序图:

text 复制代码
客户端A                             TURN服务器                             客户端B
   |                                    |                                      |
   |-------- Allocate Request --------->|                                      |
   |<------ Allocate Response ----------|                                      |
   |                                    |                                      |
   |--- CreatePermission (B的IP) ----->|                                      |
   |<--- CreatePermission Success ------|                                      |
   |                                    |                                      |
   |-------- ChannelBind (B的IP) ----->|                                      |
   |<----- ChannelBind Success ---------|                                      |
   |                                    |                                      |
   |---- ChannelData(B的数据) ------->|                                      |
   |                                    |-----> 转发数据到 客户端B ---------->|
   |                                    |<----- 客户端B发来响应数据 -----------|
   |<--- ChannelData(返回数据) -------|                                      |
   |                                    |                                      |
   |--------- Refresh Request --------->|                                      |
   |<-------- Refresh Response ---------|                                      |

TURN 与 STUN、ICE 的关系

协议 作用
STUN 获取公网地址,尝试打洞
TURN 中继传输,保证连接
ICE 综合使用 STUN/TURN,选择最优路径(直接连接优先)

TURN 是一种最后手段 ,因为它会增加 延迟带宽成本

协议详解

协议标准

TURN 协议定义在以下 RFC 中:

  • RFC 5766:TURN 协议标准
  • RFC 5389:STUN 基础
  • RFC 6062:支持 TCP 的 TURN
  • RFC 6156:IPv6 支持

通信流程详细图解

rust 复制代码
客户端A ---------> TURN服务器 <--------- 客户端B
        Allocate            Send Indication
        Refresh             Data Channel
        Send/Receive        Permissions

主要步骤:

  • Allocate Request:客户端请求分配中继地址;
  • Allocate Success Response:服务器返回一个公网 IP+端口(Relayed Address);
  • CreatePermission:允许某个对端向这个中继地址发送数据;
  • Send Indication / Data Indication:发送或接收数据;
  • Refresh:保持分配有效(每300秒刷新);
  • Channel Bind(可选):绑定 Channel,降低通信成本;

消息结构(基于 STUN)

TURN 消息与 STUN 类似,由以下字段组成:

  • Message Type:请求/响应/指示类型
  • Transaction ID:用于匹配请求与响应
  • Attributes
    • XOR-RELAYED-ADDRESS:返回的中继地址
    • LIFETIME:分配有效期
    • DATA:要中继的实际数据
    • XOR-PEER-ADDRESS:目标地址

TURN Server 实现

常见开源 TURN Server:

名称 简介
Coturn 最流行的 TURN server,支持 STUN、TURN、TLS 等协议
restund 轻量级实现
rfc5766-turn-server 老旧项目,已被 Coturn 替代

Coturn 配置文件示例:

bash 复制代码
listening-port=3478
relay-ip=your_public_ip
realm=yourdomain.com
user=username:password

优缺点

优点:

  • 100% 可达性:即使双方都在对称 NAT 后,也能通信;
  • 标准化:已被 WebRTC、SIP 等广泛采用;

缺点:

  • 服务器成本高:带宽开销大;
  • 延迟增加:所有流量都要绕行服务器;
  • 复杂度增加:协议较 STUN 更复杂;