WebRTC 演示和实际生产环境运行之间存在明显的差距,而这种差距通常存在于 TURN 层。你的演示在干净的网络环境下可能运行良好,但一旦真实用户身处 NAT、企业防火墙和移动网关之后,如果没有 TURN 层的支持,通话就会中断。
为什么 TURN 如此重要
要理解 TURN 的重要性,需要一些背景知识:WebRTC 支持两个端点之间的媒体传输。这些端点可以是两个直接通信的用户(P2P),也可以是用户连接到媒体服务器的情况,后者在 OpenVidu、Google Meet 或 Zoom 等平台上很常见,服务器接收每个参与者的视频并将其分发给其他参与者。无论哪种情况,大多数端点都位于带有 NAT 的路由器之后,从而隐藏了它们的真实 IP 地址,而 STUN 和 TURN 正是在这种情况下发挥作用。STUN 允许端点发现其从外部可见的公网 IP 地址,以便两个端点可以相互找到并尝试建立直接连接。当直接连接无法实现时,TURN 就是备选方案:一个中间服务器接收来自一个端点的流量并将其转发到另一个端点,在 NAT 或防火墙阻止直接路径时充当桥梁。实际上,还有更多细微差别(ICE,即协调连接尝试的框架;候选类型、SDP 协商……)
究竟有多少人最终需要使用备用方案?比你想象的要多。Philipp Hancke 的一项小型研究表明,高达 17.7% 的会话会经过 TURN 中继。而这些数据来自 2017 年:随着 CGNAT(移动运营商用于在数千用户之间共享单个公网 IP 的大规模 NAT 技术)在移动网络中的兴起,以及企业防火墙日益严格的限制,我们有理由相信,到了 2026 年,这个数字还会更高。

