Under the Merkle Trees

Insights on the Relentless Pursuit of Patterns in the World Around Me

Setting up a reverse https proxy with Node.Js

For reasons that aren't very important to this post, I wanted to set up a node.js https proxy in front of node/express application I'd built. The idea here is that all requests to the site would be routed over HTTPS.

I started with an Nginx proxy first but ran into some issues getting the headers forwarded correctly (at all). For that reason I decided it might be nice to keep it all Node and see if I could get it working with a Nodejitsu proxy. For this senario i'm not using a self signed cert.

If you're starting from scratch and need Node Deb package like me:
https://github.com/joyent/node/wiki/installing-node.js-via-package-manager

Working from here:
https://github.com/nodejitsu/node-http-proxy

For referece, on this go around:

root@mothra:/proxy# uname -a
Linux mothra 3.2.0-4-amd64 #1 SMP Debian 3.2.63-2+deb7u1 x86_64 GNU/Linux

mkdir proxy cd proxy

sudo npm install -g http-proxy

sudo npm install -g colors

nano proxy.js

I took this example and changed it a bit. I'll go section by section first, then all at once. If your going to copy/paste use the code at the end as i'm going to make some changes later on too.

var https = require('https'), http = require('http'), util = require('util'), path = require('path'), fs = require('fs'), colors = require('colors'), //httpProxy = require('../../lib/http-proxy'), httpProxy = require('http-proxy') //fixturesDir = path.join(__dirname, '..', '..', 'test', 'fixtures');

I got rid of the fixtureDir and the relative path to http-proxy.

I already had my node/express app running on port 4200 so I didn't need that. Next up, the actual https proxy server:

// // Create the HTTPS proxy server listening on port 8009 // httpProxy.createServer({
target: { host: 'localhost', port: 4200 }, ssl: { //key: fs.readFileSync(path.join(fixturesDir, 'agent2-key.pem'), 'utf8'), //cert: fs.readFileSync(path.join(fixturesDir, 'agent2-cert.pem'), 'utf8') key: fs.readFileSync('/etc/ssl/geode.io.key', 'utf8'), cert: fs.readFileSync('/etc/ssl/z.pem', 'utf8') } }).listen(8009);

and the fancyness:

util.puts('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8009'.yellow);

Probably the most challenging part of setting this up is the cert and key. As I mentioned, I had intially started with an nginx HTTPS proxy and followed the directions on how to get my certs and keys set up for that. I was able to simply reference those same keys. This guide should do the trick if you need to get your key/cert files set up.

My base app (on 4200) is also using websockets so this configuation failed with an error:

/usr/lib/node_modules/http-proxy/lib/http-proxy/index.js:119 throw err; ^ Error: socket hang up
at createHangUpError (http.js:1477:15) at Socket.socketCloseListener (http.js:1527:23) at Socket.emit (events.js:95:17) at TCP.close (net.js:466:12)

Added this to proxy.js to fix:

ws: true

Now, if a user requests https://yoursite.com:8009 all will be well. At this point I realized I wanted to force SSL though so I decided to look into some other options.

Comments

comments powered by Disqus

About the author

Zachary Wolff

http://zacharywolff.com