🎬 第十三章 WebRTC网页直播
📄 一句话概括

Coturn 的配置项看着多,其实只有三类:监听、认证、中继。 最容易漏的不是配置,是云服务器安全组里那一段端口。

📝 本节和前面几节的关系

13.2.2 讲了 STUN 与 TURN 各干什么,这一节把它们真装上。 13.3.2 装信令服务器,两者配合才能建连。

一、配置只有三类

Coturn 的配置项看着多,实际上只有三类: ① 监听(端口与网卡);② 认证(账号与域);③ 中继(端口段与配额)。

最核心的一份配置长这样:

listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
external-ip=203.0.113.9
relay-ip=10.0.8.7
relay-device=eth0
min-port=49152
max-port=65535
fingerprint
lt-cred-mech
user=webrtc:secret123
realm=example.com
total-quota=100
stale-nonce
no-cli
cert=/etc/coturn/cert.pem
pkey=/etc/coturn/key.pem

17 行里 13 行带值、4 行是开关,这个比例很典型: 大部分配置项的默认值就是对的,要改的只是地址与账号。

二、三个数字决定能不能用

external-ip、relay-ip、min-port 到 max-port,这三个必须改对。 其余留着默认就行。

① external-ip 是公网地址。 云服务器上内网 IP 与公网 IP 不是一个,网卡上只看得见内网的。 不写这一条,Coturn 会把内网地址分配给客户端,外面根本连不进来。

② relay-ip 是中继时用的本地网卡地址。 单网卡机器上不写也行,双网卡的机器上必须写清楚。

③ min-port 到 max-port 是中继端口段。 TURN 每分配一个中继通道就占一个端口,所以这一段决定了能同时中继多少路。 默认 49152 到 65535 有一万六千个端口,看着够, 但云厂商的安全组默认一个都不放——这才是真正的坑。

顺序很重要:先改配置,再放行端口,最后才测。 反过来做的话,你会以为是配置写错了。

三、端口放行是最容易漏的一步

3478 与 5349 是最容易撞车的两个端口。 绑不上就换,别看配置文件写得对不对。

端口 协议 能绑吗


3478 UDP 能 3478 TCP 能 5349 TCP 能

这三个都只是「本机能不能绑」,不代表外部能访问。 云服务器还要在安全组里同时放行两样: ① TCP 与 UDP 的 3478、5349;② min-port 到 max-port 那一段。

第二样最容易漏,漏了的现象是「能连上、没画面」。 因为信令走通了、ICE 也报出了中继地址, 但真往那个端口发包时被墙挡在外面。 排查这类问题的顺序永远是:先看安全组,再看配置。

四、中继带宽翻倍这件事

TURN 转发一路流,要收一份、再发一份, 所以同一个观众占用的出口带宽是原来的两倍。

方式 服务器出口 成本


直连(P2P) 0 不占服务器带宽 TURN 中继 400 Mbps 入 200 Mbps 出 200 Mbps

100 个人看 2048 kbps 的流,走中继就要 400 Mbps 出口。 这个量级下,一台 5 Mbps 带宽的云主机连三个人都撑不住。

所以自建 TURN 之前先算这笔账: 打洞成功率有多高、中继的人有多大概率、每人多少码率。 三者乘起来才是真实成本。 很多项目失败不是技术不行,是这张账单一开始就没算。

五、动手 Demo:Coturn 配置——三个数字决定能不能用

真解析一遍配置,看带值项与开关项各有多少。 再真绑一次三个端口,最后把中继带宽按人头算出来。

CONF = """listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
external-ip=203.0.113.9
relay-ip=10.0.8.7
min-port=49152
max-port=65535
fingerprint
lt-cred-mech
user=webrtc:secret123
realm=example.com
total-quota=100
stale-nonce
no-cli"""

kv = dict(x.split("=", 1) for x in CONF.splitlines() if "=" in x)
flags = [x for x in CONF.splitlines() if "=" not in x and x]
print(len(kv), "条带值的,", len(flags), "条开关式的")

# 真绑一次,看端口占没占上
for port, kind in ((3478, socket.SOCK_DGRAM),
                   (3478, socket.SOCK_STREAM),
                   (5349, socket.SOCK_STREAM)):
    s = socket.socket(socket.AF_INET, kind)
    try:
        s.bind(("0.0.0.0", port))
        print(port, "可绑")
    except OSError as e:
        print(port, "绑不上", e)
    finally:
        s.close()

