How to properly create an HTTPS transparent proxy server with node? - node.js

I am using the npm package http-proxy that claims to help with that, however I am totally incapable to make it work. So far I have only success by making an transparent HTTP proxy server, however when it goes to create a transparent HTTPS proxy server then nothing happens.
I am using an Android device configured to use a proxy with the port where the proxy is expecting to be configured, but nothing is triggered in the nodejs side. Only if I have configured an HTTP proxy server then things seems to be working.
This is the code I have for the HTTPS:
var https = require('https');
var fs = require('fs');
var httpProxy = require('http-proxy');
var options = {
key: fs.readFileSync('./client-key.pem', 'utf8'),
cert: fs.readFileSync('./client-cert.pem', 'utf8')
};
var proxy = httpProxy.createProxyServer({
ssl: options
});
https.createServer(options, function (req, res) {
console.log("new", req.url);
proxy.web(req, res, {
target: req.url
});
}).listen(8000);
If I use the createServer from the http package then it works for http calls (as in that the callback is being fired), however it does not for https with these instruction. Anybody knows what am I doing wrong?
PS: I do not care if I have to use a different npm package.

you can use https://www.npmjs.com/package/transparent-proxy
It is built extending native net.createServer. It acts like a REAL transparent http proxy and It allows you, for example, to easy upstream requests to other proxies and make some requests-chaining through multiple proxies... etc...
Install
npm i transparent-proxy
Use
const ProxyServer = require('transparent-proxy');
//init ProxyServer
const server = new ProxyServer();
//starting server on port 8080
server.listen(8080, '0.0.0.0', function () {
console.log('TCP-Proxy-Server started!', server.address());
});
It works on Termux too :)

Related

Solving a Proxy Error (Node.js server)

Basically I get a 502 Proxy Error when running my node.js app.
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET /play.
Reason: Error reading from remote server
My server looks like this.
var express = require('express');
var https = require('https');
var http = require('http');
var path = require('path');
var fs = require('fs');
var mysql = require('mysql');
var app = express();
var options = {
key: fs.readFileSync('sslcert/keyfile.key', 'utf8'),
cert: fs.readFileSync('sslcert/crtfile.crt', 'utf8')
};
var httpsServer = https.createServer(options, app);
// stuff
httpsServer.listen(process.env.PORT);
I am really sorry if this is a noob question, actually I am still a beginner in things related to node.js. Thank you for your help!
Noël.
I just ran into the same problem. It's possible your problem was different, but in my case, the 502 error was coming from Apache. My httpd.conf file was referencing the same 2 certificate files that my node app was referencing.
Instead of using
var httpsServer = https.createServer(options, app);
try just
app.listen(3000);
I'm not sure exactly why it wasn't working. My theory is the node app was using these cert files, and apache was unable to access them, and thus creating this situation. However, just using a normal express app fixed the problem for me.
I hope this helps somebody!

How to enable SSL connection a NodeJS (Express) based Server

Following is the script I found on NodeJS Official Website:
// curl -k https://localhost:8000/
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
I'm completely new to SSL thing. I read some tutorials on how to enable SSL on Nodejs but still quite not confident with the process.
I have a domain name (Godaddy), SSL (Namecheap) and Cloud Server (Digital Ocean with an application deployed on HTTP prefix).
Whenever I open my Login page of my website, Google Chrome mark it as "Not secure" so I wanted to add SSL to the website.
What things I need to do on the NodeJS server (Express) and what things I need to do on Namecheap? What will be the sequence of doing that? What are cmd lines to generate .pem .csr files?
I'm didn't found and comprehensive guide laying down all the steps in a concise manner so just laid down the steps concisely (if possible) with the links to the resources for further digging.
And also, how can I use express framework to create https server in liue of above script?
That script is correct for setting the certs for your https. If your site is public, as it seems, then you'll want to buy certs from your ssl service, Namecheap in your example. Then you would move them to your host and reference them in the options object in your example. However, you can generate your own ssl certs and that will work as well. Though, any users will be warned that they're not trusted since you self signed/created them. I suggest going with the Namecheap option.
Note: You only have an https server in your example and anyone attempting to access your site via http will receive a blank page. You'll need to also create an http server, via the following:
var http = require('http');
http.createServer(...);
I would suggest having the http server simply redirect to the https url.
My code and error is here:
no such directory found error:
key: fs.readFileSync('../private.key'),
cert: fs.readFileSync('../public.cert')
error, no such directory found
key: fs.readFileSync('./private.key'),
cert: fs.readFileSync('./public.cert')
Working code should be
key: fs.readFileSync(__dirname + '/private.key', 'utf8'),
cert: fs.readFileSync(__dirname + '/public.cert', 'utf8')
Complete https code is:
const https = require('https');
const fs = require('fs');
// readFileSync function must use __dirname get current directory
// require use ./ refer to current directory.
const options = {
key: fs.readFileSync(__dirname + '/private.key', 'utf8'),
cert: fs.readFileSync(__dirname + '/public.cert', 'utf8')
};
// Create HTTPs server.
var server = https.createServer(options, app);
This is my working code for express 4.0.
express 4.0 is very different from 3.0 and others.
4.0 you have /bin/www file, which you are going to add https here.
"npm start" is standard way you start express 4.0 server.
readFileSync() function should use __dirname get current directory
while require() use ./ refer to current directory.
First you put private.key and public.cert file under /bin folder,
It is same folder as WWW file.

