Twilio WebRTC TURN 中继在几分钟后随机停止工作

Posted

技术标签:

【中文标题】Twilio WebRTC TURN 中继在几分钟后随机停止工作【英文标题】:Twilio WebRTC TURN relay randomly stops working after a few minutes 【发布时间】:2019-01-18 11:58:42 【问题描述】:

我使用Twilio Network Traversal Service 作为本机应用程序的一部分我是working on 来执行对等远程桌面连接。我们实现了 WebRTC 协议栈的一个子集,它等效于 WebRTC 数据通道(不是 WebRTC 视频和音频协议)。使用 TURN 中继时,TURN 分配似乎在会话开始后几分钟到最多 12 分钟之间随机失效。这个问题看起来与one 非常相似,但在我的情况下,建议的解决方法(发送无声音频)是不可接受的,因为我没有实现 WebRTC 音频/视频协议。

在过去的两周里,我一直在努力解决这个问题,并将问题隔离为 Twilio 服务本身。为了比较,我使用了一个基于 Web 的 WebRTC 数据通道演示,它使用了 firefox 和 Xirsys TURN server cloud。我有wireshark捕获显示firefox与Twilio断开连接,就像我的本机应用程序一样,而完全相同的firefox演示在使用Xirsys服务器时没有断开连接。

我最初使用的是 Xirsys,但我在他们的服务中遇到了一些不稳定性,这让我改用了 Twilio,这就是为什么我宁愿让 Twilio 解决这个问题而不是回到 Xirsys。至少,我宁愿有两个 WebRTC 托管服务提供商可供我选择,我知道它们应该可以正常工作。这就是为什么我要花时间详细解释这个问题以便解决它。

这是两个使用 WebRTC 数据通道和 Twilio TURN 中继服务器的 Wireshark 捕获(过滤掉对等数据消息)显示 firefox:

在第一次捕获 4 分钟后,流量停止中继,在第二次捕获大约 11 分钟后。在这两个捕获中,firefox 检测到流量停止中继(在数据通道级别),并通过发送一个生命周期为零的刷新请求数据包来尝试正常断开连接。两次正常断开都会导致 437 Allocation Mismatch 错误,表明服务器甚至不知道 firefox 正在尝试正常关闭的分配。

对于我的本机应用程序,这通常会采用 CreatePermission Request 消息的形式,该消息失败并出现 438“Wrong nonce”错误,这基本上是客户端尝试更新不再分配的权限时应该发生的情况存在。错误代码 438 通常表示“Stale nonce”,这并不是真正的错误,而是表明 nonce 已过期,客户端应使用“错误”消息中包含的新 nonce 重试。我花了一段时间才弄清楚,但即使错误代码是438,错误字符串也不一样。我在 Xirsys 中观察到一个真正过时的 nonce 错误,并使用错误响应中的新 nonce 成功更新了我的权限,所以我知道我可以在我的实施中正确处理这种情况。

这里是我使用的 WebRTC 数据通道演示的源代码: https://github.com/devolutions/webrtc-demo

为了比较,这里是使用 Xirsys TURN 服务器云的相同 firefox 数据通道演示:

在这个捕获中,我让演示运行了大约 16 分钟(它的运行时间比这要长得多,我尝试过的最长时间是两个小时)。我们可以看到流量在整个会话期间不断中继,并且 CreatePermission 请求不断被 firefox 成功发送。最后,优雅断开是由 Firefox 关闭 WebRTC 数据通道触发的(而不是由于流量不再被中继而被关闭)。与 Twilio 捕获相反,生命周期为零的 Refresh 请求是成功的:Xirsys TURN 服务器仍然知道分配并按预期发回成功响应。

应该注意,ICMP 不可达错误是正常的,因为我认为在这种情况下,当响应返回时,firefox 不再监听给定端口。换句话说,它发送生命周期为零的刷新请求,并且不等待回复返回。

目前,我别无选择,只能返回 Xirsys,但我非常希望 Twilio 网络遍历服务能够修复。如果您对此问题有更多疑问,请告诉我。

我已经上传了wireshark捕获here供参考。

编辑:我修改了 webrtc 演示页面,使其在 ice 连接状态设置为“断开连接”时不会关闭连接。现在,当冰连接状态变为“失败”时,我得到了真正的断开连接。然而,它实际上并没有改变任何东西,因为在这种情况下,状态从“断开连接”变为“失败”只需要几秒钟。

由于我有新的相关屏幕截图和捕获,我正在更新原始问题以澄清 Philipp Hancke 指出的某些问题:

首先,这里是一个带有ice连接状态修复的新捕获(浏览器仅在状态变为“失败”时关闭连接):

有趣的是,这次会话持续了整整 18 分钟。这是在星期六早上拍摄的,所以我猜这个问题可能与 twilio 服务器上的当前工作负载有关。然而,它失败的方式与迄今为止对我来说总是一样的方式失败了。作为奖励,我们甚至有一个有效的、过时的随机数响应,可以被 firefox 正确处理。