# 中继带宽:100 人 2048 kbps,走中继要双倍出口
users, kbps = 100, 2048
print("中继出口 %.0f Mbps" % (users * kbps * 2 / 1024.0))

实跑输出:

--------------------------------------------------------------------
Coturn 配置——三个数字决定能不能用
--------------------------------------------------------------------
**① 配置其实只有三类**

  **Coturn 的配置项看着多,实际上只有三类:**
  **① 监听(端口与网卡);② 认证(账号与域);③ 中继(端口段与配额)。**

  **最核心的一份配置长这样:**

    listening-port=3478
    tls-listening-port=5349
    listening-ip=0.0.0.0
    external-ip=203.0.113.9
    relay-ip=10.0.8.7
    relay-device=eth0
    min-port=49152
    max-port=65535
    fingerprint
    lt-cred-mech
    user=webrtc:secret123
    realm=example.com
    total-quota=100
    stale-nonce
    no-cli
    cert=/etc/coturn/cert.pem
    pkey=/etc/coturn/key.pem

  类别       条数     典型项
  ----------------------------------------------------------------------
  带值的     13       listening-port、realm、user
  开关式     4        fingerprint、lt-cred-mech、stale-nonce、no-cli

  **13 条带值的、4 条开关式的,一共 17 行。**

**② 真查端口能不能用**

  **3478 与 5349 是最容易撞车的两个端口。**
  **绑不上就换,别看配置文件写得对不对。**

  端口     协议     能绑吗
  ----------------------------
  3478     UDP      能
  3478     TCP      能
  5349     TCP      能

  **这三个都只是「本机能不能绑」,不代表外部能访问。**
  **云服务器还要在安全组里同时放行 TCP 与 UDP 的 3478、5349,**
  **以及 `min-port` 到 `max-port` 那一段——**
  **那一段最容易漏,漏了的现象是「能连上、没画面」。**

**③ 中继的带宽是翻倍的**

  **TURN 转发一路流,要收一份、再发一份,**
  **所以同一个观众占用的出口带宽是原来的两倍。**

  方式            服务器出口     成本
  ----------------------------------------------------------
  直连(P2P)     0              不占服务器带宽
  TURN 中继       400 Mbps       入 200 Mbps 出 200 Mbps

  **100 个人看 2048 kbps 的流,走中继就要 400 Mbps 出口,**
  **而直连是 0。**
  **这就是为什么所有 WebRTC 服务都拼命想让打洞成功**——**每多一个中继用户,成本就翻一倍。**

  **`total-quota=100` 这一条就是干这个的:**
  **限制同时中继的路数,防止被打爆。**
  **它不是「限制用户数」,是「限制转发通道数」**,两者不是一回事。**

13 条带值的、4 条开关式的,一共 17 行。 三个端口在本机都能绑上,说明没有别的服务占着。 但这只证明「本机能绑」,不证明外面能连——安全组是另一回事。 中继出口算下来 400 Mbps,这个数字就是自建 TURN 的门槛。 一台普通云主机 5 Mbps 出口,走中继只够两个人看。 所以真要靠中继做业务,带宽成本比服务器本身贵得多。

30 秒实验

  1. 把 external-ip 删掉,猜客户端拿到什么地址——拿到内网地址,外面连不上,现象是一直 connecting。
  2. 把 max-port 改成 min-port + 10,猜能同时中继几路——最多十一路,第十二个人会被拒,报 allocation quota 超限。
  3. 只放行 TCP 3478 不放行 UDP 3478,猜会怎样——STUN 问不出去,候选表里没有 srflx,只能走中继或直连内网。

常见误区

  1. 「配置文件对就能用」——安全组不放行,配得再对也不通。
  2. 「external-ip 可以不写」——云服务器上不写就把内网地址发出去。
  3. 「中继只是备用,成本可以忽略」——它是双向带宽,翻倍。
自测三问(点开对答案) 1. Coturn 配置必须改对的是哪三个数字? —— **external-ip、relay-ip、min-port 到 max-port**。 2. 最常见的一处漏配是什么? —— **云安全组没放行中继端口段**,现象是能连上但没画面。 3. TURN 中继一路流占多少带宽? —— **双向各一份**,等于原码率的两倍。

相关笔记