Nginx security with SSL not blocking Postman/Http client requests - node.js

I have Nginx with ssl setup which is working well. I use it as a proxy server for my nodejs server. I only have SSL in Nginx and not Nodejs spp.
Issue: Postman and other HTTP clients can still make post requests without SSL cert. This nodejs server is for both android client and web client, must I implement SSL to nodejs server(Application level) directly too? like below:
const https = require('https');
const express = require('express');
// const httpsOptions = {cert, ca, key};
const app = express();
const httpsServer = https.createServer(httpsOptions, app);
httpsServer.listen(443, 'exampledomain.com');
Flutter apps are also able to make request to the server without SSL. Meaning this server is still insecure.
How do I prevent HTTP clients from accessing the server without SSL?

By default postman always will post requests with SSL certificate, make sure that you turned the SSL verification off in Settings.
POSTMAN SETTINGS
Maybe your code is already working, but you are misleading the test.

Related

http-server doesnt serve up any files

So im trying to make my localhost server up https to do some testing with webhooks, i was looking into http-server and i can get the https server up and running, but it wont server any content for my MERN application, it simply just downloads the file from the browser. I need to be able to server up my application from the localhost over https, but it seems that http-server only creates a web server... im sure if i was serving static content this might work, but it doesnt.
does anyone have any idea how to proceed? the goal is to ensure i can setup an https://localhost:3000 that i will expose on my router so i can take in content from a different API via a webhook and see what the data looks like.
Yes, setting up a https server can be done easily.
var privateKey = fs.readFileSync( 'privatekey.pem' );
var certificate = fs.readFileSync( 'certificate.pem' );
https.createServer({
key: privateKey,
cert: certificate
}, app).listen(port);
See the Node docs for more info: https://nodejs.org/api/https.html
Then you need to use a router to serve the application logic.

http2 in node.js, express, socket.io client

I am building a web app that uses a express and node.js in the backend. In my server.js file, I have the following code
const express = require("express");
const app = express();
const server = require("http").Server(app);
const io = require("socket.io")(server);
I recently discovered that there is http2 available, should I change the line 3 to
const server = require("http2").Server(app); instead?
If I switch to http2, is there anything else I need to specifically change that wasn't present in http1? And is the way of sending HTTP requests such as get or post any different from http1 to http2?
HTTP2 is more efficient and loads faster pages-Differences.
But I suggest you use https since its more secure and most of the browsers mark non https requests as insecure.
similar stack

Express server not redirecting HTTP to HTTPS

I am attempting to setup a server with ExpressJS which uses HTTPS and servers a React app. I want any HTTP requests to be redirected to using HTTPS.
Additional constraint: I am using React router, so the server needs to be able to handle that. e.g. if I request localhost:3000/profile, I want React Router to handle that, I just need Express to server up index.html as I had gone to localhost:3000.
Problem: I think I've been able to setup HTTPS (Chrome complains but I don't mind for now), but I cannot get redirection to work.
For comparison, this is my code for how I setup my HTTP-only server for development (before I ever tried to setup HTTPS):
const express = require('express');
const http = require('http');
const path = require('path');
const app = express();
const DIST_DIR = path.resolve('./dist');
app.use(express.static(DIST_DIR));
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const devServer = http.createServer(app);
devServer.listen(3000);
Next, I started with this guide. I created a self-signed SSL certificate then set up my application. I then looked at some examples of how to redirect, such as this question.
However, it doesn't seem to be working.
Here is my code at present:
app.use(express.static(DIST_DIR));
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect(`https://${req.headers.host}${req.url}`);
}
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const httpServer = http.createServer(app);
httpServer.listen(3080);
const privateKey = // uses FS to get my key
const certificate = // uses FS to get my cert
const credentials = { key: privateKey, cert: certificate };
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(3443);
I can access https://localhost:3443 and navigate the app as expected, and Express properly handles refreshes on pages like /profile. Great. Chrome complains that "CA root certificate is not trusted. Install this cert in the trusted root certification authorities store" but I haven't put in the work to solve that, because in a real production environment I'd be provided the certificate and key from a trusted source.
However, when I go to http://localhost:3080, I just end up at http://localhost:3080. Chrome devtools shows I'm not using HTTPS. Furthermore, I can't go directly to /profile, as Chrome gives me the error "This site can’t provide a secure connection".
I've tried other methods listed in that stackoverflow question I linked, but they either have the same behavior or straight up don't work. I'm a bit out of my element here and I'm trying to learn, but I don't understand why this isn't working. Any help would be appreciated. Thanks.
While you can manage this in your application it is often the convention to have a web server like nginix or apache in front of your application that manages the https redirection. Depending on your setup it is also common to manage your certificates at this front server to simplify certificate management. If you are going to deploy onto aws or another cloud provider I would let their infrastructure handle this for you.

Making requests to a node API from a different domain using HTTPS