TURN 层是 WebRTC 中那些默默无闻却至关重要的组成部分之一:它每天都要应对防火墙策略的挑战,如果配置错误,其强大的功能甚至会成为攻击的入口,而且它牵涉到大量的运维决策,最终发展成一个需要独立运维团队的基础设施项目。
本文将探讨 TURN 层为何不可或缺,为何其运维成本远超预期,以及 OpenVidu 如何将其融入平台,使其不再是那种无人问津、人人都说“这服务与我无关”的传统服务器。
运行 TURN 很简单,但要正确运行 TURN 却并非易事
让我们先来谈谈如何部署一个简单的 TURN 服务器,然后看看其中可能出现的所有问题。
作为参考的开源 TURN 服务器 coturn 是一个由社区维护的优秀项目,该项目非常活跃且维护良好。TURN 是一个复杂的协议,它可能是一把双刃剑,这也正是配置错误如此容易发生的原因。导致其难以操作的并非 coturn 的实现缺陷,而是协议本身。
原则上,部署一个基础的 coturn 实例相当简单。你需要一台安装了 Docker 和 Linux 的机器、一个公网 IP 地址,以及一个开放的中继端口范围。按照使用默认端口的标准部署流程,你的 coturn docker-compose 文件可能如下所示:
services:
coturn:
container_name: coturn
image: coturn/coturn:latest
restart: always
network_mode: host
command:
- --realm=myrealm
- --fingerprint
- --listening-ip=0.0.0.0
- --external-ip=$$(detect-external-ip)
- --listening-port=3478
- --min-port=40000
- --max-port=50000
- --log-file=stdout
- --verbose
- --lt-cred-mech
- --user=<USERNAME>:<PASSWORD>
你可能会觉得这样就够了,认为配置好 TURN 服务器后,客户端应该就能通过用户名和密码使用它了……其实,并非如此。有几点值得指出:
- 用户账号是固定的。凭证必须以某种方式传递给客户端,如果凭证是静态的,那么任何在加载你的视频会议网页应用时截获这些密钥的用户,将来都可以利用它们将你的 TURN 服务器作为代理,甚至试图访问你基础设施中的内部服务。
- 端口 3478 并非总是允许的。虽然它是默认端口和推荐端口,但有时最好在 TCP 端口 443 上部署 TURN,因为该端口是 HTTPS 端口,也是 UDP 协议下的默认 QUIC 端口,而且在任何防火墙上,它都是最有可能开放的端口。
- 没有 TLS 配置。虽然可以进行配置,但这样就需要额外的系统来管理证书、为 coturn 配置证书,并且在证书每次续期时都要重启服务;或者使用反向代理来处理 TLS 终止并将流量重定向到 coturn。这本身就已经是一个不简单的额外步骤。你也可以选择不使用 TLS,但那样的话,那些身处极度受限网络、只能通过 TLS 使用 TURN 的 0.5% 用户将完全无法使用你的服务。
- 无法实现扩展。如果你的用户普遍处于极度受限的网络环境中,那么即使扩展了媒体服务器,如果 TURN 服务器无法扩展到足以服务于那 17–22% 需要中继的用户,也无济于事。
- 缺乏安全加固。若未明确阻止对内部网络范围的对等连接,持有有效凭证的用户可能会尝试将您的 TURN 服务器作为开放代理,以此访问内部服务(例如 AWS 的元数据服务),甚至访问在 localhost 上暴露的管理服务。
所以,为了解决所有这些问题,我们需要:
- 一种用于生成临时凭证的系统,通过信令分发,并随会话一起过期。
- 支持端口 443 上的传输协议,包括 TCP/TLS 和 UDP。
- 用于管理 TLS 证书并将其配置为 TURN 的系统,或者用于处理 TLS 终止并将流量重定向到 TURN 的反向代理。
- 一种自动扩展系统,随着媒体服务器的增加,也会增加 TURN 服务器。
- 默认情况下会启用安全加固措施,包括仅使用 UDP 协议向对等节点转发数据、设置对等节点 IP 地址与媒体节点 IP 地址的允许列表,以及将转发端口范围限制在已配置的媒体端口范围内。(这仅在存在媒体服务器时才适用。即使所有连接均为严格的 P2P 模式,其他四点也同样适用。)
所有这些功能都可以用 coturn 实现,但都不简单,大多数团队在生产环境中都会遇到这些问题。好消息是 OpenVidu 已经实现了这些功能,不仅如此:OpenVidu 的架构使得 TURN 不再是一个需要单独配置的服务,而是成为了每个媒体节点的一个属性。让我们来看看它是如何实现的。
使用 OpenVidu 无需再使用 TURN
首先,我们应该记住,OpenVidu 是一个视频会议平台,它提供了必要的抽象层,因此您无需担心 WebRTC,当然也无需担心 TURN。那么,OpenVidu 究竟为 TURN 提供了哪些功能呢?
OpenVidu v3 使用嵌入在每个媒体节点中的 Pion TURN 服务器,因此每个媒体节点都包含一个 TURN 中继。接下来,我们将逐一介绍构建稳健的 TURN 部署所需的各项功能,以及 OpenVidu 如何实现这些功能。
- 一种用于生成临时凭证的系统,通过信令分发,并随会话一起过期。
OpenVidu 会在每位参与者加入房间时为其生成一个短期有效的用户名/密码对,并通过信令将其与 TURN 服务器 URL 一起传递给客户端。默认情况下,这些凭据的有效期为5 分钟(TTL 为 300 秒)。
- 支持端口 443 上的传输协议,包括 TCP/TLS 和 UDP。
OpenVidu 启用了 UDP 443 和 TCP 443 端口的 TURN 功能,并支持 TLS,因此即使在网络限制非常严格的地区,每个用户也能连接。
- 用于管理 TLS 证书并将其配置为 TURN 的系统,或者用于处理 TLS 终止并将流量重定向到 TURN 的反向代理。
OpenVidu 使用 Caddy 作为反向代理来处理 TLS 终止并将流量重定向到 Pion TURN 服务器。Caddy 通过 Let’s Encrypt 或自定义证书自动管理 TLS 证书,因此无需在证书续订时手动配置或重新加载 TURN 服务器。此外,主节点中配置的 Caddy 服务器负责将 HTTPS 信令流量与 TURN-TLS 流量进行解复用,从而使两者能够共享同一域名而不会相互干扰。此设置确保在网络受限的情况下,用户仍可使用 TURN over TLS 服务,同时为使用同一域名进行信令和 TURN 服务的所有用户提供无缝体验。
- 一种自动扩展系统,随着媒体服务器的增加,也会增加 TURN 服务器。
OpenVidu 会根据媒体节点自动扩展 TURN 功能。由于每个媒体节点都包含 TURN,因此添加媒体节点的同时也会添加一个 TURN 中继。唯一例外的情况是使用 TLS 传输的 TURN,因为主节点需要处理 HTTPS 信令流量和 TURN-TLS 流量的解复用,但考虑到 TURN-TLS 流量仅占连接数的 0.5%,其影响微乎其微。
- 默认情况下会加强安全性,仅支持 UDP 中继到对等方,允许对等方 IP 地址访问主节点和媒体节点 IP 地址,并将中继端口范围限制为配置的媒体端口范围。
在 OpenVidu,我们采纳了各项安全加固建议,同时始终将平台易用性放在首位。根据Enable Security 的建议,我们采取了以下措施:
- 集群已知 IP 地址的允许列表:对等连接只能建立到集群已知的 IP 地址。如果节点拥有公网 IP 地址且可直接从互联网访问,TURN 服务器将只能与集群内部的 IP 地址建立对等连接。如果节点位于 NAT 之后,对等流量将被限制在集群的私有 IP 地址范围内。
- 为了防止 TCP 到对等方的滥用攻击,对等方流量被限制为仅支持 UDP 的中继:TCP 分配(RFC 6062)默认禁用,但可通过配置启用。通过阻止 TURN 服务器与对等方建立出站 TCP 连接,可以有效阻止攻击者利用中继作为 TCP 代理访问内部服务。虽然这并不能完全阻止拥有有效凭据的攻击者滥用基础设施,但可以显著减少攻击途径。
- 限制中继端口范围。在 OpenVidu 部署于 NAT 环境中时,中继只会将流量转发到配置的媒体端口范围内的目标端口,而不是整个临时空间。这可以将攻击范围限制在特定的端口范围内,而不是所有可能的端口。
- 凭证的有效期很短(见上文 TTL),并且使用服务器端密钥通过 SHA-256 生成,这使得它们不可预测且难以猜测。
结论
TURN协议理论上看似简单,但实际应用却十分复杂。该协议的设计初衷是将任意数据包转发到任意目的地;然而,扩展性和运维难度都很大,如何在保证良好安全性的前提下又不影响用户体验,更是难上加难。
正确的抽象方式(也是 OpenVidu 采用的方式)是将 TURN 视为每个处理媒体的节点的一部分,而不是一个补充服务:它与 TURN 位于同一位置,自动扩展,默认强化,并由临时凭证驱动。OpenVidu的部署拓扑在单节点、弹性模式和高可用性模式下都实现了这种抽象。
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/webrtc/67665.html