本文主要讨论用于 WebRTC 的 TURN 服务器的应用,这里我们使用 coturn 。

coturn 是一个免费的开源的 TURN/STUN 服务器。coturn 服务器完整的实现了 STUN/TURN/ICE 协议,支持 P2P 穿透防火墙。

  • STUN 服务器用于获取设备的外部网络地址
  • TURN 服务器是在点对点失败后用于通信中继。

WebRTC 建立连接的步骤大概是这样的:

  1. 客户端(浏览器)直接尝试直连;
  2. 如果如果直连则通过 STUN 服务器进行穿透;
  3. 如果无法穿透则通过 TURN 服务器进行中转。

安装 coturn

本章主要阐述在 Ubuntu 系统下编译安装 coturn 的简要过程,详细的安装方法请查看 INSTALL文件

  1. 编译安装 OpenSSL 1.1.0 ,过程略;
  2. 编译安装 libevent 最新版,过程略;
  3. coturn 可以选择使用多种数据库,这里使用的是 SQLite ,使用命令 sudo apt-get install sqlite (or sqlite3)sudo apt-get install libsqlite3-dev (or sqlite3-dev) 安装;
  4. coturn 下载页 下载最新正式版本的 cotrun 源码,下载完成后使用 tar xvfz turnserver-<...>.tar.gz 命令解压;
  5. 依次使用 ./configuremakemake install 编译安装 coturn 。

唯一和官方描述的不同的是执行 ./configure 命令时没有使用 --prefix=/opt 参数,因为我的 OpenSSL 安装在默认位置,如果安装到其他位置 libevent 会找不到 OpenSSL 库文件。

安装完成后在 bin 目录下生成六个可执行文件:

  • turnserver - STUN/TURN 服务器
  • turnadmin - 用于配置、管理账户
  • turnutils_stunclient - 用于测试 STUN 服务
  • turnutils_uclient 用于测试 TURN 服务,模拟多个UDP、TCP、TLS 或 DTLS 类型的客户端
  • turnutils_peer
  • turnutils_rfc5769check

具体的使用方法请查看 wiki

配置使用

coturn 支持三种配置:命令行、conf文件和数据库, 数据库支持sqlite,mysql,postgresql,MongoDB,redis。安装后的SQLite 数据库文件可能在 /usr/local/var/db/var/db/turndb 路径下,名称为 turndb

STUN 定义了两种验证方式:Long-Term CredentialShort-Term Credential 。具体可以参考 STUN 标准 http://tools.ietf.org/html/rfc5389#section-15.4 。但是对于 WebRTC 而言,仅支持 Long-Term Credential 。

配置 Long-Term 用户

首先使用下列命令添加一个 Long-Term 用户:

sudo turnadmin -a -u you_name -p you_password -r you_realm

这里默认使用了 SQLite 数据库,其中 -a 表示添加一个 long-term 用户, -u <user> 为用户名,-p <password> 为密码,-r <realm> 为该用户所属的 Realm。在启动 turnserver 时需要指定 Realm ,只有该 Realm 下的用户才能登录。

注意一定要使用 root 权限配置,否则会配置失败,但是还没有错误提示。更多参数及具体使用方法详见 wiki

启动服务器

配置完用户后就可以启动 turnserver 了,第一次启动前需要一个配置文件,这是使用模板生成,然后就可以启动 turnserver 了。

sudo cp /usr/local/etc/turnserver.conf.default /usr/local/etc/turnserver.conf
sudo turnserver -a -f -v -r you_realm

其中 -a 表示使用 long-term 机制, -r 为指定的 Realm ,只有该 Realm 下的用户可以使用服务器。

更多参数及具体使用方法详见 wiki

测试 STUN

使用下面的命令即可测试 STUN 服务使用可用,唯一此参数是 STUN 服务器的 IP地址或域名。

# 测试 STUN
turnutils_stunclient 123.166.110.69

测试 TURN

使用下面的命令即可测试 TURN 服务使用可用,值得注意的是必须使用 turnserver 启动时指定 Realm 下的用户。

# 测试 TURN
turnutils_uclient -u cjx -w 123456 123.166.110.69

更多参数及具体使用方法详见 wiki

也可以使用 Google 提供的 WebRTC STUN/TURN 测试页面进行测试:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/

开机启动服务

如果想要开机启动 turnserver,首先需要修改配置文件 turnserver.config,一般情况需要修改以下的几个参数:

listening-ip=127.0.0.1
listening-ip=172.16.0.99    # 内网ip
external-ip=221.208.117.45  # 公网ip,如果服务器在NAT后需要指定该参数
fingerprint
lt-cred-mech
realm=<you_realm_name>

在手动修改好配置文件 turnserver.config 后,Ubuntu 14.04 系统下可以使用下列命令添加开机启动项:

sudo update-rc.d turnserver defaults

如果发生 update-rc.d: /etc/init.d/turnserver : file does not exist 错误,执行下列命令创建一个软链接即可:

sudo ln -sf /usr/local/bin/turnsever /etc/init.d/turnserver

在测试过程中,发现有时候没有开机启动成功,而且 turnsever 不支持 stop 参数导致关机失败,所以这里的开机启动方法是不正确的。这个主要原因是由于 coturn 没有自动安装开机启动服务脚本(脚本位于source/rpm目录下,需要修改)。

所以尝试第二种方法。将我的 Ubuntu 14.04 升级到 Ubuntu 16.04 (因为Ubuntu 14.04 不持支持 systemctl命令)。

<source_dir>/rpm 目录下的 turnserver.service.fc 文件作为模板,在此基础上进行修改,修改后的文件名为 turnserver.service ,修改后的文件内容如下:

[Unit]
Description=coturn
Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)
After=syslog.target network.target

[Service]
Type=forking
PIDFile=/var/run/turnserver.pid
ExecStart=/usr/local/bin/turnserver --daemon --pidfile /var/run/turnserver.pid -c /usr/local/etc/turnserver.conf
ExecStopPost=/usr/bin/rm -f /var/run/turnserver.pid
Restart=on-abort

LimitCORE=infinity
LimitNOFILE=999999
LimitNPROC=60000
LimitRTPRIO=infinity
LimitRTTIME=7000000
CPUSchedulingPolicy=other
UMask=0007

[Install]
WantedBy=multi-user.target

然后执行下列命令即可。

# 复制.service文件
sudo cp ~/coturn-4.5.0.6/rpm/turnserver.service /etc/systemd/system/turnserver.service
# 使服务自动启动
sudo systemctl enable turnserver.service
# manually start the service:
sudo systemctl start turnserver
# manually stop the service:
sudo systemctl stop turnserver

​ 如果说出现启动失败或者启动超时(timeout错误),可能是在脚本中包含 UserGroup 参数,去掉这两个参数即可。

负载均衡

coturn 可以通过设置一个 master turn server ,配置若干个 slave turn server 的方式实现负载均衡。

master 服务器只需在启动时指定 --alternate-server--tls-alternate-server 参数即可,具体使用方法可以查看 source/examples/scripts/loadbalance 目录下的几个文件。

附录

WebRTC 性能

这个其实和 cotrun 关系不大,感谢 anyRTC 提供的数据。

音视频通讯质量

音视频实时通讯质量取决于以下几个方面的因素:

网络带宽:如果上下行带宽较小时,则多人音视频会受带宽影响而降低质量并跳帧;

网络延时:参与音视频的某两方之间的网络延迟越大,他们之间的视频质量越低,延迟越大;

网络丢包:网络丢包是很常见的,丢包数的增加与音视频质量成反比;

木桶效应:在一个会议中,若单个节点网络出现异常时,会影响到其他与会者的音视频效果;

设备能力:音视频通讯的效果不仅仅与网络有关系,设备端的处理能力同样决定了音视频的通讯效果。

网络因素

p2p模式下,一般带宽只需要上下行512kbps带宽即可达到非常好的通讯效果,若是中转模式,在 TURN 服务器负责中转的情况下2mbps可支持正常的6人会议。

当然我们不建议用户在p2p模式下使用多人会议,一则浪费带宽,二则消耗设备的性能,无法保证多人会议的效果。

视频 : 在保证质量的情况下,视频的分辨率大小决定了视频码率的大小,一路1280x720视频需要平均约300kbps,峰值500kbps的带宽。更低质量的摄像头和更低的分辨率配置会显著降低带宽需要。

屏幕分享 : 每个全屏幕1920x1080视频分享约需要稳定的500kbps带宽。单个简单界面窗口的分享所需带宽可降低到80-200kbps。

音频 : 每路音频所需的带宽稳定在50kbps。

systemctl 命令用法

systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起。

任务旧指令新指令
使某服务自动启动chkconfig --level 3 httpd onsystemctl enable httpd.service
使某服务不自动启动chkconfig --level 3 httpd offsystemctl disable httpd.service
检查服务状态service httpd statussystemctl status httpd.service (服务详细信息) systemctl is-active httpd.service (仅显示是否 Active)
显示所有已启动的服务chkconfig --listsystemctl list-units --type=service
启动某服务service httpd startsystemctl start httpd.service
停止某服务service httpd stopsystemctl stop httpd.service
重启某服务service httpd restartsystemctl restart httpd.service

反向代理和 TURN 服务器的防火墙端口

反向代理、TURN 服务器和客户机之间的通信

The following ports have to be allowed through any firewalls which carry traffic between the reverse proxy and TURN server in the DMZ and the Infinity Connect Mobile client and Infinity Connect clients in the public Internet:

PurposeDirectionSource IPProtocolPortDestination IP
HTTP/HTTPSInbound<any>TCP80 / 443Reverse proxy
UDP TURN/STUNInbound<any>UDP3478TURN server
TURN relay mediaInbound<any>UDP49152–65535TURN server
RTP mediaOutboundTURN serverUDP<any><any>
DNSOutboundReverse proxy and TURN serverTCP/UDP53DNS server
NTPOutboundReverse proxy and TURN serverTCP123NTP server

本地网络和 DMZ / Internet 之间的通信

The following ports have to be allowed through any firewalls which carry traffic between Conferencing Nodes and management stations in the local network and the reverse proxy and TURN server in the DMZ/internet:

PurposeDirectionSource IPProtocolPortDestination IP
HTTPSInboundReverse proxyTCP443Conferencing Nodes
UDP TURN/STUNOutboundConferencing NodesUDP3478TURN server
UDP TURN/STUNOutboundConferencing NodesUDP3478 / 19302STUN server (if configured). Note that stun.l.google.com uses port 19302.
SSHOutboundManagement PCTCP22Reverse proxy and TURN server

参考文章:

  1. webrtc学习: 部署stun和turn服务器
  2. https://www.anyrtc.io/resoure
  3. systemctl命令用法
  4. Firewall ports for the reverse proxy and TURN server

标签: WebRTC, coturn, STUN, TURN, systemctl

已有 2 条评论

  1. lwei2

    楼主,您好,内网ip和外网ip分别是指哪个和哪个呢?比如我安装的时候,以虚拟机为内网,以主机为外网,这样对不对呢?

    1. 内网是指局域网,外网是指带有固定IP地址的互联网。不建议安装到虚拟机中

添加新评论