Encrypting content sent with Node.js

I am trying to get HTTPS up on my node.js application. I made progress on this by creating certAccess group that contains both root and ec2-user, and then saying sudo chown ec2-user.certAccess /etc/pki/tls/private/serverKey.key. However, when I run this dummy code:
var fs = require('fs');
var https = require('https');
var app = require('express')();
var options = {
key : fs.readFileSync('/etc/pki/tls/private/serverKey.key').toString(),
cert : fs.readFileSync('/etc/pki/tls/certs/2_mikewarren.me.crt').toString()
};
app.get('/', function (req, res) {
res.send('Hello World!');
});
https.createServer(options, app).listen(8080, function () {
console.log(JSON.stringify(options, null, '\t'));
console.log('Started!');
});
and test it out in my browser (use <yourDomain>:8080), I get no response from server.
I go in and see the permissions of my private key and certificate, and see this:
The private key and certificate configuration, located in /etc/httpd/conf.d/ssl.conf looks like:
However, when I do the test in my browser (even typing https:// in front of the URL, which I shouldn't have to), I get no response from server.
What should I do?!?!?
I came up with solution. Here's what I did:
I added ca member to options and pointed to that chain cert as it, like this: ca : fs.readFileSync('/etc/pki/tls/certs/1_root_bundle.crt', 'utf8'). That solves the cert problem. As for the next part, I simply wrote line in BASH that redirects https (port 443) to the port I was using (which I, out of convenience, changed to 8443, because I already redirected http to 8080).
That got it working, but it still sucks that I have to still prefix URL with https://. I shouldn't have to! I think solution to that is to do what I already have done, but redirect http to port 8443, or proxy port 8080 to port 8443.

Node.js socket.io with ssl connection

I am trying to connect node.js server with socket.io using ssl. My server has windows 2008 server and iis installed. I intalled ssl my domain name on IIS and I can connect with my domain via http s://mydomain.com. But I cant connect my node.js server with ssl. I am using following code on my server,Have you got any ideas what the problem might be?
var fs = require('fs');
var options = {
pfx: fs.readFileSync('sslkey.pfx'),
passphrase:'password'
};
var express = require('express'),
app = express(),
server = require('https').createServer(options,app),
server2 = require('http').createServer(app),
io = require('socket.io').listen(server, {log: true});
function sendCrossDomain(req, res){
//return;
res.set('Content-Type', 'text/xml; charset=utf-8');
res.sendfile(__dirname + '/crossdomain-test.xml');
};
app.get('/crossdomain.xml', sendCrossDomain);
app.get('/', sendCrossDomain);
server.listen(9595);
Assuming there are no errors about your certificate when you run the node program,
I would check to make sure the firewall port is opened on TCP 9595.
You will also have to request the page with https://yourdomain.com:9595 in order to access the running program since it's SSL and on a different port than 443.

How to run express and geddy apps on the same port?

There is an existing node.js application implemented using geddy framework, it is started by Heroku's foreman like so:
web: geddy
I am working on making it into a Heroku add-on. Heroku has a way to auto-generate the skeleton code necessary for an add-on, but it is implemented using express. It is started by this command:
web: node web.js
Internally, Heroku only allocates 1 port per app (that gets external traffic routed to it). Is there a way to start both existing geddy app and add-on express app on the same port? Or have some type of an application level router that would forward to geddy or express based on incoming request path?
Assuming you are on Heroku and are limited to only Node.js apps, I would suggest you to start a new node instant as a reverse proxy. A quick and dirty example would be the following:
proxy.js
var http = require('http'),
httpProxy = require('http-proxy');
var options = {
pathnameOnly: true,
router: {
'/foo': '127.0.0.1:8001',
'/bar': '127.0.0.1:8002'
}
};
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(8000);
first.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('I am the first server!\n');
}).listen(8001);
second.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('I am the second server!\n');
}).listen(8002);
start all three scripts using node, and the test result is as follows:
cloud#wishlist:~$ curl localhost:8000/foo
I am the first server!
cloud#wishlist:~$ curl localhost:8000/bar
I am the second server!
which is exactly what you need: something that makes it look like two apps are listening on the same port. For more detail, look into the node http-proxy module

Resources