coturn认证实战:长期凭证与限时密钥双方案全走通

发布时间:2026/9/12 1:31:56
coturn认证实战:长期凭证与限时密钥双方案全走通 coturn认证实战长期凭证与限时密钥双方案全走通【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn凌晨3点WebRTC通话服务的告警响了TURN请求批量401。排查发现是上一周有人改了coturn的--realm参数却没通知客户端——长期凭证的完整性密钥是MD5(用户名:realm:密码)推导出来的realm一变所有客户端算出的Message-Integrity全部对不上无一幸免。这个故障暴露了coturn认证的两个核心点密钥到底怎么算、realm和timestamp在链路里起什么作用。下面按先选型、再走通、后调优的顺序讲清楚。先做决策该用哪套认证机制coturn支持两套互斥的认证机制选型只需回答三个问题用户数量固定且很少变动→ 长期凭证long-term credential--lt-cred-mech/-a用户动态生成、需要凭证自动过期→ 限时密钥auth secret--use-auth-secret基于时间戳共享密钥派生短期凭证用户数过万、要集中管理→ 都配数据库后端MySQL/PostgreSQL/Redis等turnserver --use-db-mysql ...维度长期凭证限时密钥凭据生命周期永久人工轮换时间戳过期自动失效服务端存储每用户一条密码/密钥仅1个或几个共享密钥密钥轮换粒度逐用户改密码换一次secret全量生效重放风险密码可长期复用过去时间戳直接拒收两套机制不能混用同时给--lt-cred-mech和--use-auth-secret启动时会打CONFIG警告且实际以限时密钥为准。方案A 长期凭证从401到认证成功的一条完整链路客户端第一次发Allocate请求时只带USERNAME不带密码。coturn在get_user_key()里查不到用户回401并在响应里塞REALM。客户端拿到realm后开始算密钥integrity_key MD5(username : realm : password) Message-Integrity base64(HMAC-SHA1(integrity_key, 整个请求包))客户端把USERNAME、REALM、MESSAGE-INTEGRITY三个属性补齐后重发。服务端再次进入get_user_key()这次先查启动时用--user预计算好的静态账户表ur_string_map_lock(turn_params.default_users_db.ram_db.static_accounts); if (ur_string_map_get(..., usname, ukey)) { ret 0; // 用户名命中ukey就是启动时算好的integrity_key } ur_string_map_unlock(...); // ... 静态表未命中时回落到数据库驱动 dbd-get_user_key(usname, realm, key)源码位置src/apps/relay/userdb.c→get_user_key()验证通过分配流程继续。你要改的配置就三行参考 examples/scripts/longtermsecure/secure_relay.shturnserver --lt-cred-mech --realmnorth.gov --useralice:s3cret \ --certturn_server_cert.pem --pkeyturn_server_pkey.pem # --user 格式 用户名:密码可写多个也可用 0x 开头的十六进制直接指定integrity_key注意--user的密码部分如果以0x开头会被当作已计算好的20字节密钥跳过MD5推导——批量导入数据库密钥时很有用。方案B 限时密钥时间戳就是核心这套机制不存用户密码只共享一个secret。客户端自己拼装凭证username 1765432100:alice # 当前Unix时间戳 : 用户名 password base64(HMAC-SHA1(secret, 完整username字符串))服务端收到后的处理在同一个get_user_key()里顺序是先解析时间戳、再判过期、最后才做HMAC。ts get_rest_api_timestamp((char *)usname); // 从 username 里拆出 : 前的数字 if (turn_time_before(ts, ctime)) { return ret; // 时间戳在过去 → 直接拒绝这是重放防护 } // ... 遍历密钥列表静态 数据库逐个重算HMAC并校验 Message-Integrity源码位置src/apps/relay/userdb.c→get_rest_api_timestamp()/get_user_key()两个细节值得注意时间戳解析用的是默认分隔符:rest_api_separator所以username里不能含裸冒号密钥列表由get_auth_secrets()合并静态配置和数据库两部分这为无缝轮换留了口子。服务端配置参考 examples/scripts/restapi/secure_relay_secret.shturnserver --use-auth-secret --static-auth-secretlogen --realmnorth.gov # 客户端侧等价写法turnutils_uclient -u alice -W logen 服务器地址生产环境必做的5件事限额--user-quota100 --total-quota300单用户和全局会话数上限都设上防止单个凭证被滥刷。轮换把secret从--static-auth-secret迁到数据库用turnadmin --set-secret写入新密钥旧密钥保留一个窗口期再删——双密钥并存期间新旧客户端都能通过。时钟coturn只拒收过去的时间戳远未来的时间戳同样能通过校验所以客户端和服务端都要走NTPchronyc sources确认偏差100ms。⚠️传输层加--tls-listen --cert... --pkey...走TLS别让HMAC和realm在裸UDP里被嗅探。取证-v --log-filestdout保持中等日志级别认证失败的用户名和key_lookup结果未找到/已过期/完整性不匹配都打在日志里排查时直接看。避坑速查表现象原因修复全部客户端401改密码能短暂恢复客户端realm与--realm不一致MD5推导的密钥对不上对齐双方realm如turnserver --realmnorth.gov只有部分客户端失败重登就好时间戳已过期客户端时钟偏快过服务器或请求排队太久修NTPchronyc -a makestepusername带自定义分隔符全部失败默认分隔符是:解析不出合法时间戳username保持时间戳:用户名格式分隔符两侧一致--user配了却不生效secret模式下add_static_user_account()直接返回-1静用户被丢弃二选一去掉--use-auth-secret或去掉--user启动报lt-cred-mech and use-auth-secret at the same time两机制互斥secret优先长期凭证被架空只保留一条认证开关✅ 选型原则一句话账号少且稳定用长期凭证用户动态或有安全合规要求用限时密钥。完整参数清单见 README.turnserver配置模板可直接抄 examples/etc/turnserver.conf。【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考