6、STUN/TURN服务器部署:Coturn搭建、中继模式配置、安全认证、负载均衡策略

说实话,WebRTC 最难搞的部分,往往不是音视频编解码,而是网络穿透。你想想看,两个用户在不同的内网里,怎么找到对方?这就是 STUN/TURN 要解决的问题。我最早接触这个坑,是在一个跨国视频会议项目里,用户死活连不上,最后发现是 TURN 服务器没配好。嗯,今天我们就来彻底搞定它。

6.1 为什么需要 STUN/TURN?

先简单说下原理。WebRTC 默认会用 ICE 框架来尝试建立 P2P 连接。ICE 会先尝试直连,不行就通过 STUN 打洞,再不行就只能走 TURN 中继了。

  • STUN:帮客户端发现自己的公网 IP 和端口。说白了就是「照镜子」。
  • TURN:当 P2P 走不通时,充当中间人转发数据。说白了就是「传话的」。

我个人习惯把 TURN 当作最后的保底方案。毕竟中继要消耗服务器带宽,成本不低。但有些场景,比如对称 NAT 或者防火墙严格的网络,不用 TURN 还真不行。

6.2 Coturn 是什么?

Coturn 是目前最主流的开源 STUN/TURN 服务器实现。它支持完整的 RFC 标准,性能稳定,配置灵活。我几乎所有的项目都用它,没出过什么大问题。

它的核心功能包括:

  • 同时支持 STUN 和 TURN 协议
  • 支持 UDP、TCP、TLS 传输
  • 内置用户认证机制
  • 支持多线程和负载均衡
  • 提供详细的日志和统计

6.3 搭建 Coturn 服务器

搭建过程其实不复杂。我以 Ubuntu 20.04 为例,带大家走一遍。

6.3.1 安装 Coturn

# 更新包管理器
sudo apt update

# 安装 Coturn
sudo apt install coturn -y

# 检查安装是否成功
turnserver --version

安装完成后,默认配置文件在 /etc/turnserver.conf。我个人习惯先备份一份原始配置:

sudo cp /etc/turnserver.conf /etc/turnserver.conf.bak

6.3.2 基础配置

打开配置文件,修改以下几个关键参数:

# 监听的端口,默认是 3478
listening-port=3478

# TLS 监听端口,默认是 5349
tls-listening-port=5349

# 内网 IP 地址(根据实际情况修改)
listening-ip=0.0.0.0

# 公网 IP 地址(必须填写)
relay-ip=你的公网IP

# 外部 IP 映射(如果服务器在 NAT 后面)
external-ip=你的公网IP/内网IP

# 允许的最大中继会话数
max-bps=1000000

# 日志文件路径
log-file=/var/log/turnserver.log

# 是否开启详细日志
verbose
注意:我曾经遇到过一个问题,就是忘记配置 relay-ip,结果客户端虽然能连上 TURN 服务器,但数据就是转发不出去。排查了半天才发现是 IP 没绑定对。所以这个参数一定要填对。

6.3.3 启动服务

# 启动 Coturn
sudo systemctl start coturn

# 设置开机自启
sudo systemctl enable coturn

# 查看运行状态
sudo systemctl status coturn

如果一切正常,你应该能看到 active (running) 的状态。

6.4 中继模式配置

Coturn 支持多种中继模式。我常用的有三种:

模式 说明 适用场景
UDP 中继 默认模式,性能最好 大多数实时音视频场景
TCP 中继 通过 TCP 转发,更稳定 网络丢包严重或防火墙限制 UDP
TLS 中继 加密传输,安全性最高 对安全要求极高的场景

配置中继模式很简单,在 turnserver.conf 里加上对应的参数即可:

# 启用 UDP 中继(默认开启)
# 不需要额外配置

# 启用 TCP 中继
relay-tcp

# 启用 TLS 中继(需要证书)
cert=/etc/ssl/certs/turnserver.pem
pkey=/etc/ssl/private/turnserver.key
我的建议:如果条件允许,优先使用 UDP 中继。延迟低,带宽利用率高。只有在 UDP 被封锁的情况下,才考虑 TCP 或 TLS。

6.5 安全认证

安全认证这块,我吃过不少亏。早期有个项目没加认证,结果 TURN 服务器被恶意用户拿来当代理,流量跑了几百 GB,月底账单吓死人。所以,认证一定要配。

6.5.1 静态认证(简单但不够安全)

