5分钟搞定 coturn 认证:长期密钥 vs 临时凭证怎么选
【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn
凌晨两点,告警群炸了:移动网络下的 WebRTC 通话大面积掉线,客户端日志满屏 401 Unauthorized。排查到最后,问题出在 coturn 认证上——新环境里没显式开任何认证机制,服务器直接跑在匿名模式,所有客户端的重新认证都打了空。coturn 是 TURN 服务器(NAT 穿透媒体中继,WebRTC 打洞失败时让媒体流量"借道"中转的保底通道)的主流开源实现,它的认证只有两种玩法:长期密钥和临时凭证。选哪种、怎么配,直接决定了你的 401 是消失还是刷屏。
(认证流程示意)
这张图里最该关注的节点是get_user_key——两种机制最终都汇到src/apps/relay/userdb.c里的这一个函数,分叉只发生在函数内部,所以读源码时盯住它就行。第二个值得注意的点是 401 挑战是必经之路:客户端第一次永远不带完整凭证,攻击者也可以伪造源地址疯狂"骗"401,拿它做 UDP 放大,后文清单里有对应的防护参数。
先选型:哪种 coturn 认证方案匹配你的场景
先给结论:长期密钥适合"用户是固定资产"的场景,临时凭证(TURN REST API,一种用共享密钥现算限时用户名密码的机制)适合"用户是流水"的场景。两者不能同时生效,coturn 官方明确建议二选一,配置里写哪个就按哪个来。
- 用户数固定、总量小于 100、认证频率低、内部系统 → 长期密钥(
lt-cred-mech,命令行参数-a) - 用户动态生成、高并发、需要按用户统计流量 → 临时凭证(
use-auth-secret) - 合规要求凭证必须短命、泄露后风险可控 → 只有临时凭证
- 两种都没配、也没写任何
user=→ 服务器回落到匿名访问,这是最危险的默认值
TURN 长期密钥配置:lt-cred-mech 最小可运行配置
一句话原理:预置的用户名密码,每次认证校验 HMAC 完整性,凭证永久有效。
这里的 HMAC 校验(一种用共享密钥生成"数字封条"的完整性验证方式,类似快递封条被拆就发现被调包)是这样用的:客户端用密码算出校验值填进 MESSAGE-INTEGRITY 字段,服务器用同一份密码重算,对不上就 401。
关键流程:
- 服务器启动,把
user=条目加载进内存 - 客户端请求不带完整性,服务器回 401 挑战
- 挑战携带 realm(认证域,客户端算 HMAC 必须带同一个值),客户端参与计算
- 服务器按用户名取密钥,重算并比对完整性
- 通过则分配中继端口,开始转发
下面这段在仓库examples/目录下直接复制运行,开长期密钥认证并启用 TLS(证书文件在examples/etc/):
cd examples turnserver --syslog -a \ --user=ninefingers:youhavetoberealistic \ --user=gorst:hero \ --realm=north.gov \ --cert=etc/turn_server_cert.pem \ --pkey=etc/turn_server_pkey.pem参数里-a就是--lt-cred-mech;--realm决定 401 挑战里携带的 realm,两端不一致必然认证失败。user=后面除了明文密码,还可以填turnadmin算出的 0x 开头密钥,这条命令的输出可以直接回填:
turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic # 输出 0xbc807ee29df3c9ffa736523fb2c4e8ee生产环境建议用密钥形式而不是明文密码,配置文件泄露时多一层缓冲。
coturn 临时凭证生成:时间戳 + 共享密钥的 HMAC 方案
一句话原理:用户名里塞时间戳,密码是共享密钥的 HMAC,凭证随时间自然失效。
关键流程:
- 客户端拼出
时间戳:userid作为用户名 - 用共享密钥对该用户名算 HMAC-SHA1
- HMAC 结果做 base64 编码,作为密码
- 服务器解析时间戳,过去的时间直接拒绝
- 逐个 secret 重算并比对完整性,通过即放行
第 4 步有个容易忽略的细节:服务器只拒绝"已经过期"的时间戳,没有偏移容忍参数,客户端时钟落后于服务器就会认证失败。服务端最小可运行配置(同样在examples/下运行):
cd examples turnserver --syslog \ --use-auth-secret \ --static-auth-secret=logen \ --realm=north.gov \ --cert=etc/turn_server_cert.pem \ --pkey=etc/turn_server_pkey.pem客户端侧生成凭证的小脚本,密钥与服务器--static-auth-secret保持一致:
NOW=$(date +%s) U="${NOW}:alice" P=$(printf '%s' "$U" | openssl dgst -sha1 -hmac logen -binary | base64)跑完后$U和$P就是这次会话的用户名和密码。建议每次会话前重新生成,有效期按 300 秒掌握,userid 部分填你的业务用户 ID,流量统计就能落到具体人头上。
⚠️ 上线前必踩的 3 个坑
⚠️ 症状:临时凭证稳定 401,时钟快几分钟没事、慢 5 秒就挂。根因:服务器只拒绝过去的时间戳,没有偏移容忍参数。修复:客户端开 NTP 同步,时钟偏差控制在秒级。
⚠️ 症状:同时配了lt-cred-mech和use-auth-secret,静态用户全部认证失败。根因:两种机制互斥,user=静态条目在 REST API 模式下不生效。修复:删掉多余的user=行,二选一改完重启验证。
⚠️ 症状:重启后测试发现任何人不用密码都能建会话。根因:没配用户、没开机制时 coturn 默认 no-auth 匿名放行。修复:显式加-a或--use-auth-secret,再用turnutils_uclient验证一次拒绝。
coturn 认证安全与运维清单(可抄进 runbook)
选型对比统一放这,前文不再重复:
| 维度 | 长期密钥 lt-cred-mech | 临时凭证 use-auth-secret |
|---|---|---|
| 凭证生命周期 | 永久,换密码才失效 | 由时间戳决定,自然过期 |
| 用户存储 | 配置文件user=或数据库 | 无用户表,只存 secret |
| 流量归属 | 固定用户名可统计 | userid 可统计到人 |
| 泄露后果 | 密码泄露等于永久后门 | 密钥泄露仍可换钥止损 |
- TURN 流量走 TLS:配置
cert=与pkey=,客户端连 5349 端口 - 会话配额:
-q 100(单用户最多 100 个会话)、-Q 300(服务器总量 300 个) - 开 401 洪泛防护:
unauthorized-ratelimit加unauthorized-ratelimit-rps=10(每 IP 每秒最多回 10 个 401) - 临时凭证按 300 秒有效期生成,客户端与服务器时钟走 NTP,偏差控制在秒级
- 长期密钥不用明文密码,
turnadmin -k生成 0x 密钥后回填--user= stale-nonce=600保持默认,nonce 10 分钟后强制重新认证- 两种机制二选一,配置里不要同时出现
lt-cred-mech和use-auth-secret
延伸入口
- 全量参数与默认值看 docs/Configuration.md。
- 想看两种机制的真实分叉,读
src/apps/relay/userdb.c里get_user_key的use_auth_secret_with_timestamp分支,不到百行。 - 直接跑起来:
git clone https://gitcode.com/GitHub_Trending/co/coturn后执行examples/scripts/restapi/secure_relay_secret.sh(临时凭证)和examples/scripts/longtermsecure/secure_relay.sh(长期密钥)。
【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考