pghalliday / tls-tunnel

MIT License
29 stars 11 forks source link

tls-tunnel

A Node.js client/server implementation of a secure tunnel over TLS/SSL. Useful for exposing local servers on public hosts. Initially implemented to expose a local server to browsers provided by BrowserStack to integrate their beta API with test scripts.

The idea is simple.

Features

Installation

npm install tls-tunnel

API

To instantiate and start a server

var fs = require('fs');
var Server = require('tls-tunnel').Server;

var server = new Server({
  port: 8080,   // port to listen for client connections
  key: fs.readFileSync('./keys/server-key.pem'),    // server's private key
  cert: fs.readFileSync('./keys/server-cert.pem'),  // server's SSL certificate
  ca: [fs.readFileSync('./keys/client-cert.pem')],  // list of authorized client SSL certificates
  forwardedPorts: {
    start: 8081,    // Start of port range to assign to connecting clients
    count: 10       // maximum number of ports and hence clients that can be supported
  }
});

server.start(function() {
  // server should be listening on port 8080 now
  server.stop(function() {
    // server should have ended all connections and stopped
  });
});

To instantiate and connect a client

var fs = require('fs');
var http = require('http');
var Client = require('tls-tunnel').Client;

var client = new Client({
  tunnel: {
    host: 'mytlstunnel.com',  // the host where the server is running
    port: 8080,               // the port on which the server is running
    key: fs.readFileSync('./keys/client-key.pem'),    // client's private key
    cert: fs.readFileSync('./keys/client-cert.pem'),  // client's SSL certificate
    ca: [fs.readFileSync('./keys/server-cert.pem')]   // list of authorized server SSL certificates
  },
  target: {
    host: 'localhost',  // the target host to expose through the tunnel
    port: 8000,         // the target port to expose through the tunnel
  },
  timeout: 5000 // Timeout in milliseconds to use when waiting for a server to assign a public port (default is 2000)
});

client.connect(function(error, port) {
  if (error) {
    // errors could include not having enough ports available on
    // the server to support another
  } else {
    // only if no errors were encountered will the <port> parameter
    // contain the public port that was assigned for the tunnel
    http.get('http://mytlstunnel.com:' + port, function(res) {
      res.on('data', function() {
        // should receive the response from localhost:8000 here 
        // (if it's listening of course)
      });
      res.on('end', function() {
        client.disconnect(function() {
          // client should have ended all connections
        });
      });
    });
  }
});

Hints on generating certs for testing

See the test/keys folder for certificates used by the tests. These can be regenerated at anytime using either keys.sh (OSX, Linux) or keys.bat (Windows). These scripts use OpenSSL. OSX and Linux most likely already ship with OpenSSL. If using Windows you will need to install OpenSSL first.

It should be noted that for the client to authorize server certificates they need to have the correct hosts listed as altnames in the v3 extensions (although this doesn't seem to be required on Windows).

Roadmap

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using ./grunt.sh or .\grunt.bat.

Release History

(Nothing yet)

License

Copyright (c) 2012 Peter Halliday
Licensed under the MIT license.