为什么现有的WebSocket客户端实现不支持代理?

29
Web Socket 可以检测到代理服务器的存在,并自动建立一个隧道通过代理。该隧道是通过向代理服务器发出 HTTP CONNECT 声明来建立的,该声明请求代理服务器打开到特定主机和端口的 TCP/IP 连接。一旦隧道建立,通信就可以无阻碍地通过代理进行。由于 HTTP/S 的工作方式类似,因此基于 SSL 的安全 Web Sockets 可以利用相同的 HTTP CONNECT 技术。[1]
好的,听起来很有用!但是,在迄今为止看到的客户端实现中(Go [2]、Java [3]),我没有看到任何与代理检测相关的内容。
我是否漏掉了什么,还是这些实现只是年轻?我知道 WebSockets 是非常新的,客户端实现可能同样年轻和不成熟。我只想知道我是否对代理检测和处理有所遗漏。[1] http://www.kaazing.org/confluence/display/KAAZING/What+is+an+HTML+5+WebSocket [2] http://golang.org/src/pkg/websocket/client.go [3] http://github.com/adamac/Java-WebSocket-client/raw/master/src/com/sixfire/websocket/WebSocket.java

3
他们不这样做?啊!我一直想知道为什么我的代码不起作用!浪费了整个上午,但现在它似乎可以工作了,因为我删除了代理。谢谢你问这个问题! - Tieme
1
@Tieme证明了问题和答案同样重要。 - user1382306
6个回答

46

让我来解释一下您可能遇到的不同成功率。虽然HTML5 Web Socket协议本身不知道代理服务器和防火墙,但它具有与HTTP兼容的握手,以便HTTP服务器可以与Web Sockets网关或服务器共享其默认的HTTP和HTTPS端口(80和443)。

Web Socket协议定义了ws://和wss://前缀,分别表示WebSocket和WebSocket安全连接。这两种方案都使用HTTP升级机制升级到Web Socket协议。一些代理服务器是无害的,并能正常地使用Web Sockets; 其他代理服务器将阻止Web Sockets正确工作,导致连接失败。在某些情况下,可能需要进行其他代理服务器配置,并且某些代理服务器可能需要升级以支持Web Sockets。

如果未加密的WebSocket流通过透明代理服务器或显式代理服务器连接到WebSocket服务器,则无论代理服务器的行为如何,今天几乎肯定会导致连接失败(在未来,代理服务器可能会变得Web Socket感知)。因此,仅应在最简单的拓扑中使用未加密的WebSocket连接。

如果使用加密的WebSocket连接,则在浏览器配置为使用显式代理服务器时,Web Sockets Secure连接中使用传输层安全性(TLS)确保发出HTTP CONNECT命令。这建立了一个隧道,在Web Sockets Secure客户端和WebSocket服务器之间通过HTTP代理提供低级别的端到端TCP通信。在透明代理服务器的情况下,浏览器不知道代理服务器,因此不会发送HTTP CONNECT。但是,由于线路流量是加密的,中间透明代理服务器可能仅允许加密流量通过,因此如果使用Web Sockets Secure,则WebSocket连接成功的机会要大得多。当然,使用加密并不是免费的,但通常提供最高的成功率。

一个展示该过程的方法是下载和安装 Kaazing WebSocket Gateway--一种高度优化的、感知代理的WebSocket网关,它提供本地WebSocket支持以及针对旧版浏览器的标准完整仿真。


Peter,感谢您的评论。但是它似乎回避了问题。你有点回答了这个问题:使用明确代理配置的浏览器将发出HTTP CONNECT。问题是关于WS客户端,而不仅仅是浏览器。我尝试过的几个客户端都没有任何明确的代理支持。我可以从你的回答中推断出,对于这样的客户端来说,是否拥有这样的支持(就像浏览器一样)是由他们自己决定的,只是还没有实现(到目前为止)? - z8000
2
抱歉,我误解了你的问题 - 你是对的,那些客户端不支持代理。 - Peter Lubbers
1
你的帖子有75%是从维基百科文章中复制粘贴的。请学习如何使用块引用并引用您的来源。 - Emile Cormier
22
哎呀!我查看了维基百科文章的版本历史,发现是你撰写了那些段落。我感到非常尴尬,对此道歉。 :-( 我会回滚我的编辑。(这里我在抨击你没有引用自己的作品,哈哈) - Emile Cormier
1
@PeterLubbers,关于“其他人会阻止Web Sockets正常工作,导致连接失败”的问题;但是为什么 - Pacerier
1
@PeterLubbers,关于“今天注定会失败”的问题,但是为什么会失败呢? - Pacerier

2
答案是这些客户端不支持代理。-Occam

1
答案是使用HTTP CONNECT指令。使用HTTP CONNECT指令的连接对于客户端来说看起来像一个基本的TCP连接,因此他会在之后发送Websocket握手请求。他会为一个Websocket握手请求发送两个HTTP请求,一个给代理服务器,一个给Websocket服务器。 - sinni800

1

WebSocket协议出现时,通信渠道已经建立。WebSocket是基于TCP和HTTP构建的,因此您不必关心这些协议已经完成的事情,包括代理。

当WebSocket连接建立时,它始终从HTTP/TCP连接开始,稍后在WebSocket的“握手”阶段进行“升级”。此时建立了隧道,因此代理是透明的,无需关心它们。


那么 HTTP 连接是什么意思呢? - z8000
2
@z8000 HTTP CONNECT建立了一个HTTP连接。它是一个普通的GET请求,如果服务器支持WebSocket协议,则稍后进行升级。WebSocket协议使用HTTP来协商连接,并且正如您所建议的那样,绕过代理。 - Tihauan
1
HTTP CONNECT 是什么?不是 HTTP CONNECT 是什么?根据维基百科:“另一种基于 HTTP 的隧道方法使用 HTTP CONNECT 方法/命令。客户端向 HTTP 代理发出 HTTP CONNECT 命令。代理然后建立到特定服务器:端口的 TCP 连接,并在服务器:端口与客户端连接之间中继数据。”我在 WebSocket 客户端中没有看到通过 HTTP CONNECT 与代理通信的内容。例如,考虑 libcurl API 中的 CURLOPT_PROXY。 - z8000

0
关于websocket客户端和透明代理,我认为websocket客户端连接大多数情况下会失败,原因如下(未经测试):
  • 如果连接是明文的,由于客户端不知道它正在与一个HTTP代理服务器通信,它不会发送“CONNECT TO”指令,将HTTP代理转换为TCP代理(在websocket握手之后需要)。如果代理本身支持websocket并且以ws方案处理URL,则可能会起作用。

  • 如果连接是SSL加密的,则透明代理无法知道应该连接到哪个服务器,因为它必须解密https请求中的主机名。它可以通过动态生成自签名证书(例如SSLStrip)或提供自己的静态证书并解密通信来实现,但如果客户端验证服务器证书,则会失败(请参见https://serverfault.com/questions/369829/setting-up-a-transparent-ssl-proxy)。


0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接