局域网内,即使不配置 stun/turn, webrtc 也是能音视频通话。如果在广域网环境,必须得有 turn 服务。那么自己构建一个 turn 服务就很有必要。不过广域网的 webrtc 对带宽的消耗也是很大。
STUN
STUN(Session Traversal Utilities for NAT,NAT 会话穿越应用程序)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的 Internet 端端口。这些信息被用来在两个同时处于 NAT 路由器之后的主机之间创建 UDP 通信。该协议由 RFC 5389 定义。(提供客户端检测自己的公共 IP 地址和端口)
STUN 并不是每次都能成功的为需要 NAT 通话设备分配 IP 地址的,P2P 在传输媒体流时,使用的本地带宽,在多人视频通话的过程中,通话质量的好坏往往需要根据使用者本地的带宽确定。
TURN
TURN 的全称为 Traversal Using Relays around NAT,是 STUN/RFC5389 的一个拓展,主要添加了 Relay 功能。如果终端在 NAT 之后, 那么在特定的情景下,有可能使得终端无法和其对等端(peer)进行直接的通信,这时就需要公网的服务器作为一个中继, 对来往的数据进行转发。这个转发的协议就被定义为 TURN。
在 STUN 分配公网 IP 失败后,可以通过 TURN 服务器请求公网 IP 地址作为中继地址。这种方式的带宽由服务器端承担,在多人视频聊天的时候,本地带宽压力较小,并且,根据 Google 的说明,TURN 协议可以使用在所有的环境中。(中继流量,当点对点连接不可用时,Coturn 会接管通信。)
ICE 跟 STUN 和 TURN 不一样,ICE 不是一种协议,而是一个框架(Framework),它整合了 STUN 和 TURN。coturn 开源项目集成了 STUN 和 TURN 的功能。
构建 coturn 镜像
不直接使用 coturn/coturn 镜像。以 coturn/coturn 构建一个本地镜像。
services/coturn/Dockerfile 文件
FROM coturn/coturn
compose.yaml 文件
coturn:
build:
context: './services/coturn'
image: my-coturn:1.0
然后构建镜像和将镜像打包到本地。
docker-compose build coturn
docker save -o my-coturn.tar my-coturn:1.0
加载镜像
构建镜像可以在本地构建也可以在服务端构建。多搞一个自己的构建仅仅只是多了一个步骤,方便如果有特殊情况的扩展。但估计也用不上。
将 my-coturn.tar 文件上传到目标服务器上。加载镜像到环境中。
docker load -i my-coturn.tar
使用镜像
先创建一个 coturn 的配置文件。
conf/coturn/turnserver.conf
# 监听的端口
listening-port=3478
# 监听的 IP 地址,0.0.0.0 表示监听所有接口
listening-ip=0.0.0.0
# 外部 IP 地址,这是客户端看到的服务器 IP
external-ip=106.15.11.11
# 最小和最大端口号,用于 NAT 穿透
# min-port=49152
# max-port=65535
# Realm 名称,通常是一个域名
realm=yuepaibao.com
# 用户名和密码,格式为 user:password
user=ypb:ypbpwd
cli-password=ypbpwd
# 启用日志记录
log-file=/var/log/turnserver/turnserver.log
# 启用详细日志记录
verbose
# 启用指纹认证
fingerprint
# 允许使用长-term credential 机制(该配置和账号密码相互冲突)
lt-cred-mech
# 指定使用的证书和密钥,如果需要 TLS
# cert=/etc/turnserver/turn_server_cert.pem
# pkey=/etc/turnserver/turn_server_pkey.pem
# 指定使用的 STUN/TURN 协议版本
stun-only=false
这里主要配置了公网 ip,realm,用户名密码还有 lt-cred-mech。 lt-cred-mech 这个很关键。
compose.yaml 文件中增加 coturn 的服务。
coturn:
image: my-coturn:1.0
container_name: coturn-1.0
restart: always
privileged: false
volumes:
- ./conf/coturn/turnserver.conf:/etc/turnserver.conf
- ./logs/coturn:/var/log/turnserver
ports:
- 3478:3478
- 3478:3478/udp
command: ['turnserver', '-c', '/etc/turnserver.conf']
networks:
- ypbnet
执行 docker-compose up -d
启动 coturn
服务。
前端程序使用
const configuration = {
iceServers: [
{
urls: ["turn:106.15.11.11:3478"],
realm: "yuepaibao.com",
username: "ypb",
credential: "ypbpwd",
},
],
};
const pc = new RTCPeerConnection(configuration);