I want to force https request to http in express js - node.js

I do not have ssl so I want my website should only be serve on http. but now when we hit https it says the site can not be accessed.
is there any way we can redirect https request to http ??
const express = require('express')
const Router = express.Router()
const app = express()
const path = require('path')
app.use(Router);
app.use(express.static(path.join(__dirname , '../reactjs-admin-panel/build' )))
app.get('*', (req, res)=>{
res.sendFile(path.join(__dirname, '../reactjs-admin-panel/build'));
})
app.listen(80);

The only way to redirect from https to http is to have both an https server and an http server. You would have an https server that would accept the https request and then redirect to http (which may also generate a browser warning). So, you would need a full-on https server with certificate, etc... to do that. And, once you had a full-on https server, you may as well just let the user use it rather than redirect to the less secure http.
So, if you don't have https server up, then you can't respond to https requests in any way, not even just to redirect to http. So, basically, there isn't a way to do what you're asking without already having an https server configured and working.

Related

Node.js Express Websocket clients coming from http origin?

I have a webapp that communicates to Node.js Express server using websocket.
When verifying the websocket connection, I check the ORIGIN header of the request (and a few other parameters to ensure they are legitimate)
The expected request is either "https://www.mywebsite.com" or "https://mywebsite.com"
If the ORIGIN header is not expected, we will kick the user.
Then I noticed some people can be kicked when their socket connection looks alright, but the ORIGIN is "http://mywebsite.com". We quickly checked and realise the website can be visited in http. We added a piece of redirect code like this:
const server = express()
.enable('trust proxy')
.use((req, res, next) => {
req.secure ? next() : res.redirect('https://' + req.headers.host + req.url)
})
And now theoretically, whoever visit the http version of the website should be redirected to https.
But, even this redirection is done, we still notice people being kicked because their origin is http instead of https. Why is this so? Is there any chance that some users can never use https?
This is the correct way to redirect to https on Heroku:
Under the hood, Heroku router (over)writes the X-Forwarded-Proto and the X-Forwarded-Port request headers. The app must check X-Forwarded-Proto and respond with a redirect response when it is not https but http.
Taken from: https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls
This is some sample code you can use:
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
res.redirect(`https://${req.header('host')}${req.url}`)
} else {
next()
}
})
The reason your code doesn't work is that Heroku does SSL termination for you and serves the certificates this means the connection between the Heroku router and your Node.js server is insecure and req.secure returns false:
https://devcenter.heroku.com/articles/http-routing#routing
Correction: Cause you set trust proxy this means req.protocol will be set to https and req.secure will return true so your code will work.

Nginx security with SSL not blocking Postman/Http client requests

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.

what is the difference between using Express GET method and HTTPS GET method in the below code?

const express = require("express");
const app = express();
const https = require("https");
app.get("/", function (req, res){
var url = "https://***";
https.get(url, function(response){
console.log(response);
});
res.send("server running");
});
Express is really just a layer on top of http.
I reckon those following links might help you out, this question has been asked.
what's the technical difference between express and http, and connect for that matter
Difference between a server with http.createServer and a server using express in node js
app.get() registers a listener for a specific INCOMING http request path on a local Express server.
https.get() makes an OUTBOUND https request TO some other https server to fetch content from that other server.
And, obviously, the https.get() is using https, not http. The app.get() could be listening for either - it depends upon how the server it is part of is started (as an http server or an https server) which the code you have in your question does not show.

two node.js servers at one web address

I have two web application node.js servers and I need to have them under one web address.
It should work like this:
example.com/wa/* -> redirect to example.com:pppp
others example.com/* -> redirect to example.com:qqqq
I have experimented with http proxy module, but it doesn't work, maybe the problematic part is the fact, both servers are https not http.
Using Express you can do something like this
var express = require('express');
var http = require('http');
var app = express();
app.use('/wa/*', function(req, res){
req.redirect('example.com:pppp')
});
app.use('/*', function(req, res){
req.redirect('example.com:qqqq')
});
http.createServer(app);
Not tested, but it should work.
Note: The /wa/* route must come before the /* route. otherwise all requests will get redirected by the first middleware

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