HTTPS on same port as HTTP? - node.js

I'm writing an HTTP/HTTPS proxy server in Node.JS, I want the server to handle HTTPS traffic on the same port as HTTP.
The below image explains why I want to do this, the user can just check the box...
I realize that I can't have 2 servers listening on the same port, but is there a way to setup a main server that forwards the traffic to either HTTP or HTTPS traffic?
Something like this:
http.createServer(myHTTPCallback).listen(3129, '127.0.0.1');
https.createServer(myHTTPSCallback).listen(3130, '127.0.0.1');
//Then a main server that will listen for both kinds of traffic
main.createServer(function(req, res){
if(/*Traffic is HTTPS*/){
//Forward to 127.0.0.1:3130
}
else{
//Forward to 127.0.0.1:3129
}
}).listen(3128, '192.168.0.2');
How would I code the above?
EDIT - As per #Chris Jester-Young answer
I created this simple server, but I only receive output for HTTP requests. Also breakpoints or console logs don't trace:
var http = require('http');
http.createServer(function(req, res){
res.write('<h1>Resquest Received</h1>');
res.write('<span>Requested URL = ' + req.url + '</span>');
res.end();
}).listen(3128);

You don't have to listen to both HTTP and HTTPS on the same port, in your specific case of writing a proxy server. Browsers connect to proxy servers via HTTP, whether for proxying HTTP or HTTPS requests. HTTPS requests use the CONNECT HTTP method to open a direct connection to the HTTPS server---that CONNECT request is still done in the unencrypted portion of the proxy traffic.
Edit: Here's what I think your code should look like:
http.createServer(function (request, response) {
// Handle normal requests here
}).on('connect', function (request, socket, head) {
// Handle CONNECT requests here
}).listen(3128);

Related

Creating A HTTP proxy server with https support and use another proxy server to serve the response using nodejs

I need help creating a proxy server using node js to use with firefox.
the end goal is to create a proxy server that will tunnel the traffic through another proxy server (HTTP/SOCKS) and return the response back to firefox. like this
I wanna keep the original response received from the proxy server and also wanna support https websites as well.
Here is the code I came up with.
var http = require('http');
var request = require("request");
http.createServer(function(req, res){
const resu = request(req.url, {
// I wanna Fetch the proxy From database and use it here
proxy: "<Proxy URL>"
})
req.pipe(resu);
resu.pipe(res);
}).listen(8080);
But it has 2 problems.
It does not support https requests.
It also does not supports SOCKS 4/5 proxies.
EDIT: I tried to create a proxy server using this module. https://github.com/http-party/node-http-proxy
but the problem is we cannot specify any external proxy server to send connections through.
I have found a really super simple solution to the problem. We can just forward all packets as it is to the proxy server. and still can handle the server logic with ease.
var net = require('net');
const server = net.createServer()
server.on('connection', function(socket){
var laddr = socket.remoteAddress;
console.log(laddr)
var to = net.createConnection({
host: "<Proxy IP>",
port: <Proxy Port>
});
socket.pipe(to);
to.pipe(socket);
});
server.listen(3000, "0.0.0.0");
You have to use some middleware like http-proxy module.
Documentation here: https://www.npmjs.com/package/http-proxy
Install it using npm install node-http-proxy
This might help too: How to create a simple http proxy in node.js?

Why is my NodeJS server deployed to Elastic Beanstalk receiving HTTPS traffic on port 80?

I've written a very simply NodeJS server
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(80);
console.log('Server running at http://127.0.0.1:8081/');
I then deployed it to Elastic Beanstalk with the "Classic Load Balancer" option selected.
Oddly, the server responds to traffic sent with https.
I expected that it would not know how to handle this traffic since the server is only listening on port 80, which is for http (no s).
Does anyone have an explanation or at least idea of why my NodeJS is handling non-HTTPS requests?
When https request made, it is terminated at the Load Balancer. The Load Balancer then will make an http request to the listener aka the NodeJS apps. This is the default configuration of Load Balancer in ElasticBeanstalk.
So your NodeJS apps is handling an http request from the Load Balancer instead of the https directly from the client.

How can I bind http and https in one node server

I have a chatting application using node.js server, Few days back we moved from http to https server, Where https server is working fine on web but not on native app, so for this we have created new http server with different port number.
Now I have two node socket.io server, one is http who is working on port 3000(for mobile client) and another one is https who is working on 3001 port(for web client), both the server has a same code, but now I am not able to make communication between native and web user.
So is it possible for node server to listen HTTP and HTTPS request simultaneously on a same port.
or
Is there any way through which I can send HTTp server request to HTTPS server ?
Below is the code for HTTP server
var app = require('http').createServer(handler),
io =require('socket.io').listen(app);
var querystring = require('querystring');
var http=require('http');
var fs = require('fs');
var webservice_host="xxxxxxxxxxxx.com";
var port = process.argv[2] || 3000;
var authKey="";
I'm not sure if you can get the http and https servers to listen simultaneously on the same port and accept only its protocol.
Is there any way through which I can send HTTp server request to HTTPS server ?
Yes, check out this question that explains how to create an HTTP -> HTTPS proxy. How to use node-http-proxy for HTTP to HTTPS routing?

HTTP server port number

If I create and HTTP server using nodejs like this:
var http = require("http");
http.createServer(function (request, response) {
// Send the HTTP header
// HTTP Status: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// Send the response body as "Hello World"
response.end('Hello World\n');
}).listen(8081);
// Console will print the message
console.log('Server running at http://127.0.0.1:8081/');
does it mean that if I use a web hosting service, the URL of the website will always need to contain somehow 8081 port? How would the URL look like?
Yes you would always need to the port number with requests, however if you use relative links this will not be such a problem.
Good idea
Questionable idea
You may also look into reverse proxies and virtual hosts depending on your application.
If you expose a server using port 80 means http and / or via 443 means https. Your urls don't need port. Other than that if you are using a different port then you can use ngnix or haproxy to expose them in 80 or 443. Without following this you will end up giving port to the urls

NodeJS listening on HTTP and HTTPS for one single domain name

I use express and a server cloud on AWS (Amazon Web Server) and a DNS "mydomain.com".
Question: how can I avoid my users to have to writing in the Browser-URL: http://mydomain.com:4000 and https://mydomain.com:3000
This is my code:
sudo node app.js
var app = express();
var server = http.createServer(app).listen(4000, function() {
console.log('Express HTTP server listening on port ' + app.get('port'));
});
var server = https.createServer(credentials, app).listen(3000, function() {
console.log('Express HTTPS server listening on port 3000');
});
// redirect all http requests to https
app.use(function(req, res, next) {
if(!req.secure) {
return res.redirect(['https://mydomain.com', req.url].join(''));
}
next();
});
I want my user to be able to write my domain name using http and https with no port numbers. I already have a SSL certificate and everything is working fine, but I haven't been able remove the port-numbers and use both: https and http.
Any idea? please :)
I use MEAN stack (Mongo, Express, Angular, )
The only way to do that is to use the default ports for the protocols. That is, Port 80 for HTTP and Port 443 for HTTPS.
If you don't use the default protocol ports then the only way for the browser (or whatever client the users are using) to determine which port to connect to is for the user to specify it in the URL.
Edit - To address your comment above about different server objects
In the code in your question you create an HTTP server and then use the variable server to hold a reference to the object. You then create an HTTPS server and assign it to the same variable. If you use the server variable later in your code then you'll be dealing with the HTTPS server object, but will have no way to reference the HTTP server object.
To fix this, just use two different variables to hold the object references.
var httpServer = http.createServer ....
var httpsServer = https.createServer ....

Resources