Nginx proxy_pass with Node and SSL - node.js

I have managed to setup HTTPS using Nginx on a Node server at localhost:4000 by placing the cert and key paths in the Nginx conf file, however, I would also like to understand how to embed the ssl certificate inside the node index.js file and just pass the proxy'd address to the localhost:4000 with the certs inside the application rather than the nginx.conf file.
This nginx.conf file will work correctly with https/ssl once node isn't being served as ssl.
server {
listen 4500 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
access_log /var/log/nginx/example.com.access.log;
location / {
proxy_pass http://localhost:4000;
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;
}
}
However, if I comment out the following nginx.conf
# ssl_certificate /etc/letsencrypt/live/api.ballers.ie/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/api.ballers.ie/privkey.pem;
And then add the certs to my node server as follows, it tells me that the site can't be reached.
// ...
// dependencies & config
// ...
const privateKey = fs.readFileSync('/etc/letsencrypt/live/example.com.privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/letsencrypt/live/example.com.cert.pem', 'utf8');
const ca = fs.readFileSync('/etc/letsencrypt/live/example.com.chain.pem', 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca,
};
const httpsServer = https.createServer(credentials, app);
app.get('*', (req, res) => {
res.send('I am a HTTPS endpoint !');
});
httpsServer.listen(4000);
I have also tried changing proxy_pass to proxy_pass https://localhost:4000;
I'd be very interested to understand how to make this work, thanks for your assistance.

Related

Issue with Websockets/Peerjs on production (Nginx)

I'm facing an issue with peerjs on nginx. The same code works fine on localhost, but doesn't work when I host it on a production sereverv via Nginx. Following the code below, two peers can connect to and regcognize eachother, but can't communicate when I try to send an image over.
I have added some comments in the frontend code, where I suspect the error. Can anyone help me please? Thanks :)
Here is the backend code:
const fs = require('fs');
const express = require('express');
const { ExpressPeerServer } = require('peer');
const app = express();
app.get('/', (req, res, next) => res.send('Hello world!'));
const sslOptions = {
key: fs.readFileSync('/etc/letsencrypt/live/<server_URL>/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/<server_URL>/fullchain.pem')
}
const server = app.listen(5000);
const peerServer = ExpressPeerServer(server, {
path: '/myApp',
debug: true,
proxied: true,
ssl: sslOptions
});
app.use('/peerjs', peerServer);
Frontend:
const peerConfig = {
secure: true,
host: '<server_URL>',
path: '/peerjs/myApp',
debug: 3
}
const peer = new Peer('any_ID_1', peerConfig);
console.log(peer) // this works fine and the object has "_open:true"
const conn = peer.connect('any_ID_2');
console.log(conn) // however, the object here returns "_open:false"
Nginx conf:
server{
server_name <server_URL>;
root /var/www/backend;
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/<server_URL>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/<server_URL>/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
}

Mixed Content Error : This request has been blocked; the content must be served over HTTPS in MERN project on AWS

