通过nginx 1.10.3和LetsEncrypt

时间:2018-02-26 00:21:09

标签: node.js nginx https websocket

由于我无法找到无法通过WebSocket连接到我的HTTPS服务器的原因,所以我们一直在扯掉头发。

所以,我有一台运行vue应用的Express 4服务器。它使用来自npm的ws库连接到WebSocket服务器。 nginx是1.10.3。我使用LetsEncrypt来保护它。

当我上线时,我(在控制台中):

  

main.js:12'wss://play.mysite.com:8443 /'的WebSocket连接失败:连接建立错误:net :: ERR_CONNECTION_CLOSED

第12行:

  

window.ws = new WebSocket(${tls}://${window.location.hostname}:${port});`

那是wss://play.mysite.com:8443。它确实位于子域。

这是我的nginx块: 更新:我明白了!

upstream websocket {
    server 127.0.0.1:8443;
}

server {
    root /var/www/play.mysite.com/dist;
    index index.html;

    access_log /var/log/wss-access-ssl.log;
    error_log /var/log/wss-error-ssl.log;

    server_name play.mysite.com www.play.mysite.com;

    location /ws {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    listen [::]:443 ssl ipv6only=on default_server; # managed by Certbot
    listen 443 ssl http2 default_server; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/play.mysite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/play.mysite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

如您所见,我们在https://play.mysite.com上有子域名。我的Express服务器始终在端口4000上侦听,而我的WebSocket服务器在生产时侦听wss /端口8443

当我查看/var/log/wss-error-ssl.log时,我得到:

  

2018/03/01 04:45:17 [错误] 30343#30343:* 1连接()失败(111:连接被拒绝)连接上游时,客户端:68.117.172.118,服务器:play.mysite.com ,请求:“GET /static/css/app.67b8cb3fda61e1e2deaa067e29b52040.css HTTP / 1.1”,上游:“http://[::1]:4000/static/css/app.67b8cb3fda61e1e2deaa067e29b52040.css”,主持人:“play.mysite.com”,引荐来源:“https://play.mysite.com/”< / p>

那么,我究竟做错了什么?

proxy_pass设置正确。在客户端/服务器上侦听8443的端口WebSocket。什么意思?谢谢。

编辑:是的,我知道端口8443正在运行:

root@MySITE:/var/www/play.mysite.com# netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:https                 *:*                     LISTEN
tcp        0      0 localhost:4000          *:*                     LISTEN
tcp        0      0 localhost:mysql         *:*                     LISTEN
tcp        0      0 *:http                  *:*                     LISTEN
tcp        0      0 *:ssh                   *:*                     LISTEN
tcp6       0      0 [::]:8443               [::]:*                  LISTEN
tcp6       0      0 [::]:https              [::]:*                  LISTEN
tcp6       0      0 [::]:http               [::]:*                  LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
udp        0      0 *:bootpc                *:*
udp        0      0 45.76.1.234.vultr.c:ntp *:*
udp        0      0 localhost:ntp           *:*
udp        0      0 *:ntp                   *:*
udp6       0      0 2001:19f0:5:2b9c:54:ntp [::]:*
udp6       0      0 fe80::5400:1ff:fe61:ntp [::]:*
udp6       0      0 localhost:ntp           [::]:*
udp6       0      0 [::]:ntp                [::]:*

1 个答案:

答案 0 :(得分:4)

TL&#39; DR为/websocket添加第二个位置区块,并让javascript客户端点击wss://play.mysite.com/websocket

我发现你的nginx服务器conf有几个问题。

  1. Nginx未在端口8443上侦听,但您的javascript正在点击wss://play.mysite.com:8443。因此,虽然nginx正在为443域提供端口80play.mysite.com,但是javascript正试图使用​​wss(TLS)绕过nginx并直接命中NodeJS - 尽管我想你打算将SSL卸载到Nginx上。 wss调用必须通过nginx才能使SSL握手成功。

  2. 您正在将所有来电传递给localhost:4000。相反,我建议您有两个位置区块location / { ... }location /websocket { ... }。这样,在第二个websocket位置块中,您可以代理将调用传递给localhost:8443。这将要求客户端连接到wss://play.mysite.com/websocket