通过 nginx 代理安全 websocket 到 Play 服务器

Proxy secure websocket to Play server through nginx

我是 运行 一个 Play 框架应用程序,其中 javascript 的一部分需要连接到服务器上的 websocket。 服务器是 运行 Play 应用程序前面带有 SSL 的 nginx 代理,具有以下设置:

proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=one:10m max_size=500m;
proxy_cache_methods GET HEAD;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 10m;
proxy_http_version 1.1;

upstream backend {
    server 127.0.0.1:9001;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    ssl on;
    server_name www.studiecirkel.net;
    gzip off;

    ssl_certificate     /home/sfr/certs/ssl-bundle.crt;
    ssl_certificate_key /home/sfr/certs/server.key;
    ssl_session_timeout 5m;
    ssl_ciphers     EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass https://backend;
        auth_basic "Internt alpha-test";
        auth_basic_user_file /home/sfr/studiecirkel/.htpasswd;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        tcp_nodelay on;
    }
}

javascript 如下所示:

var chatSocket = new WS("@routes.HomeController.connectChat().webSocketURL(request)");

connectChat 方法如下所示:

public LegacyWebSocket<JsonNode> connectChat() {
        return new LegacyWebSocket<JsonNode>() {
            public void onReady(WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out){
                // Some internal code here
            }
        };
    }

当一切都在本地主机上时,这工作正常,但现在服务器在云端,我在 Chromium 中收到以下错误:

WebSocket connection to 'wss://backend/messages/socket/' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED

我还尝试将 proxy_pass 指令地址从后端切换到 127.0.0.1:9001,然后我得到 ERR_CONNECTION_REFUSED。

如果我尝试使用 "proxy_pass http://backend" 并切换到代理后面的非 SSL,浏览器会提示 websocket 连接不安全并且无法连接。

这里可能有什么问题? websockets 是否必须能够直接连接到代理 URL?支持 SSL 的 websockets 不能这样工作吗?

这个代码有问题

var chatSocket = new WS("@routes.HomeController.connectChat().webSocketURL(request)")

服务器端已解决,因此出现ERR_NAME_NOT_RESOLVED错误。当客户端无法解析主机时出现 DNS 错误,在您的例子中是 backend 并且浏览器无法解析它。

尝试用下面的代码替换它,看看它是否有效

var chatSocket = new WS("messages/socket/");

更新。 似乎上面的代码还不够。下面是从文档对象

获取主机的方法
var webSocketURL = 'wss://' + window.location.host + '/messages/socket/';
var chatSocket = new (webSocketURL);