My project is deployed on AWS ec2 instance. After adding SSL to my domain I am start getting this error:
Mixed Content: The page at 'https://example.com/' was loaded over
HTTPS, but requested an insecure resource
'http://14.1.41.10/api/product/productsforcarousel'. This request has
been blocked; the content must be served over HTTPS.
This is a MERN project and problem is arrive after putting SSL. Here is my code:
const fs = require("fs");
const path = require("path");
const express = require("express");
const mongoose = require("mongoose");
const app = express();
mongoose
.connect(`mongodb+srv://${process.env.DB_URL}`, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
.then(() => {
app.listen(5000);
})
.catch((err) => {
console.log(err);
});
And here is nginx code
server {
listen 80 default_server;
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;
root /var/www/Example_Pro/public;
index index.php index.js index.html;
server_name example.com www.example.com;
ssl_certificate "/etc/nginx/ssl/ssl.crt";
ssl_certificate_key "/etc/nginx/ssl/private.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256";
location / {
proxy_pass http://127.0.0.1:8043;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_read_timeout 90;
proxy_buffering off;
proxy_redirect http://127.0.0.1:8043 https://example.com;
}
}

socket.io return Transport unknown error through nginx

I'm trying to connect to my Nodejs server by Nginx.
my server runs on port 3000 and my Nodejs client successfully connects to the server using https://example.com:3000, while https://example.com/socket.io returns:
{"code":0,"message":"Transport unknown"}
I used certbot for SSL certification and it configured my nginx.conf
this is Nginx .conf file for my socket.io server:
upstream nodesocket {
server 127.0.0.1:3000;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
access_log /var/log/nginx/access-ssl.log;
error_log /var/log/nginx/error-ssl.log;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 60;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
large_client_header_buffers 8 32k;
location /socket.io/ {
proxy_pass https://nodesocket;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
and this is my socket io server:
const express = require('express')
const https = require('https')
const socketIo = require('socket.io')
var fs = require('fs')
var options = {
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
ca: fs.readFileSync('/etc/letsencrypt/live/example.com/chain.pem')
}
var app = express();
var server = https.createServer(options, app);
var io = socketIo(server);
server.listen(3000, function(){
console.log('listening on :3000');
});
I checked nodejs and nginx logs but there were no related logs and no error.
I had the exact same issue and this worked for me
I deleted proxy_http_version 1.1;
and here is my nginx.conf
location /socket.io/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:3000/socket.io/;
}

Nginx Proxy Pass on SSL is not Considering Listening URL

I am currently trying to set up nginx virtual server blocks, which I have me absolutely ripping my hair out.
Essentially, I have a NodeJS instance running on a droplet at DigitalOcean. The point of this application, is to host both a website as well as an api. I want both of these to run on the same droplet.
I have set up my NodeJS app with express to create the routing and so on, and then create an http server with the express app. As my explanation might cause confusion, I have included the essentials of the code below:
const API_PORT = 8080;
const WEB_PORT = 8081;
const api = express();
const web = express();
web.use(express.static(path.join(__dirname, '../build')));
web.get('//', (req, res) => {
res.sendFile(path.join(__dirname, '../build', 'index.html'));
})
api.use((req, res, next) => {
const ip = (req. headers['x-forwarded-for'] || '').split(',').pop()
|| req.connection.remoteAddress
|| req.socket.remoteAddress
|| req.connection.socket.remoteAddress
if (req.headers.auth !== AUTHCODE) {
httpError(400, 'Validation failed');
console.warn('Bad Auth Code');
console.warn(req.headers.auth);
console.warn(ip);
return (res.json('Validation failed'));
}
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader('Access-Control-Allow-Headers', '*');
next();
});
Graph.route(api);
const apiServer = http.createServer(api);
const webServer = http.createServer(web);
apiServer.listen(WEB_PORT, '127.0.0.1', () => {
console.log(`API Server is running on port ${API_PORT}`);
});
webServer.listen(API_PORT, '127.0.0.1', () => {
console.log(`WEB Server is running on port ${WEB_PORT}`);
});
What I want to achieve is shown in the code above, but essentially I am trying to have a my api server listening to port 8080, and my website server to listen on port 8081.
I was told that I could use nginx to create a proxy_pass for this although I have not managed to make it work as intended. Below you see two examples of what I tried to do !
Anyone able to help me out would forever be my hero !
server {
listen lace.guide:443 ssl;
server_name lace.guide www.lace.guide;
ssl_certificate /var/my-server/ssl/myapp.crt;
ssl_certificate_key /var/my-server/ssl/myapp.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_pass http://127.0.0.1:8080/$request_uri;
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;
}
}
server {
listen api.lace.guide:443 ssl default_server;
server_name api.lace.guide www.api.lace.guide;
ssl_certificate /var/my-server/ssl/myapp.crt;
ssl_certificate_key /var/my-server/ssl/myapp.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_pass http://127.0.0.1:8081/$request_uri;
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;
}
}
I am also having another quite peculiar error which means that if I access my api.lace.url/something/somethingElse it actually hits //something/somethingElse on my server (console.log from req.url)
Here is an example of how server and client live on one server and are being managed with nginx (ssl setup omitted for simplicity). All request prefixed with /api get routed to the server and the rest - to the client.
upstream client {
server client:3000;
}
upstream api {
server api:5000;
}
server {
listen 80;
location / {
proxy_pass http://client;
}
location /api {
proxy_set_header X-Forwarded-For $remote_addr;
rewrite /api/(.*) /$1 break;
proxy_pass http://api;
}
}

NGINX config with Node.js Express and TCP server on same port?

I am trying to set up my node server that uses express to serve files on port 3000 and the net library to serve a TCP server on port 5052, so:
const express = require('express');
const app = express();
const httpServer = require('http').Server(app);
const io = require('socket.io').listen(httpServer);
const path = require('path');
const net = require('net');
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, './public/index.html'))
});
let server = net.createServer(function(socket) {
// Left out for brevity
}
server.listen(5052, 'localhost');
httpServer.listen(3000, () => {
console.log('Ready on port 3000');
});
Locally, this all works very well. I can load up localhost:3000 and I get my HTML served and it connects to socket.io fine. I can also connect to the server on port 5052 perfectly and life is good. I just can't get nginx to serve it all correctly. Here's what I have:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mycoolproject.com www.mycoolproject.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;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/mycoolproject.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mycoolproject.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 5053;
server_name mycoolproject.com www.mycoolproject.com;
location /{
proxy_pass http://localhost:5052;
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;
}
}
When I navigate to mycoolproject.com I get the site loaded fine, so the express side is working fine. I just can't connect to my server on 5053. Any ideas?
You need to configure a different port for Nginx, 5052 is busy by Node.js.
server {
listen 5053;
server_name mycoolproject.com www.mycoolproject.com;
location /{
proxy_pass http://localhost:5052;
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;
}
}
Then you can connect to mycoolproject.com:5053

Resources