# 在配置文件中设置共享密钥
static-auth-secret=你的密钥

# 客户端连接时需要提供用户名和密码
# 用户名格式:timestamp:username
# 密码计算:base64(hmac-sha1(secret, username))

这种方式适合测试环境。生产环境我不推荐,因为密钥是固定的,一旦泄露就很麻烦。

6.5.2 动态认证(推荐)

动态认证需要配合一个认证服务。客户端先向你的后端服务请求一个临时凭证,然后拿着凭证去连 TURN 服务器。

配置方式:

# 使用外部认证服务
use-auth-server

# 认证服务的地址
auth-server=你的后端服务地址:端口

# 认证服务的共享密钥
auth-server-secret=你的密钥

后端服务生成凭证的示例代码(Node.js):

const crypto = require('crypto');

function generateTurnCredentials(username, secret) {
  const timestamp = Math.floor(Date.now() / 1000) + 24 * 3600; // 24小时有效
  const user = `${timestamp}:${username}`;
  const hmac = crypto.createHmac('sha1', secret);
  hmac.update(user);
  const password = hmac.digest('base64');
  return { username: user, password: password };
}
注意:凭证一定要设置有效期。我一般设 24 小时,太短了用户频繁重连体验不好,太长了有安全风险。

6.6 负载均衡策略

当用户量上来后,单台 TURN 服务器肯定扛不住。这时候就需要做负载均衡。我常用的方案有两种:

6.6.1 DNS 轮询

最简单的方式。配置多个 TURN 服务器的域名解析到同一个域名,DNS 会自动分配请求。

# 在 DNS 管理后台添加多条 A 记录
turn.example.com  A  192.168.1.10
turn.example.com  A  192.168.1.11
turn.example.com  A  192.168.1.12

优点:配置简单,成本低。缺点:无法感知服务器负载,可能造成某些服务器过载。

6.6.2 基于 Nginx 的负载均衡

用 Nginx 做 TCP/UDP 代理,把请求分发到多台 TURN 服务器。

Nginx 配置示例:

stream {
    upstream turn_servers {
        least_conn;  # 最少连接数策略
        server 192.168.1.10:3478;
        server 192.168.1.11:3478;
        server 192.168.1.12:3478;
    }

    server {
        listen 3478 udp;
        proxy_pass turn_servers;
        proxy_timeout 60s;
        proxy_responses 1;
    }

    server {
        listen 3478 tcp;
        proxy_pass turn_servers;
        proxy_timeout 60s;
    }
}

我个人比较推荐这种方式。Nginx 的 least_conn 策略能比较均匀地分配连接,而且配置起来也不复杂。

6.6.3 基于 Coturn 集群

Coturn 本身也支持集群模式。通过配置 relay-threadsuserdb 共享,可以实现多实例协同。

# 每个 Coturn 实例的配置
relay-threads=4
userdb=/var/lib/turn/turndb

# 使用 Redis 共享用户数据库
redis-userdb=redis://redis-server:6379/0

这种方式适合大规模部署。但需要额外维护 Redis,复杂度会高一些。

6.7 知识体系总览

下面这张图总结了本章的核心内容,方便你快速回顾:

STUN/TURN 服务器部署知识体系 Coturn 服务器 搭建部署 中继模式配置 安全认证 负载均衡策略 安装配置 / 启动服务 UDP / TCP / TLS 中继 静态认证 / 动态认证 DNS轮询 / Nginx代理 / Coturn集群 核心目标:保证 WebRTC 连接在各种网络环境下都能建立

6.8 避坑指南

最后,分享几个我踩过的坑:

  • 防火墙端口没开:记得在服务器安全组里开放 3478(UDP/TCP)和 5349(TLS)端口。我曾经因为这个排查了一整天。
  • 带宽估算不足:TURN 中继的带宽消耗是双向的。一个 1080p 视频流大约需要 4-6 Mbps,如果有 100 个用户同时使用,服务器带宽至少要 1 Gbps。
  • 日志没开:出问题的时候,日志是救命稻草。建议把 verbose 打开,方便排查。
  • 证书过期:如果用了 TLS 中继,记得设置证书自动续期。我见过好几次因为证书过期导致连接失败的情况。

好了,关于 STUN/TURN 服务器的部署,今天就聊到这里。配置这东西,光看文档是不够的,建议你动手搭一个试试。遇到问题别慌,先看日志,八成能找到答案。


公众号:蓝海资料掘金营,微信deep3321