TLS Websocket转发无法按预期工作

时间:2018-01-14 13:27:51

标签: javascript nginx playframework websocket

我有一个可以从我的客户端代码到达的工作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

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

1 个答案:

答案 0 :(得分:0)

我找到了一个针对这个问题的解决方法,将来会留给任何人使用。

所以我在尝试:

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

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

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