WebSocket连接失败:WebSocket握手被取消。

18

我最近设置了一个EC2实例(在没有负载均衡器的VPC中),承认配置有点奇怪,但这是我们运行的Web应用程序所需的。

Web服务器(使用Haskell编写)正在端口4433上运行(标准端口已保留给Apache实例),并且正在接收从另一个系统广播的UDP数据包。 我已经打开了很多端口(仅在测试期间),如安全组中所示:

Custom TCP Rule    4433     tcp 0.0.0.0/0   ✔
Custom TCP Rule    8080     tcp 0.0.0.0/0   ✔
SSH                22       tcp 0.0.0.0/0   ✔
HTTP               80       tcp 0.0.0.0/0   ✔
HTTPS              443      tcp 0.0.0.0/0   ✔
Custom UDP Rule    30090    udp 0.0.0.0/0   ✔
Custom UDP Rule    30089    udp 0.0.0.0/0   ✔
JavaScript 的 TCP 套接字请求在此同一端口上设置套接字(使用分配给 AWS 公共 IP 的 URL),这是请求返回错误的位置:

WebSocket 连接到 'wss://[URL]:4433/projects/socket' 失败:WebSocket 开启握手被取消。

将套接字绑定到 0.0.0.0 将导致相同的错误。
为了启动 Haskell Web 服务器,我不得不引用 AWS 提供的 内部 IP,因为当引用弹性 IP 服务提供的 公共 IP 时无法运行。考虑到这可能是问题所在,我将套接字请求更改为以下内容...
wss://[internal ip]:4433/projects/socket

这里的错误是:

WebSocket连接到'wss://[内部IP]:4433/projects/socket'失败:建立连接时出错:net::ERR_CONNECTION_REFUSED

我认为这个错误很有道理,因为内部IP对外部世界不可用。

我在AWS上阅读的所有与WebSockets相关的内容都涉及ELB(弹性负载均衡器),而我并不需要其中的一个。我已经尝试了目前SO上所有已发布答案中的所有方法(有些问题甚至没有得到答案),但是都没有成功。我还向Amazon建立了一个支持案例(将近24小时前),但还没有收到回复。

其他信息

导航到http://[URL]:4433/projects/socket会显示“WebSocket可用”,其中URL是我们希望使用的URL,也是AWS提供的公共DNS。

运行netstat -plunt会显示以下内容:

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 [internal IP]:8080      0.0.0.0:*               LISTEN      -
tcp        0      0 [internal IP]:4433      0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
tcp6       0      0 :::443                  :::*                    LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      -
udp        0      0 [internal IP]:30089     0.0.0.0:*                           -
udp        0      0 0.0.0.0:30090           0.0.0.0:*                           -
udp        0      0 0.0.0.0:11950           0.0.0.0:*                           -
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -
udp6       0      0 :::38450                :::*                                -

有人在 AWS 上使用 WebSockets 时遇到类似的问题吗?如果有,你是如何解决这个问题的?


1
我对AWS没有太多经验,但这个问题读起来真是太棒了!(感觉在SO上找到了一颗钻石 :)) - Rizier123
不,证书不是自签名的。@Samar - Jay Blanchard
我已经尝试过这样做,但它以与@Samar相同的方式失败。 - Jay Blanchard
@Sarmar 谢谢你的帮助。我已经验证了恰当的SSL证书正在使用,就像你建议的那样。然而,我仍然感到困惑,AWS的工作人员表示我已经正确地设置好一切。换句话说,他们也不知道发生了什么。 - Jay Blanchard
1
我感觉有些好消息正朝我们走来,山姆,我说得对吗? - @JayBlanchard - Funk Forty Niner
显示剩余3条评论
3个回答

20

哈斯克尔服务器和Apache服务器之间存在SSL证书不匹配的问题。

必须在哈斯克尔服务器上重新构建包含新证书信息的实例。此外,EC2实例未安装适当的SSL库(libssl0.9.8 libssl-dev),这在重建哈斯克尔服务器时导致了问题。知道EC2实例是一个“空画布”,没有进行该安装是我的错误。

一旦安装了libssl,就能用它重新构建哈斯克尔服务器,并指向新证书。一旦证书“匹配”,websocket问题就消失了。

再次强调,我们的情况非常特殊。我们有一个Apache服务器(端口80和443)和一个Haskell服务器(端口8080和4433),它们彼此通信,在websocket上执行pub-sub操作。两个服务器之间的证书不匹配(无论类型如何,可能是多个Apache实例都不会有影响)会导致SSL警告。来自SSL的任何警告都会取消建立或维护websocket的任何尝试(因此出现“握手取消”消息)。

另一个StackOverflow帖子提供了一些线索,在这个过程中非常有帮助。更具体地说,是以下警告 -

问题的关键在于:如果您的SSL证书引发任何警告,则wss:// WebSocket连接将立即失败,并且没有公认的方法可以检测到此问题。


1
很高兴听到这个消息,Sam!又是一个愉快的结局;-) - Funk Forty Niner
1
谢谢 Ralph!没有那个负担,我感觉轻松多了。@Fred-ii- - Jay Blanchard

-1
这个错误可能是由于在前端中没有正确放置websocket URL引起的。

请查看此答案https连接中的Websockets

正确放置前端URL的方法是"wss://example.com/wss/"

错误的前端URL放置方式为

wss://example.com:8080/wss/ -> port no should not be mentioned
ws://example.com/wss/ -> url should start with wss only.
wss://example.com/wss -> url should end with / -> most important

-1

当我从file:// URL使用基于blob的webworker时,遇到了这个与websockets相关的错误。我怀疑在web服务器上运行可能会解决这个问题;我通过关闭SSL来进行调试并解决了它。


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