coturn stateless-nonce 模式怎么配置防止伪造源 IP 洪水耗尽会话内存【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn当你的 coturnturnserver以 long-term / auth-secret 认证对外提供 UDP 服务时会面对一个内存层面的攻击面UDP 源地址可以被伪造而一个结构合法的 STUNALLOCATE在认证之前就提交了真实资源——listener 地址表里的一个子 UDP socket、一个约 18KB 的ts_ur_super_session只为存放 nonce以及一个让二者存活 60 秒TURN_MAX_ALLOCATE_TIMEOUT的 to-be-allocated 定时器。文档给出的量化是10k 伪造包/秒就能撑起数十万条存活会话、数 GB 内存而这些流量永远走不到认证。--stateless-nonce模式就是为封住这个面而加的。开启后challenge nonce 不再是每会话随机值而是一个可校验的时间戳 cookie未认证的伪造洪水不分配任何状态只有把本服务器发给它的那个 nonce 原样回显回来的源才会拿到会话。这篇文章讲怎么开启/配置它以及怎么验证它确实生效。先确认威胁与默认状态先理解为什么--unauthorized-ratelimit单独不够它压制的是 401响应反射/放大防御但状态在那之前已经分配了所以它约束不了内存详见 401-ratelimit.md。内存约束来自 stateless-nonce 的 listener fast path来自未知 UDP 源、不带 MESSAGE-INTEGRITY 的请求直接由 listener 回 401 challenge——不建子 socket、不建会话。带 MESSAGE-INTEGRITY 的请求只有当它的NONCE能证明是本服务器发给该源地址的才被放行进会话路径其余realm 不匹配、nonce 缺失/畸形由 listener 直接按check_stun_auth的字节顺序应答400/437/441/438。关键前提该模式默认开启。所以第一步不是加参数而是确认你没有显式关掉它显式开启等价于默认--stateless-nonce关闭配置文件写法stateless-noncefalse--stateless-noncefalse只有在需要兼容硬编码 16 字符 nonce 缓冲的客户端时才考虑关闭见文末限制。配置方法单实例默认即生效单台服务器什么都不用加fast path 默认已生效。若你希望显式声明或从命令行确认turnserver --use-auth-secret --static-auth-secret你的auth-secret --realm你的realm \ --stateless-nonce --log-filestdout其中--static-auth-secret/--realm是项目测试文档里用的示例值替换成你自己的认证配置即可。nonce 有效期由--stale-nonce控制文档与源码一致未设置时默认 600 秒。多实例 / 负载均衡共享密钥默认密钥是进程内临时随机值——重启即失效负载均衡下落在另一实例上的重试也会多走一次438。要让整套集群互相校验对方发的 nonce用--stateless-nonce-secret配置文件写法stateless-nonce-secret隐含开启--stateless-nonceturnserver --use-auth-secret --static-auth-secret你的auth-secret --realm你的realm \ --stateless-nonce-secret你的高熵secret --log-filestdout派生公式与运行要点均来自文档务必逐条核对密钥派生K SHA-256( coturn-stateless-nonce-v1 || secret )。同一 secret 的所有服务器跨重启、跨集群互相校验。熵由你负责KDF 固定的是密钥长度不是猜解熵。攻击者收集几个 401 就能对弱口令做离线字典攻击——用长随机字符串。不要复用其他凭据例如--static-auth-secret当这个 secret 的值label 域分隔只是防碰撞不是复用许可。优先写配置文件别放命令行命令行上的 secret 在进程列表里可见。时钟必须一致跨实例校验会把 nonce 内嵌的签发时间和校验方时钟比较整个集群要在--stale-nonce有效期内良好 NTP 同步未来偏差容忍只有几秒。轮换目前 改 secret 并重启客户端经一次标准438重认证恢复。同时接受新旧两个 secret 是文档里明确的 future work。可选加强401 响应限流stateless-nonce 管内存不增长--unauthorized-ratelimit管响应不被放大。二者正交可叠加。它默认关闭、opt-in只对 UDP 生效TCP/TLS 无法伪造从不被限流turnserver --use-auth-secret --static-auth-secret你的auth-secret --realm你的realm \ --unauthorized-ratelimit --unauthorized-ratelimit-rps10--unauthorized-ratelimit-rpscount默认 10每秒每源 IP 的 401 上限非正值会被拒并回退默认。某源在窗口内首次超限时服务器记一条日志窗口内其余丢弃静默401 rate-limit exceeded from ip, suppressing responses for this window开启 Prometheus 时turn_unauthenticated_401_requests/turn_unauthenticated_401_responses/turn_unauthenticated_401_dropped_responses三个计数器描述这条 UDP 反射面。在 stateless-nonce 下伪造 MESSAGE-INTEGRITY 触发的438/437/441/400应答消耗同一个每源预算、同样被压制日志记为unauthorized-response rate-limit exceeded但不进 Prometheus 的 401 计数器。验证它真的生效光启动不等于 fast path 在工作。项目提供了端到端回归与探测脚本按从快到全的顺序验证。1. 检查服务器启动日志标记启动后在日志里找两条标记这是回归套件 run_tests_stateless_nonce.sh 实际 grep 的字符串stateless-nonce: listener fast-path challenge active—— fast path 确实接管而非静默回退到逐会话路径。使用--stateless-nonce-secret时另有Stateless nonce key derived from the configured secret—— 确认密钥来自配置的 secret 而非临时随机值。缺任一条说明配置没落地回到上一步核对参数。2. 标准客户端工作负载证明线协议透明该模式设计为对客户端不可见所以断言就是标准负载照常成功。测试脚本的做法是用turnutils_uclient经 UDP/TCPLinux 上再加 TLS/DTLS各中继 1000 字节成功判定为客户端日志出现start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000单条最小验证UDP-W为 auth-secretuser为用户名turnutils_uclient -u user -W 你的auth-secret -e 127.0.0.1 -X -g 127.0.0.1TCP 加-tTLS/DTLS 加-t -S/-S。出现上面的tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000即通过否则用脚本里的diagnose_failure思路看客户端的 401/438/nonce 行与服务器 auth/session 行。3. 伪造 MESSAGE-INTEGRITY 探测证明无会话应答examples/scripts/stateless_nonce_forged_mi.py 用纯标准库构造turnutils_uclient造不出的畸形请求并固定每种应答码python3 examples/scripts/stateless_nonce_forged_mi.py 127.0.0.1 3478 你的用户名成功时逐条打印OK: ...并以RESULT forged-mi-probepass结束。它固定的应答码未签发 nonce →438realm 不匹配ALLOCATE →437REFRESH →441UDP 上的 CONNECTION-BIND、缺 NONCE、缺 USERNAME →400服务器确实发给该 socket 的 nonce→ 放行进会话路径、因伪造的 integrity 失败而回401。这正是带 MI 的请求只有在 nonce 可证明归属该源时才值得一个会话的直接证据。flood子模式可配合限流观察压制效果配合--unauthorized-ratelimit-rps使用flood count发包并统计应答数。noncelen子模式用于断言 challenge nonce 长度stateless 模式应为 24 字符legacy--stateless-noncefalse服务器应为 16 字符。4. 完整回归套件要一次跑完负载 日志标记 伪造 MI 探测 legacy 校验用 examples/run_tests_stateless_nonce.sh。它是专为 stateless-nonce 设计的单一任务套件可作整体回归。副作用与前提需先说明需要已构建的二进制脚本按../bin/turnserver或../build/bin/turnserver探测脚本会自行启动并 kill它拉起的turnserver与turnutils_peer进程在/tmp写临时日志并在退出时删除trap cleanup EXITTLS/DTLS 用例会引用../examples/ca/turn_server_cert.pem/turn_server_pkey.pem需已构建并存在这些证书macOS 上会跳过 TLS/DTLS 与非确定性部分只跑确定性子集Linux 是完整目标。限制与已知边界默认开启--stateless-noncefalse用于兼容硬编码 16 字符 nonce 缓冲的客户端正常合规客户端RFC 8489 要求把 nonce 当作最多 128 字符的不透明串不受 24 字符长度影响。重启与集群默认临时密钥意味着重启让未过期 nonce 失效每客户端一次438重认证负载均衡下落在另一实例的重试同理。跨实例用--stateless-nonce-secret消除并要求 NTP 同步。BINDING 不走此路径BINDING 无需认证、有自己的 listener fast path与本选项独立--secure-stun的 BINDING challenge 只受益于 challenge 会话拆解不受益于 nonce fast path。TCP/TLS 行为不变这些传输无法伪造源、已按连接固定会话保持原有行为派生 nonce 被使用无害。secret 泄露影响有限该密钥签的是 DoS 加固 cookie不是凭据——伪造 nonce 永远无法通过认证MESSAGE-INTEGRITY 仍被校验只是让伪造流量重新到达凭据查找约等于该特性引入前的负载内存仍被 challenge 会话拆解约束。配置落地后验证收敛到两点日志里能看到listener fast-path challenge active标记、伪造 MI 探测打印forged-mi-probepass同时标准turnutils_uclient负载仍按tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000成功。三者齐备即代表未认证伪造洪水不再分配会话状态而合法客户端行为不变。【免费下载链接】coturncoturn TURN server project项目地址: https://gitcode.com/GitHub_Trending/co/coturn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考