【问题标题】:CoTURN: How to use TURN REST API?CoTURN:如何使用 TURN REST API?
【发布时间】:2026-02-08 11:35:01
【问题描述】:

我已经构建了 coturn 并成功运行它。 ip:192.168.1.111。现在我面临的问题是通过 REST API 获得 Turn 凭证。 https://datatracker.ietf.org/doc/html/draft-uberti-behave-turn-rest-00根据段落请求格式应该是

GET /?service=turn&username=mbzrxpgjys

并且响应应该是JSON。现在我的问题是:

a) 如何配置和命令 TURN SERVER 使其在REST API 模式下运行?

b) 如何以正确的格式编写 http 请求,以便TURN SERVER 可以正确回复?可以举个例子吗?

【问题讨论】:

    标签: rest api webrtc turn coturn


    【解决方案1】:

    这里有几点需要澄清:

    • GET /?service=turn&username=mbzrxpgjys 返回 JSON,只是一个 建议 uri,用于从服务器检索 time-limited TURN 凭据,您不必遵循也就是说,您的 uri 可以只是 /?giveMeCredentials。事实上,我使用我的套接字连接来检索这些数据,而不是直接使用 json 响应进行 http 调用。一天结束,只要这些凭据有效,您(使用上述 TURN 的客户端)如何获得这些凭据并不重要。

    • 您不直接向 TURN 服务器发出任何请求,no rest api 对 TURN 服务器的调用在您的控制之下。

    • 您在启动 TURN 服务器时分配了一个密钥,这可以从数据库中获取(因此可以动态更改),但我很懒,只是硬编码,并在轮流配置中提供文件,还记得启用 REST API。作为转弯命令的一部分,turnserver ... --use-auth-secret --static-auth-secret=MySecretKey

    • 1234563密码将是带有您的密钥的用户名的 HMAC。
    • 关于 UNIX 时间戳,这是 TURN 服务器中的时间,在此之前您的凭据必须有效,因此计算此时间时请确保您考虑到您的应用程序服务器与轮到您之间的时钟时间差服务器。

    现在一些示例代码取自我对另一个 question 的回答

    启动服务器的命令:

    turnserver -v --syslog -a -L xx.xxx.xx.xx -X yy.yyy.yyy.yy -E zz.zzz.zz.zzz --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --static-auth-secret=my_secret --realm=north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -q 100 -Q 300 --cipher-list=ALL
    

    node.js 在应用服务器中创建 TURN 凭证的代码:

    var crypto = require('crypto');
    
    function getTURNCredentials(name, secret){    
    
        var unixTimeStamp = parseInt(Date.now()/1000) + 24*3600,   // this credential would be valid for the next 24 hours
            username = [unixTimeStamp, name].join(':'),
            password,
            hmac = crypto.createHmac('sha1', secret);
        hmac.setEncoding('base64');
        hmac.write(username);
        hmac.end();
        password = hmac.read();
        return {
            username: username,
            password: password
        };
    }
    

    使用这个的浏览器代码:

      ...
      iceServers:[
        {
          urls: "turn:turn_server_ip",
          username: username,
          credential:password
        }
      ...
    

    【讨论】:

    • 感谢您提到时间戳不是实际时间戳而是过期时间戳,我忘记了。我还必须使用 HMAC 的 RAW 输出,就像@SparX 说的那样,否则我会收到这个错误:489: session 001000000000000004: realm <> user <>: incoming packet message processed, error 401: Unauthorized 489: check_stun_auth: Cannot find credentials of user <1564836087:webrtc>。顺便说一句,用户名:randomText的结尾不需要,你可以使用时间戳,就像我在coturn配置文件中读到的那样。
    • 谁能帮我解决这个问题,请*.com/questions/64154550/…
    • 我今天整天都在拔头发尝试这个,只是为了有点随机地发现为了让它工作,一个必须还指定一个领域。如果未在配置中设置realm 选项,则它不起作用,并且会收到realm <> user <> 错误消息。也许这可以节省一些头发!
    【解决方案2】:

    在经历了(许多)小时的挫折之后,@Mido 出色的 answer 是唯一真正让 CoTurn 的 REST API 为我工作的东西。

    我的凭证服务器是 PHP,我使用 CoTurn 的配置文件“turnserver.conf”,所以这里是针对这种情况的 Mido 工作的经过测试和工作的翻译:

    假设“共享密钥”为“3575819665154b268af59efedee8826e”,以下是相关的 turnserver.conf 条目:

    lt-cred-mech
    use-auth-secret
    static-auth-secret=3575819665154b268af59efedee8826e
    

    ...还有 PHP(它误导了我好久):

    $ttl = 24 * 3600;  // Time to live
    $time = time() + $ttl;
    $username = $time . ':' . $user;
    $password = base64_encode(hash_hmac('sha1', $username, '3575819665154b268af59efedee8826e', true));
    

    【讨论】:

    • 您在回答中使用的秘密哈希提醒我,coturn 说该秘密应该使用 MD5 进行哈希处理,但我在没有对秘密进行哈希处理的情况下进行了测试,并且它也有效。使用散列秘密有什么好处吗?我想使用未散列的秘密就足够安全了。我还注意到不需要配置条目lt-cred-mechuse-auth-secret。您只需使用static-auth-secret(和cert + pkey 即可使用SSL 证书)。在 WebRTC JavaScript 代码中,应使用端口 5349 进行安全连接,否则使用未加密的端口 3478。
    • @baptx 我使用秘密的唯一原因,它是某物的哈希值,是为了便于自动更改它,同时几乎不可能猜测或蛮力。我也只有这么多猫,所以很快就会用完猫名密码。
    【解决方案3】:

    基于@Mido 和@HeyHeyJC 的回答,这里是为coturn 构建凭据的Python 实现。

    import hashlib
    import hmac
    import base64
    from time import time
    
    user = 'your-arbitrary-username'
    secret = 'this-is-the-secret-configured-for-coturn-server'
    
    ttl = 24 * 3600 # Time to live
    timestamp = int(time()) + ttl
    username = str(timestamp) + ':' + user
    dig = hmac.new(secret, username, hashlib.sha1).digest()
    password = base64.b64encode(dig).decode()
    
    print('username: %s' % username)
    print('password: %s' % password)
    

    这是一个web application,用于测试您的 coturn 服务器的登录。使用turn:host.example.com 作为服务器名称。

    【讨论】:

    • 我不得不使用 bytes(secret, 'utf-8')bytes(username, 'utf-8') (Python3.9)
    【解决方案4】:

    我最近遇到了类似的问题(让 REST API 与 TURN 服务器一起工作)并了解到 TURN 服务器根本不支持 REST API 调用,并且当我们在转配置。 draft 仅提供有关我们在实现此类 REST API 时需要考虑的事项的信息,我们需要自行创建 API 或使用 turnhttp 之类的东西来生成临时用户名密码组合。

    正如@mido 所详述的,您可以在应用程序本身中实现用户名/密码生成部分。但是,如果您有理由将其与应用程序分开并希望将其实现为完全不同的 API 服务,而不是按照 draft 实现完整的 API,我遇到了另一个 post,其中 OP 提供了一个 PHP生成临时用户名和密码的脚本,一旦您将 hash_hmac() 函数修改为以下内容,这个脚本就可以很好地工作,

    $turn_password = hash_hmac('sha1', $turn_user, $secret_key, true);
    

    我们需要对 hash_hmac 的 RAW 输出进行 base64 编码以使其正常工作,我相信这就是为什么它不适用于该链接中的 OP。

    您应该能够使用 turnutils_uclient 命令测试身份验证,以验证临时用户名/密码组合是否按预期工作。

    turnutils_uclient -y -u GENERATED_USERNAME -w GENERATED_PASSWORD yourturnserver.com
    

    一旦您验证了身份验证并确认其工作正常,您就可以为 PHP 脚本设置网络服务器以使其可用于您的应用程序并获取临时用户名/密码组合。此外,您还需要实施其他安全设置(身份验证)以保护 API 免受未经授权的访问。

    我知道这是一篇旧帖子,只是在这里分享我的发现,希望有一天它对某人有用。

    【讨论】:

    • 感谢您提到我们必须使用 RAW 输出,它帮助我让它工作。但是如果人们读到这篇文章,我建议做一个真正的测试(例如使用 WebRTC),即使turnutils_uclient 命令失败并显示0: error 401 (Unauthorized)。在我的情况下,命令失败但当我强制 Firefox 使用 TURN 服务器时 WebRTC 工作,也许你知道为什么?我在安装了 TURN 服务器的 Linux 服务器上测试了该命令。
    【解决方案5】:

    这是我使用 TTL 的 c# 实现

    public string[] GenerateTurnPassword(string username)
    {
        long ttl = 3600 * 6;
        var time = DateTimeOffset.Now.ToUnixTimeSeconds() + ttl;
        var newuser = time + ":" + username;
        byte[] key = Encoding.UTF8.GetBytes("YOURSECRET");
        HMACSHA1 hmacsha1 = new HMACSHA1(key);
        byte[] buffer = Encoding.UTF8.GetBytes(newuser);
        MemoryStream stream = new MemoryStream(buffer);
        var hashValue = hmacsha1.ComputeHash(stream);
        string[] arr = new string[2];
        arr[0] = Convert.ToBase64String(hashValue);
        arr[1] = newuser;
        return arr;
    }
    
    

    【讨论】:

      【解决方案6】:

      @Augusto Destrero 提供的实现将在 Python 3.7.6 上导致 TypeError: key: expected bytes or bytearray, but got 'str',对于正在寻找另一个 Python 实现的任何人,这里有一个示例:

      import time
      import hmac
      import hashlib
      import base64
      
      secret = b'abcdefghijkmln'
      
      def generateTurnUsernamePwd():
          username = "arbitry username here"
          password = hmac.new(secret, bytes(username, 'UTF-8'), hashlib.sha1).digest()
          passwordStr = base64.b64encode(password).decode("utf-8")
          
          return username,passwordStr
      
      print(generateTurnUsernamePwd())
      

      主要区别在于hmac lib 中的keymessage 关键字参数在新版本中必须是字节,而在旧版本中则需要str。

      【讨论】:

        【解决方案7】:

        我认为值得在答案中添加 coturn 有关此主题的文档的实际文本,并为感兴趣的人添加link

        --auth-secret TURN REST API 标志。设置基于身份验证机密的特殊 WebRTC 授权选项的标志。这 功能目的是支持描述的“TURN Server REST API” 在下面的 TURN REST API 部分中。此选项使用时间戳 作为组合用户名的一部分:usercombo -> "timestamp:username", 转用户-> 用户组合,转密码-> base64(hmac(input_buffer = usercombo, key = shared-secret))。这 允许将 TURN 凭证计入特定的用户 ID。如果 您没有合适的 id,可以单独使用时间戳。这 选项只是打开基于秘密的身份验证。实际上 秘密值由选项 static-auth-secret 定义, 或者可以在数据库的turn_secret表中找到。

        【讨论】: