【问题标题】:TLS Websocket forwarding not working as expectedTLS Websocket 转发未按预期工作
【发布时间】:2018-01-16 19:31:04
【问题描述】:

我有一个可用的 websocket,可以从我的客户端代码访问,如下所示:(不使用 Socket.io 或任何库,只是普通的 html5 websockets)

ws://localhost:9000/socket/connect

Websocket在Java Play Framework中实现

public WebSocket connect() {
    return WebSocket.Text.accept(request -> ActorFlow.actorRef(out -> SocketActor.props(out, jsonWebToken),
            actorSystem, materializer
    )
    );
}

无论如何,这工作正常,但是我现在想为网站设置 https 并在 nginx 上执行此操作。切换到 https 我还需要使用 wss 协议而不是 ws,因此我也想通过 nginx 代理 wss 调用,因此我遇到了问题。

我已经为 websocket 代理配置了我的 nginx,如此处所述https://www.nginx.com/blog/websocket-nginx/ 我的完整配置如下所示

upstream backend {
        server backend:9000;
}

server {
        listen 80;
        server_name _;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;
        server_name legato;
        ssl_certificate /etc/nginx/ssl/legato.crt;
        ssl_certificate_key /etc/nginx/ssl/legato.key;

        location /api {
                return 302 /api/;
        }
        location /api/ {
                proxy_pass http://backend/;
        }
        location /statics {
                root /var/www;
        }
        location /socket/connect {
                proxy_pass http://backend/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
        }
        location / {
            root /var/www/frontend;
            index index.html;

            try_files $uri /index.html;
        }
}

所以 /socket/connect 路由被转发到 websocket 后端路由。

从我的客户端 javascript 代码中,我现在像这样打开 websocket

socket = new WebSocket(wss://192.168.155.177/socket/connect);

这给了我错误

WebSocket connection to 'wss://192.168.155.177/socket/connect' failed: Error during WebSocket handshake: Unexpected response code: 200

有人可以向我解释一下这种情况有什么问题吗?

【问题讨论】:

  • 所以您刚刚将 nginx 更改为在前端使用 HTTPS,但 nginx 代理仍然通过 HTTP 连接到 Play 后端?
  • 没错,这就是我面临的问题

标签: javascript nginx playframework websocket


【解决方案1】:

我为这个问题找到了一个小解决方法,以后会留在这里给任何人。

所以我在尝试:

  • 为 NGINX 上的 Websocket 实现 SSL 加密。这不起作用,因为 NGINX 将再次通过 http 连接到 websocket。由于我没有使用任何 socket.io,这不起作用,因为后端不支持它
  • 在后端实施 SSL。这对我来说相当棘手。在 java 上切换到 https 涉及使用密钥库,此外,How to use TLS in Play!Framework WebSockets ("wss://") 建议即使我可以让 https 工作,也可能是 wss 仍然无法工作。所以在几次失败的尝试后,我放弃了这个。

解决方案是使用 stunnel,它允许我打开一个端口,加密任何传入流量并将其转发到另一个端口。所以我现在正在对端口 9433 上的流量进行 ssl 加密,并将其转发到后端未加密的 ws 端点,使其工作。

如果你不想在实际生产环境中使用它,你应该对这种方法的可扩展性进行一些研究,尤其是 stunnel。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2015-01-11
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多