wss connection to node ws server via nginx, ERR_CERT_AUTHORITY_INVALID - node.js

I have a websocket server running behind nginx.
Connecting via http works ok (ws://mywebsite.com) with following nginx config:
http {
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location /myWebSocket {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:5000;
}
}
}
I'd like to connect to this via https (wss://mywebsite.com) and have tried this:
http {
server {
listen 443 ssl http2 ;
listen [::]:443 ssl http2 ;
server_name mywebsite.com; # managed by Certbot
root /usr/share/nginx/html;
ssl_certificate /etc/mycert.pem;
ssl_certificate_key /etc/mykey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
location /myWebSocket {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:5000;
}
}
}
However, I get a ERR_CERT_AUTHORITY_INVALID on the browser side (e.g. with wss://myWebsite/myWebSocket).
My understanding is that WSS is a connection to a standard websocket via https, is this correct?
Is my approach above correct?
Is there something obvious I'm doing wrong?
To confirm the cert was installed with certbot, and the e.g. https://example.com works.
Note also, there is another server block listening on 443, this does not define the /myWebSocket location (I think it is the nginx default ssl block that is superceded by certbot block).
Edit: note removing that first ssl server block results in the browser side websocket connection error message changing to ERR_CERT_COMMON_NAME_INVALID.
Another Edit: I was connecting using the server's IP address not the DNS name - that removed the error. :-)

Related

Socket proxy-pass from https to http

We have recently configured https for our backend server and are now running into some issues with socket. It seems that the sockets sort of work but it doesn't seem to transfer data between devices as intended. The socket is on port 3000 and instead of configuring SSL certification with sockets I just proxy_passed HTTPS requests to localhost port 3000. My suspicion is that it is linked to my nginx config any ideas where I might be going wrong?
server {
server_name app.domain.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_pass http://localhost:3000;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/app.domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/app.domain.com/privkey.pem; # managed by Certbot
}

Two proxy servers on NGINX are not working simultaneously

I have two Nginx servers acting as reverse proxies for nodejs servers running on ports 5000 and 5001.
The one that is running on port 5000 is for normal form upload
The other one that is running on port 5001 is for uploading images
On the client side, what I've done is after filling out the form (title, description, and image) by the user, the image is uploaded to the image server first and the imageURL, title, and description are uploaded to the normal web server then.
The Problem
When the client fills out the form and clicks on upload if the image upload works then upload to the normal server fails or if normal server upload works then upload to the image server fails.
The error is the following one: (This could for either of them)
Access to XMLHttpRequest at 'https://myserver.com/imagev2api/profile-upload-single' from origin 'https://blogs.vercel.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Note: I've used app.use(cors()) on both servers (image and normal server)
Here's both nginx server configurations
Image Server
upstream imageserver.com {
server 127.0.0.1:5001;
keepalive 600;
}
server {
server_name imageserver.com;
error_log /var/www/log/imagserver.com.error;
access_log /var/www/log/imagserver.com.access;
location / {
proxy_pass http://imageserver.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
}
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/linoxcloud.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/linoxcloud.com/privkey.pem; # managed by Certbot
ssl_protocols TLSv1.2 TLSv1.3 SSLv2 SSLv3;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 10m;
ssl_session_tickets off;
}
server {
if ($host = imageserver.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name imageserver.com;
}
Normal Server
upstream normalserver.com {
server 127.0.0.1:5000;
keepalive 600;
}
server {
server_name normalserver.com;
error_log /var/www/log/normalserver.com.error;
access_log /var/www/log/normalserver.com.access;
location / {
proxy_pass http://normalserver.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen 443 ssl http2; # managed by Certbot
ssl_certificate ...; # managed by Certbot
ssl_certificate_key ...; # managed by Certbot
ssl_protocols TLSv1.2 TLSv1.3 SSLv2 SSLv3;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 10m;
ssl_session_tickets off;
}
server {
if ($host = normalserver.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name normalserver.com;
}
I've been trying to overcome this problem for some period of time by trying literally everything.
Reference: Two NGINX servers one passing CORS issue (but this doesn't provide any insights into what the problem and solution is)
Any possible fixes, please?
You have to combine these reverse proxies in one configuration file. There was already a similar thread here: https://serverfault.com/questions/242679/how-to-run-multiple-nginx-instances-on-different-port
Hope it helps.
The problem in my case is that I'm running my NODEJS instances/servers using "pm2" and they are not working simultaneously.
Similar issue: https://github.com/Unitech/pm2/issues/4352
Elaborating on what happened was if two requests are made simultaneously one pm2 process successfully executes but meanwhile the server crashes/restarts after that execution which is making the other server throw a 502 Bad Gateway error. (unreachable as though the server is not running)
For now, I'm running one server on "pm2"
and the other one uses "forever"
Note: This issue has nothing to do with Nginx (since it can handle any number of websites with different domain names on a single port 80)
This problem happened quite recently maybe it's some "pm2" bug
In simple words, when the two requests hit individual pm2 processes, one executes, and the pm2 processes kind of restart again making the second request obsolete.

Nginx proxy to node.js server SSL ERR_SSL_PROTOCOL_ERROR

EDIT:
I have verified that nodejs is running on the correct port, on http, and I have also tried with and without:
app.use('trust proxy', true);
EDIT 2:
I turned off the nodejs server and tried to serve static files just with nginx, and the error persists, so clearly this has something to do with nginx and my ssl cert.
My domain is a free domain from freenom and the ssl certificate was generated with certbot.
Original:
I have a nodejs server running, and want to use nginx and proxy to the nodejs server. (Nginx https -> nodejs http)
Running nginx -t gives no errors.
On ubuntu 20.04.2, nginx 1.18.0 node 14.5.5
I have verified that my site works fine via http (on port 3000), but i get the following error when visiting via browser on https:
ERR_SSL_PROTOCOL_ERROR
Further if i use openssl cli to try and connect, I get this
openssl s_client -connect my_domain.com:443 -servername my_domain.com
CONNECTED(00000003)
139662603941184:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../ssl/record/ssl3_record.c:331:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 310 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
/etc/nginx/conf.d/ssl.conf
server {
listen 443 ssl;
ssl_certificate /server/resources/cert.pem;
ssl_certificate_key /server/resources/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
If you use Cloudflare, It may Cloudflare not issued SSL certificate for you yet, or Cloudflare failed to connect to origin with secure connection. Check your dashboard.
Following is the working configuration of nginx.conf
I have also setup SSL with certbot + letsencrypt.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name example.com www.example.com;
root "/home/ubuntu/domain/code/directory/path/";
index index.html index.htm;
client_max_body_size 75M; # adjust to taste
location /api {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 600s;
}
location / {
try_files $uri $uri/ /index.html;
}
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1h;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
add_header Strict-Transport-Security “max-age=15768000” always;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
}
I guess the above configuration might solve your issue.
URL is https://www.example.com/api/ping redirects to http://localhost:3000/api/ping on the server.

NodeJs + Nginx .. upstream prematurely closed connection while reading response header fro m upstream

My website was running on port 80 (http) and I was using nginx without any problem. Below is default file that I was using in nginx
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Now I am planning to use https and downloaded Lets encrypt certs.Currently I am not able to access the website. I am getting following error .
*[error] 754#754: 1 upstream prematurely closed connection while reading response header fro
m upstream, client: xxx.xx.xxx.xxx, server: example.com, request: "GET /favicon.ico HTTP/2.0", upstream: "h
ttp://127.0.0.1:3000/favicon.ico", host: "www.exapmple.com", referrer: "https://www.example.com/"
Below is my default file from nginx
# HTTP — redirect all traffic to HTTPS
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
return 301 https://$host$request_uri;
}
server {
listen 443 default_server ssl;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
My nodejs code is as follows
var app = express();
var port = 3000;
var server = https.createServer(app).listen(port, function() {
console.log("Application connected on port " + port);
});
and server is running at port 3000.
Thanks in advance.. J
This issue is resolved now. Problem was with nodejs code.
I changed above code to
var app = express();
var port = 3000;
var server = app.listen(port, function() {
console.log("Application connected on port " + port);
});
https.createserver calls the http.server() internally and creates the instance.
so by removing this, the error got resolved.
Thanks for help !!
this reason is because you request url has space, "h ttp://127.0.0.1:3000/favicon.ico",and node http server doesn't support url has uncoded space,so you may delete the space or use net server instead. wish to solve you problem

Socket.io lost connection after few minutes but only with NGINX proxy enabled

I have a problem with socket.io. When I start my Nodejs App Sockets works correctly but after few minutes the connection to websocket is closed and after reconnecting Socket.io fires emit again.
I'm using NGINX Proxy and I have noticed that bypassing NGINX the problem is solved, which configuration I need to edit? I think that the problem is my nginx configuration.
This is my NGINX default config:
server {
listen 80; #listen for all the HTTP requests
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri; }
server {
server_name example.com;
listen 443 ssl http2;
#Optimize Webserver work
#client_max_body_size 16M;
keepalive_timeout 20;
ssl on;
ssl_certificate /root/social/ssl/cert.pem;
ssl_certificate_key /root/social/ssl/key.pem;
location / {
proxy_pass http://localhost:5430;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
upstream io_nodes {
server 127.0.0.1:5430;
keepalive 20;
}
Please help
You should add another parameter:
proxy_read_timeout 96000;
The default value is 60s. You will get a message "lost connect" after 60s idles with the default value.

Resources