# stunnel.js A client that works in combination with [stunneld.js](https://github.com/Daplie/node-tunnel-server) to allow you to serve http and https from any computer, anywhere through a secure tunnel. * CLI * Library CLI === Installs as `stunnel.js` with the alias `jstunnel` (for those that regularly use `stunnel` but still like commandline completion). ### Install ```bash npm install -g stunnel ``` ### Advanced Usage How to use `stunnel.js` with your own instance of `stunneld.js`: ```bash stunnel.js --locals john.example.com --stunneld wss://tunnel.example.com:443 --secret abc123 ``` ```bash stunnel.js \ --locals http:john.example.com:3000,https:john.example.com \ --stunneld wss://tunnel.example.com:443 \ --secret abc123 ``` ``` --secret the same secret used by stunneld (used for authentication) --locals comma separated list of :: to which incoming http and https should be forwarded --stunneld the domain or ip address at which you are running stunneld.js -k, --insecure ignore invalid ssl certificates from stunneld ``` ### Usage **NOT YET IMPLEMENTED** Daplie's tunneling service is not yet publicly available. **Terms of Service**: The Software and Services shall be used for Good, not Evil. Examples of good: education, business, pleasure. Examples of evil: crime, abuse, extortion. ```bash stunnel.js --agree-tos --email john@example.com --locals http:john.example.com:4080,https:john.example.com:8443 ``` Library ======= ### Example ```javascript var stunnel = require('stunnel'); stunnel.connect({ stunneld: 'wss://tunnel.example.com' , token: '...' , locals: [ // defaults to sending http to local port 80 and https to local port 443 { hostname: 'doe.net' } // sends both http and https to local port 3000 (httpolyglot) , { protocol: 'https', hostname: 'john.doe.net', port: 3000 } // send http to local port 4080 and https to local port 8443 , { protocol: 'https', hostname: 'jane.doe.net', port: 4080 } , { protocol: 'https', hostname: 'jane.doe.net', port: 8443 } ] , net: require('net') , insecure: false }); ``` * You can get sneaky with `net` and provide a `createConnection` that returns a `stream.Duplex`. ### Token ```javascript var tokenData = { domains: [ 'doe.net', 'john.doe.net', 'jane.doe.net' ] } var secret = 'shhhhh'; var token = jwt.sign(tokenData, secret); ``` ### net Let's say you want to handle http requests in-process or decrypt https before passing it to the local http handler. You'll need to create a pair of streams to connect between the local handler and the tunnel handler. You could do a little magic like this: ``` var Dup = { write: function (chunk, encoding, cb) { this.__my_socket.write(chunk, encoding); cb(); } , read: function (size) { var x = this.__my_socket.read(size); if (x) { this.push(x); } } }; stunnel.connect({ // ... , net: { createConnection: function (info, cb) { // data is the hello packet / first chunk // info = { data, servername, port, host, remoteAddress: { family, address, port } } var myDuplex = new (require('stream').Duplex)(); var myDuplex2 = new (require('stream').Duplex)(); // duplex = { write, push, end, events: [ 'readable', 'data', 'error', 'end' ] }; myDuplex2.__my_socket = myDuplex; myDuplex2._write = Dup.write; myDuplex2._read = Dup.read; myDuplex.__my_socket = myDuplex2; myDuplex._write = Dup.write; myDuplex._read = Dup.read; myDuplex.remoteFamily = info.remoteFamily; myDuplex.remoteAddress = info.remoteAddress; myDuplex.remotePort = info.remotePort; // socket.local{Family,Address,Port} myDuplex.localFamily = 'IPv4'; myDuplex.localAddress = '127.0.01'; myDuplex.localPort = info.port; httpsServer.emit('connection', myDuplex); if (cb) { cb(); } return myDuplex2; } }); ```