但是,如果我们对同一捕获采取不同的看法,我们可以看到流量在 30 秒内停止中继,然后 firefox 认为连接已被丢弃并发送生命周期为零的刷新请求。与之前的捕获一样,服务器响应分配不匹配错误,表明它不知道 firefox 正在谈论哪个分配。

最后发送的八个数据包大小相同,所以我猜测它们是重传。重传 30 秒后,SCTP 可能会认为传输已被丢弃。

关于生命周期为零的刷新请求,我做了一个测试,我很早就从浏览器关闭了连接。在这种情况下,服务器识别分配并返回成功响应:

分配不匹配是最容易观察到的症状,但在我使用本机应用程序进行的测试中,我发现非零生命周期的刷新请求和 CreatePermission 请求(438“错误随机数”错误)有类似的错误。但是,由于浏览器在 30 秒没有中继数据后关闭连接,因此在当前的 webrtc 演示中很难观察到这些错误。如果我们可以将该超时更改为 10 分钟,我们也会看到这些错误。

【问题讨论】:

多么好的问题?!​​!!!! 【参考方案1】:

很好的问题描述!

没有服务器日志,很难确定哪里出了问题。我尝试使用运行最新版本的 coturn 并显示与 Twilio 服务器相同的行为的出现.in TURN 服务器。 Xirsys 似乎正在运行 coturn 的自定义版本(来自软件领域的 Coturn-0.5 'Xirsys Turn Services',但 coturn 从未有过这样的版本)。

在两次捕获中,firefox 都检测到流量停止中继(在数据通道级别),并通过发送生命周期为零的刷新请求数据包尝试正常断开连接。

不完全是。生命周期为 0 的刷新请求用于丢弃分配。到那时,服务器返回什么都无关紧要,因为无论如何连接都无法修复。

这是由于如果iceconnectionstate 更改为disconnected 时peerjs 关闭peerconnection,here 在您的捆绑库版本中。

这过于激进(甚至没有解决问题),我们已经讨论了规范应该做什么来尝试通过冰重启here 来解决问题,这也链接到了一个很好的解释断开状态。

断开状态可能是因为丢失了一些数据包。但这是在轻微拥塞时可能发生的事情。我建议在断开连接的情况下删除 pc.close()。

如果您正在寻找其他 TURN 提供商,Tokbox 提供了same service。对于数据通道,正确运行的分布式 TURN 网络的延迟并不像 VoIP 那样重要,因此您可以在一个位置运行自己的服务器。

【讨论】:

感谢您花时间阅读问题描述并提供详细答案。我一定会获得一个 tokbox 帐户并尝试他们的服务。我已经在 PeerJS 库中解决了这个问题并做了一些新的测试。我也更新了我原来的问题,提供了有关断开连接的更多详细信息。您报告最新的 coturn 服务器具有与 twilio 相同的行为这一事实让我担心 - 这怎么正常?从我的角度来看,连接只是在没有警告的情况下随机断开。是的,我们可以重新连接,但这会带来非常糟糕的用户体验。 这听起来像是 coturn 中的一个讨厌的错误。作为基于 UDP 的,TURN 有很多计时器,可以防止在客户端离开时保留资源而不释放这些资源。例如,这可能是由于其中一个客户端未刷新权限(或刷新请求丢失)引起的。权限到期,导致数据包被静默丢弃,您遇到了问题。要排除这种情况,必须在隔离环境中运行测试。 另一个可能的原因是凭证是基于时间的,并且在需要在后续分配请求中验证它们时过期。这应该可以工作(见tools.ietf.org/html/…)但是......现在可能是时候在coturn存储库中提交一个错误了。 或在他们的讨论列表上发帖。只要有指控,就比提交错误要好:-) 我已经检查了 RFC,协议实现看起来都很好,firefox 和 chrome 都在正确的时间触发了计时器(刷新请求和创建权限请求)。我正在努力手动配置 coturn 以查看是否可以重现该问题,但我主要担心的是我的测试 coturn 服务器没有足够的流量来触发任何事情。我刚刚用 ubuntu 18.04 打包的版本 4.5.0.3 做了一个测试,似乎运行良好。你能告诉我你使用的是哪个版本的appear.in服务器吗?

以上是关于Twilio WebRTC TURN 中继在几分钟后随机停止工作的主要内容,如果未能解决你的问题,请参考以下文章

WebRTC:Firefox 中缺少中继候选人

基于webRTC的前端远程控制系统

为 WebRTC PeerConnections 强制 TCP

WebRTC 如何决定使用哪些 TURN 服务器

WebRTC - 我需要指定多少 STUN/TURN 服务器?

硬核讲解:编译webrtc协议为什么需要turn服务器?