使用 TURN Server 通过防火墙

2,419 阅读4分钟

先上结论:通过将内网中的 TURN service 端口映射可以实现在两个对称型 NAT 的里面的设备进行通信,使用 TURN server 通过防火墙方案可行。

一、问题现象

使用 WebRTC 过程中,有个成都的客户在使用中需要通过公网进行互动,客户有公网 IP,设备部署在内网,可以通过一个华为的路由器把服务器的端口映射出去,部署时发现客户的防火墙是对称型 NAT,打洞无法穿透,因为客户有 VPN,暂时通过 VPN 进行使用。

二、原因分析

通过学习 NAT 的类型和打洞原理知道,如果是对称型的网络,使用 STUN 打洞是无法成功的。

在学习的过程中看到一篇博客里面说通过将 TURN 部署在对称型的 NAT 里面,通过端口映射将 TURN Server 的监听端口暴露出去,可以解决对称型 NAT 打洞的问题,而且也不需要使用公网的服务器,但是只是提了一下,找不到具体的实现,具体哪篇博客目前找不到了。

后续在学习 《WebRTC 权威指南》 的时候看到下面这张图,进一步佐证了这个方案的可行性,后续了解到 TURN 服务器是 Client/Server 设计,理论上也是可以行的,遂开始搭建环境进行确认。

三、验证可行性

1. 使用 nc 测试端口监听

在客户环境的设备上使用 nc 工具监听 UDP 20000 端口,然后将防火墙上配置端口映射,将设备的 20000 端口映射到公网,然后在家里使用 nc 工具去连接映射后的公网地址和端口,观察客户环境的设备上是否可以接受到发送的数据。

# nc 监听 20000 端口
nc -ul 20000
# nc 连接映射后的公网地址和端口就
nc -u xxx.xxx.xxx.xxx 20000

连接成功后在控制台输入字符然后敲回车,客户环境中的设备上同步输出相同的内容,证明 Client/Server 模式使用端口映射可以进行通信。

2. 搭建 TURN server

使用 coturn 搭建 TURN server,搭建的步骤另外记录,测试的配置如下:

# TURN server name and realm
realm=192.168.100.221
server-name=turnserver

# Use fingerprint in TURN message
fingerprint

# IPs the TURN server listens to
# listening-ip=192.168.10.221

# External IP-Address of the TURN server
#external-ip=121.199.22.135

# Main listening port
listening-port=3478

# Further ports that are open for communication
min-port=20000
max-port=22000

# Enable verbose logging
verbose

# Specify the user for the TURN authentification
user=test:123456

# Enable long-term credential mechanism
lt-cred-mech

TURN server 启动后使用 webrtc.github.io/samples/src… 测试一下

3. 网络环境

两个网络,分别用手机 4G 做热点,一个模拟客户公司内网,一个模拟公网设备访问。

网络一:模拟客户公司内网

电信 4G 开热点,使用 JCG 路由器做 wifi 中继, NATTypeTester 测试结果:

  • NAT type:Symmetric
  • Local end: 0.0.0.0:59524
  • Public end:36.17.176.200:26597

网络二:模拟设备通过公网访问

移动 4G 开热点,使用笔记本连接手机热点,NATTypeTester 测试结果:

  • NAT type:Symmetric
  • Local end: 0.0.0.0:56586
  • Public end:223.104.244.91:3235

4. 设备连接

网络一中设备列表:

  • Janus 服务器:192.168.100.221
  • TURN server:192.168.100.221
  • 加入互动的电脑:192.168.100.108

网络二中的设备:

  • 笔记本,IP 地址未记录

5. 内网穿透

使用向日葵内网穿透将 Janus 互动服务器的 Web server 端口映射(tcp://192.168.100.221:443)出去,提供给公网的设备访问,映射后的访问地址为 https://39263k5f22.zicp.vip:43540

使用飞鸽内网穿透将 TURN server 的端口(udp://192.168.100.221:3478)映射出去,映射后的地址和端口为 free.svipss.top:51351

6. 修改网页代码,设置 TURN server

    const pc = new RTCPeerConnection({
      iceServers: [
        // { urls: 'stun:stun.opensight.cn' },
        {
          urls: ['turn:free.svipss.top:51351'],
          username: 'test',
          credential: '123456',
          credentialType: 'password',
        },
      ],
      iceTransportPolicy: 'all',
      iceCandidatePoolSize: '0',
      bundlePolicy: 'max-bundle',
      rtcpMuxPolicy: 'require',
      tcpCandidatePolicy: 'disable',
      IceTransportsType: 'nohost',
    });

7. 开始互动

网络一中的电脑访问内网地址 https://192.168.100.221 打开互动教室端后开始互动。

网络二中的笔记本打开公网访问地址 https://39263k5f22.zicp.vip:43540 加入互动。

四、验证结论,互动成功,方案可行

实际测试两台电脑可以成功进行互动,相互看见对方,证明通过 TURN service 端口映射可以实现在两个对称型 NAT 的里面的设备进行通信,使用 TURN server 通过防火墙方案可行。