webRTC TURN服务器搭建

发布于:2025-02-11 ⋅ 阅读:(29) ⋅ 点赞:(0)

背景:

前言:如果还不清楚webrtc可以先看读这个文章webrtc的RTCPeerConnection使用_new rtcpeerconnection-CSDN博客

webRTC的RTCPeerConnection通讯,是p2p的通讯,配置的时候需要填写个stun和turn服务器

举例:

const configuration = {
  iceServers: [
    { urls: "stun:stun.l.google.com:19302" },
    {
      urls: "turn:xxx.xxx.xxx.xxx:3478",
      username: "admin",
      credential: "123456",
    },
  ],
};

stun服务器负责尝试做NAT穿透,让2个设备可以点对点通讯,但大部分网络环境这个穿透会失败。
stun服务器的工作内容很简单,只管下发2个设备的信令信息,基本不占用资源。
在穿透失败后,webtrc会尝试通过turn服务器进行中继通讯,turn服务器此时做的事情类似路由器,通讯数据会先流经turn服务器,再中转,所以turn服务器需要消耗较多资源,特别是带宽资源

turn服务器搭建:

这里采用docker的coturn/coturn镜像

镜像地址:https://hub.docker.com/r/coturn/coturn
git地址:https://github.com/coturn/coturn

拉取镜像命令:

docker pull coturn/coturn

宿主机创建配置文件:/home/test/turnserver.conf
参考:https://www.wware.org/wide/yw/backups/turnserverconfig.html
内容如下,把ip给成自己的实际的ip:

#中继服务器监听的IP地址,直接写公网IP地址,可以指定多个IP
listening-ip=60.70.80.91
#中继服务器转发地址(本地IP地址将用于传递数据包的给每个端),和监听地址一样
relay-ip=60.70.80.91
#外部IP,直接写公网IP地址
external-ip=60.70.80.91
#打开fingerprint的注释,使用长期证书机制。
fingerprint
#打开密码验证,使用短期证书机制。
lt-cred-mech
#服务器名称,用于OAuth认证,默认和realm相同,直接填公网ip.部分浏览器本段不设可能会引发cors错误。
server-name=60.70.80.91
# TURN REST API的长期凭证机制范围,同样设为ip,同server-name.
realm=60.70.80.91
#移动的ICE(MICE)的规范支持。
mobility
#快捷的添加用户是使用user=XXX:XXXX的方式,可以添加多个。/var/db/turndb也工作,可以使用turnadmin来管理其中用户,可以添加多个。
user=admin:123456

 启动命令:

docker run -d -v /home/test/turnserver.conf:/etc/coturn/turnserver.conf --network=host --name my-turn-server coturn/coturn

测试:

打开 :https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
输入相应turn服务器信息

点击测试,如果有输出上面的srflx和relay 就说明这2个服务器都部署成功,coturn启动后会同时拥有stun和turn服务

也可以自己写个简单的html测试,双击打开即可

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>TURN Server Test</title>
  </head>
  <body>
    <h1>Testing TURN Server</h1>
    <pre id="output"></pre>

    <script>
      function testTurnServer(turnConfig) {
        const output = document.getElementById("output");
        const configuration = { iceServers: [turnConfig] };

        // 创建一个新的 RTCPeerConnection
        const pc = new RTCPeerConnection(configuration);

        // 当收集到新的 ICE 候选者时触发
        pc.onicecandidate = (event) => {
          if (event.candidate) {
            output.innerHTML += `ICE Candidate: ${JSON.stringify(event.candidate)}\n`;
            if (event.candidate.type === "relay") {
              output.innerHTML +=
                "Relay candidate found. TURN server is working.\n";
              cleanup();
            }
          } else {
            output.innerHTML += "ICE gathering complete.\n";
            cleanup();
          }
        };

        // 当 ICE 状态改变时触发
        pc.oniceconnectionstatechange = () => {
          output.innerHTML += `ICE Connection State: ${pc.iceConnectionState}\n`;
          if (pc.iceConnectionState === "failed") {
            output.innerHTML +=
              "ICE connection failed. Check TURN server configuration.\n";
            cleanup();
          }
        };

        function cleanup() {
          pc.close();
          //setTimeout(() => window.location.reload(), 2000); // 重新加载页面以重置状态
        }

        // 强制触发 ICE 候选者的收集
        setTimeout(() => {
          pc.createDataChannel("test"); // 创建一个数据通道来触发候选者收集
          pc.createOffer()
            .then((offer) => {
              return pc.setLocalDescription(offer);
            })
            .catch((error) => {
              console.error("Error creating offer:", error);
              output.innerHTML += `Error: ${error}\n`;
              cleanup();
            });
        }, 1000);
      }

      // 定义要测试的 TURN 服务器配置
      const turnServerToTest = {
        urls: "turn:xxx.xxx.xxx.xxx:3478",
        username: "admin",
        credential: "123456",
      };

      // 开始测试
      testTurnServer(turnServerToTest);
    </script>
  </body>
</html>

正常的输出结果: 

其他:

查看coturn容器的信息

进入容器:

docker exec -it my-turn-server  /bin/bash

 执行turnserver命令命令查看一些信息,例如版本信息

turnserver

例如我这边镜像的版本是 Coturn Version Coturn-4.6.3 'Gorst'