I am serving a static page over HTTPS (https://example.com) that makes requests to a node API on a different domain (example-api.com).
My API is a standard express app using HTTP. Here's my setup code:
var express = require('express');
var app = exports.app = express();
var port = process.env.PORT;
exports.server = require('http').createServer(app).listen(port);
In the requests from my static page, I specify https://example-api.com as the URL. This works most of the time, but every once in a while (10% of the time?) Chrome errors out on the requests with:
net::ERROR_INSECURE_RESPONSE
Other users who've come across this issue (e.g. Failed to load resource: net::ERR_INSECURE_RESPONSE socket.io) seem to solve it by adding a credentials option to their createServer call, e.g.
var server = https.createServer(credentials, app)
So when I tried to implement this I came up with the following:
var fs = require('fs');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
var express = require('express');
var app = exports.app = express();
exports.server = require('https').createServer(options, app).listen(port);
However this solution doesn't seem to work for me. When I try it the requests never make it to my app - even logs in app.use middleware don't appear.
What's really confusing is the fact that my setup seems to work most of the time.
Does anyone know how I can reliably make my requests?
Thanks and sorry in advance for my ignorance.
I struggled with this a bit as well. If you are on windows I have a solution that is a bit of a work around, but will allow you to serve your site, and NodeJS app over HTTPS.
In Windows, I created a reverse proxy in IIS to point at the nodeJS RESTful endpoint (i.e. nodeJS RESTful services == website.com:7000). Don't let reverse proxy scare you, its gravy.
To Implement:
Install IIS (if you haven't already)
Create your Self Signed Cert (assuming you know how to do that), or apply your Cert you are using now.
Install Application Request Routing
Open your website configuration, and go to URL Rewrite
For the rewrite stuff:
For Pattern: ^api(.*)
For rewrite: http://www.website.com:7000{R:1}
This basically takes any request from: https://www.website.com/api/someApiAwesomeness, and rewrites it to your nodejs App running at http://www.website.com:7000. Now you have an SSL RESTful app..
Good luck man I hope this helps!

Proxy HTTPS with HTTP in Node.js express

I wrote an express app as an HTTP proxy, to intercept and analyse some of the network traffic. The parts of traffic my app is interested in are all HTTP, however I still want my app to proxy HTTPS so users can use it without extra setting.
My express app is created with a HTTP server. When testing, I changed the proxy setting in Chrome with SwitchyOmega, to proxy HTTPS connections with HTTP. HTTP works well, But my express app couldn't get these proxy requests for HTTPS.
So I wrote a simple TCP proxy to check on them, and find that they're like this:
CONNECT HOSTNAME:443 HTTP/1.1
Host: HOSTNAME
Proxy-Connection: keep-alive
User-Agent: MY_AGENT
ENCRYPTED HTTPS
I believe these requests are HTTP, but why express isn't receiving them?
For sure if I change the browser proxy setting to ignore HTTPS, the app works well. But I do want to know if there is any workaround that I can use to proxy all protocols with HTTP and only one port.
THX.
UPDATE- code from my express app
app.use('*', function (req, res, next) {
// print all the request the app receive
console.log('received:', req.url)
})
app.use(bodyParser.text({type: '*/*'}))
app.use(cookieParser())
app.use(logger('dev'))
app.use(express.static(path.join(__dirname, 'public')))
// serve web pages for my app, only the request targeting my server
// is handled here(right IP and port), proxy request gets handled after this.
app.use('/', internalRoute)
// analyse the part I want
app.use('/END_POINT_I_WANT', myRoute)
// handle proxy requests
app.use('*', function (req, res, next) {
// proxy the request here
})
The problem is, my first middleware, which is used to display all the requests the app receive, can't catch the HTTPS proxy requests wrapped in HTTP described above. And of course the middleware I used as proxy can't catch them either.
UPDATE-tried node-http-prxoy, no luck
var httpProxy = require('http-proxy')
, http = require('http')
, fs = require('fs')
var options = {target: 'http://127.0.0.1:8099'}
, proxy = httpProxy.createServer(options)
http.createServer(function (req, res) {
console.log(req.url)
proxy.web(req, res)
}).listen(5050)
With the above code, and browser setting to proxy all protocols with HTTP, it works the same as my express app. HTTPS proxy requests gets ERR_EMPTY_RESPONSE, and nothing on the console.
With the below options, it seems that I have to change the proxy protocol to HTTPS, which I'd rather not use, at least for now. And I get ERR_PROXY_CERTIFICATE_INVALID for my self-signed certs...
var options = { secure: true
, target: 'http://127.0.0.1:8099'
, ssl: { key: fs.readFileSync('cert/key.pem', 'utf8')
, cert: fs.readFileSync('cert/server.crt', 'utf8')
}
}
UPDATE- pin point the problem to the 'connect' event listener
Through some searching, I found this post helpful.
It pointed out that the http server doesn't have a listener for the connect event. I tried the code in the post, works. But as the last comment of that post mentioned, my app serves as a proxy in order to get the data, it then proxy the request to another proxy in order to go over the GreatFireWall.
The process is like : BROWSER -> MY_APP -> ANOTHER_PROXY -> TARGET.
Without the ANOTHER_PROXY, which is an HTTP proxy, it works well for both HTTP and HTTPS. However I failed to chain them all up. The ANOTHER_PROXY I use supports HTTPS over HTTP.
It's hard to see what might be wrong, since you haven't posted any code.
However, if you just want to create a simple proxy that supports HTTP and HTTPS, i think that you should consider using a module like node-http-proxy.
Their readme has example code for the most common scenarios, and it sounds like it will support your needs fine.

Resources