一、背景

在开发 WebRTC 应用时,ICE(Interactive Connectivity Establishment)协议用于通过 STUN(Session Traversal Utilities for NAT)和 TURN(Traversal Using Relays around NAT)服务器来进行 NAT 穿透,确保客户端能够在不同网络环境中建立连接。在大多数情况下,STUN 服务器能够有效地穿透 NAT,并帮助客户端获取公共 IP 地址。然而,在某些网络环境中(例如,Linux 服务器环境),仅使用 STUN 服务器可能无法成功建立 WebRTC 连接,此时需要 TURN 服务器作为中继来保证连接的稳定性。

二、问题描述

在开发过程中,在 Windows 环境中通过配置 STUN 服务器成功建立了 WebRTC 连接。然而,当将应用部署到 Linux 服务器上时,尽管配置了相同的 STUN 服务器,连接却始终无法建立。经过调试,发现是由于 NAT 穿透问题,导致 STUN 无法正常工作,最终通过配置 TURN 服务器成功解决了问题。

三、解决方案

1. STUN 服务器在 Windows 中的表现

在 Windows 环境下,由于操作系统和网络配置的不同,STUN 服务器通常能够顺利穿透 NAT,帮助 WebRTC 客户端获取公共 IP 地址。STUN 通过发送请求到公共 STUN 服务器(如 stun:stun.l.google.com:19302)来获取客户端的外部地址,这通常在家庭或办公室网络等环境中是可行的。

Windows 中使用 STUN 的正常配置:

const configuration = {
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' }
    ]
};

2. STUN 服务器在 Linux 服务器中的问题

然而,在 Linux 服务器上,尤其是云服务器或数据中心环境,网络配置通常会更加严格,可能会使用更复杂的 NAT 设置或防火墙规则。这种情况下,STUN 服务器无法成功穿透 NAT,导致 WebRTC 连接无法建立。原因可能是:

  • 严格的 NAT 配置:Linux 服务器通常处于严格的企业或云网络环境中,使用端口映射或网络地址转换(NAT)策略。这些 NAT 配置阻止了 STUN 服务器从客户端接收到正确的外部 IP 地址。

  • 防火墙和端口问题:很多云服务提供商(如 AWS、RunPod 等)默认会阻止 UDP 流量或限制某些端口,这会影响 STUN 服务器的正常工作。

3. 使用 TURN 服务器解决问题

TURN 服务器作为 NAT 穿透的中继服务器,可以帮助客户端和服务器之间进行数据传输,即使 STUN 服务器无法工作。TURN 服务器会接收来自客户端的数据,并将其转发到目标服务器或其他客户端,从而确保 WebRTC 连接的稳定性。

通过配置 TURN 服务器,WebRTC 客户端即使在复杂的 NAT 环境下,依然能够建立连接。TURN 服务器通常提供用户名和密码认证,以避免滥用。

TURN 服务器配置示例:

const configuration = {
    iceServers: [
        { 
            urls: 'turn:freestun.net:3478',  // TURN 服务器地址
            username: 'free',  // 用户名
            credential: 'free'  // 密码
        }
    ]
};

在这种情况下,TURN 服务器会充当中继,确保即使 STUN 服务器无法穿透 NAT,WebRTC 连接依然能够成功建立。

4. 在后端配置 TURN 服务器

不仅仅是前端需要配置 TURN 服务器,后端也需要使用相同的 TURN 服务器进行配置,以确保服务器端与客户端之间能够顺利进行 ICE 候选交换。

后端 Python 配置示例:

ice_servers = [
    RTCIceServer(
        urls="turn:freestun.net:3478",  # TURN 服务器的地址
        username="free",  # 用户名
        credential="free"  # 密码
    )
]

configuration = RTCConfiguration(ice_servers)

# 初始化 RTCPeerConnection
pc = RTCPeerConnection(configuration=configuration)

解决的关键问题

  1. NAT 穿透问题:在 Windows 环境下,STUN 服务器通常可以有效穿透 NAT,而在 Linux 环境下,严格的 NAT 配置或防火墙可能会导致 STUN 服务器无法正确获取外部 IP 地址。此时,使用 TURN 服务器作为中继就显得尤为重要。

  2. TURN 服务器配置:配置 TURN 服务器时,必须确保其可访问,并且网络允许通过该服务器进行数据传输。使用公共 TURN 服务器时,确保提供正确的用户名和密码。如果公共 TURN 服务器不可用,可以选择搭建自己的 TURN 服务器。

  3. 防火墙和网络设置:在服务器环境中,尤其是云服务环境下,可能需要确保 UDP 端口(例如 3478)没有被防火墙阻止,并且 NAT 配置不会干扰 STUN/TURN 服务器的正常工作。

四、常见错误和排查方法

  1. 无法连接 TURN 服务器:如果出现 TURN host lookup received error 错误,通常是由于 TURN 服务器不可用或网络无法访问。此时,可以通过 telnetnc 工具测试服务器是否可达:

telnet turn:freestun.net 3478
  1. ICE 候选没有交换:如果 ICE 连接始终处于 checking 状态,可以在 onicecandidate 事件中打印日志,检查是否有候选信息被交换。如果没有候选信息,可能是由于 TURN 服务器没有正确响应。

  2. STUN 服务器配置问题:确保配置了有效的 STUN 服务器,并检查是否能够获取正确的公网 IP 地址。如果 STUN 服务器无法工作,TURN 服务器将成为唯一的连接方式。

总结

在开发 WebRTC 应用时,STUN 和 TURN 服务器是实现 NAT 穿透和稳定连接的关键。在 Windows 环境中,STUN 服务器通常能够正常工作,但在 Linux 服务器环境中,严格的 NAT 配置和防火墙规则可能会导致 STUN 服务器无法穿透 NAT,此时需要使用 TURN 服务器作为中继。通过正确配置 TURN 服务器并确保网络环境的支持,我们可以成功解决 ICE 连接问题。