将 WebSocket 升级到 TLS

Posted

技术标签:

【中文标题】将 WebSocket 升级到 TLS【英文标题】:Upgrading WebSockets to TLS 【发布时间】:2017-02-25 16:00:11 【问题描述】:

对于 HTTP,可以使用 301 响应将所有请求升级到 HTTPS。

然而,对于 websocket,它似乎并不那么容易。如果我将 ws://127.0.0.1 请求重定向到 wss:/127.0.0.1,我会使用 websocket.org 上的测试在浏览器中收到“错误:未定义”(是的,证书是受信任的并且适用于 wss 如果直接使用)。发出初始请求,并发出重定向。但是,TLS 端口上没有第二个请求。

该规范仅简要介绍了重定向。

是否可以将 ws 升级到 wss? 即使有重定向响应,我是否需要发送特定于 WebSocket 的标头? (目前,我不这样做 - 并且规范列出了在完成握手之前重定向) 还有什么我想念的吗?

【问题讨论】:

【参考方案1】:

对于 HTTP,可以使用 301 响应将所有请求升级到 HTTPS。

(吹毛求疵)这并不是真正的请求升级,而是导致不同请求的重定向。

ws 可以升级到 wss 吗?

根据websocket standard (RFC 6455):

如果从服务器收到的状态码不是 101,则 客户端根据 HTTP [RFC2616] 程序处理响应。在 特别是,客户端可能会执行身份验证,如果它 收到 401 状态码; 服务器可能会重定向客户端 使用 3xx 状态码(但客户不需要遵循 他们)等。

所以是的,某些客户端可能支持它,但其他客户端不支持。例如,在 Firefox 中,相关属性 network.websocket.auto-follow-http-redirects 默认为 false,即默认情况下它不遵循重定向。

即使有重定向响应,我是否需要发送特定于 WebSocket 的标头?

这些仅与升级到 websocket 的请求有关,与重定向无关。这意味着标头只能在升级响应中发送(状态码 101)。

【讨论】:

嗯 kay :( 很高兴知道。对于尊重重定向的客户 => 一个简单的HTTP/1.1 301 Moved Permanently\r\nLocation: wss://host:port/requestTarget?query\r\n\r\n 是要走的路吗?转发到 https 而不是 wss 也可以,这样重定向端点不需要解析 websocket 标头?是否有更好的解决方案来执行实际有效的重定向? @Etan:websocket 客户端应该如何处理重定向到 http(s)?一个 websocket 客户端想要使用 websocket,如果对方不这样做(“...不需要解析 websocket 标头”),那么 websocket 升级将失败。但是,如果客户端支持 websocket 的重定向,您的示例重定向到 wss:// 应该可以工作。 是的,我假设的。想知道是否存在允许通用重定向到 SSL 端点的例外,这些端点不关心它们重定向到另一个端口的内容。将调整我的以将 websocket 请求重定向到 wss:// 并调整客户端以确保他们始终直接访问 wss 版本。【参考方案2】:

这取决于 webSocket 客户端实现是否处理 3xx 状态码。 webSocket specification 不需要客户端实现来执行此操作。这是规范中的引述:

如果从服务器收到的状态码不是 101,则 客户端根据 HTTP [RFC2616] 程序处理响应。在 特别是,客户端可能会执行身份验证,如果它 收到 401 状态码;服务器可能会重定向客户端 使用 3xx 状态码(但客户不需要遵循 它们)等。否则,请执行以下操作。

【讨论】:

常规 HTTP 301 响应的措辞相同——但是,对于这些响应,每个主要浏览器实际上都支持重定向。奇怪的是websockets有一个例外。

以上是关于将 WebSocket 升级到 TLS的主要内容,如果未能解决你的问题,请参考以下文章

如何将 HTTP 请求升级到 Websocket (Autobahn & Twisted Web)

在 HTTPS 页面上创建 websocket 对象时,如何阻止 chrome 将 websocket 从 WS 升级到 WSS

我可以从 websocket 升级回 http 吗?

Websocket 连接尝试失败,返回“连接:升级,关闭”。

动作线无法连接(升级到 WebSocket 失败)

tornado 只能升级到 websocket 错误