Been ripping hair out because I cannot find out why I cannot connect to my WebSocket
server through HTTPS
.
So, I have an Express 4 server running a vue
app. It uses the ws
library from npm to connect to the WebSocket
server. The nginx is 1.10.3. I use LetsEncrypt to secure it.
When I go online, I get (in the console):
main.js:12 WebSocket connection to 'wss://play.mysite.com:8443/' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
Line 12:
window.ws = new WebSocket(
${tls}://${window.location.hostname}:${port}
);`
That is wss://play.mysite.com:8443
. It is indeed on a subdomain.
Here is my nginx
block:
update: I got it!
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
}
As you see, we have the subdomain on https://play.mysite.com
. My Express
server always listen on port 4000
and my WebSocket
server listens to wss
/ port 8443
on production.
When I view the /var/log/wss-error-ssl.log
, I get:
2018/03/01 04:45:17 [error] 30343#30343: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 68.117.172.118, server: play.mysite.com, request: "GET /static/css/app.67b8cb3fda61e1e2deaa067e29b52040.css HTTP/1.1", upstream: "http://[::1]:4000/static/css/app.67b8cb3fda61e1e2deaa067e29b52040.css", host: "play.mysite.com", referrer: "https://play.mysite.com/"
So, what exactly am I doing wrong?
The proxy_pass
was set right. Listening to port 8443
for WebSocket
on both client/server. What is the meaning? Thank you.
edit: and yes, I know the port 8443
is running:
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 [::]:*
TL'DR Add a second location block for /websocket
and have the javascript client hit wss://play.mysite.com/websocket
I see a couple of issues with your nginx server conf.
Nginx is not listening on port 8443
yet your javascript is hitting wss://play.mysite.com:8443
. So while nginx is serving up ports 443
and 80
for the play.mysite.com
domain, you javascript is trying to bypass nginx using wss
(TLS) and hit NodeJS directly -- though I suppose you meant to offload the SSL onto Nginx. The wss call must go through nginx in order for the SSL handshake to be successful.
You are passing all calls to localhost:4000
. Instead I suggest that you have two location blocks location / { ... }
and location /websocket { ... }
. This way in the second websocket location block you can proxy pass the calls to localhost:8443
. This would require the client to connect to wss://play.mysite.com/websocket
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With