diff --git a/README.md b/README.md index 65ca2ca..efd6fa8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ npm install -g stunnel How to use `stunnel.js` with your own instance of `stunneld.js`: ```bash -stunneld.js --servenames tunnel.example.com --protocols wss --secret abc123 +stunneld.js --servernames tunnel.example.com --protocols wss --secret abc123 ``` Options @@ -31,6 +31,13 @@ Options incoming http and https should be forwarded ``` +### Privileged Ports without sudo + +```bash +# Linux +sudo setcap 'cap_net_bind_service=+ep' $(which node) +``` + ### Alterntive Methods **NOT YET IMPLEMENTED** diff --git a/bin/stunneld.js b/bin/stunneld.js index 6a629bf..c6eddac 100755 --- a/bin/stunneld.js +++ b/bin/stunneld.js @@ -14,16 +14,30 @@ function collectProxies(val, memo) { // http:john.example.com:3000 // http://john.example.com:3000 var parts = location.split(':'); + if (1 === parts.length) { + parts[1] = parts[0]; + parts[0] = 'wss'; + } + if (2 === parts.length) { + if (/\./.test(parts[0])) { + parts[2] = parts[1]; + parts[1] = parts[0]; + parts[0] = 'wss'; + } + if (!/\./.test(parts[1])) { + throw new Error("bad --serve option Example: wss://tunnel.example.com:1337"); + } + } parts[0] = parts[0].toLowerCase(); parts[1] = parts[1].toLowerCase().replace(/(\/\/)?/, '') || '*'; parts[2] = parseInt(parts[2], 10) || 0; if (!parts[2]) { // TODO grab OS list of standard ports? - if ('http' === parts[0]) { - parts[2] = 80; + if (-1 !== [ 'ws', 'http' ].indexOf(parts[0])) { + //parts[2] = 80; } - else if ('https' === parts[0]) { - parts[2] = 443; + else if (-1 !== [ 'wss', 'https' ].indexOf(parts[0])) { + //parts[2] = 443; } else { throw new Error("port must be specified - ex: tls:*:1337"); @@ -42,6 +56,11 @@ function collectProxies(val, memo) { return memo; } +function collectPorts(val, memo) { + memo = memo.concat(val.split(/,/g).filter(Boolean)); + return memo; +} + program .version(pkg.version) //.command('jsurl ') @@ -49,8 +68,8 @@ program .action(function (url) { program.url = url; }) - .option('--serve ', 'comma separated list of :: to which matching incoming http and https should forward (reverse proxy). Ex: https://john.example.com,tls:*:1337', collectProxies, [ ]) // --reverse-proxies - .option('--serve ', 'the domain (or ip address) at which you are running stunneld.js (the proxy)') // --proxy + .option('--serve ', 'comma separated list of :: to which matching incoming http and https should forward (reverse proxy). Ex: https://john.example.com,tls:*:1337', collectProxies, [ ]) + .option('--ports ', 'comma separated list of ports on which to listen. Ex: 80,443,1337', collectPorts, [ ]) .option('--secret ', 'the same secret used by stunneld (used for JWT authentication)') .parse(process.argv) ; @@ -59,10 +78,7 @@ program.stunneld = program.stunneld || 'wss://pokemap.hellabit.com:3000'; var jwt = require('jsonwebtoken'); var domainsMap = {}; -var tokenData = { - name: null -, domains: null -}; +var tokenData = { name: null, domains: null }; var location = url.parse(program.stunneld); if (!location.protocol || /\./.test(location.protocol)) { @@ -77,13 +93,27 @@ program.serve.forEach(function (proxy) { tokenData.domains = Object.keys(domainsMap); tokenData.name = tokenData.domains[0]; +if (!program.ports.length) { + program.ports = [ 80, 443 ]; +} program.services = {}; +program.portsMap = {}; +program.servernamesMap = {}; program.serve.forEach(function (proxy) { //program.services = { 'ssh': 22, 'http': 80, 'https': 443 }; + program.servernamesMap[proxy.hostname] = true; program.services[proxy.protocol] = proxy.port; + if (proxy.port) { + program.portsMap[proxy.port] = true; + } }); +program.servernames = Object.keys(program.servernamesMap); +program.ports = program.ports.concat(Object.keys(program.portsMap)); program.token = program.token || jwt.sign(tokenData, program.secret || 'shhhhh'); +if (!program.serve.length) { + throw new Error("must specify at least on server"); +} // TODO letsencrypt program.tlsOptions = require('localhost.daplie.com-certificates').merge({}); @@ -93,10 +123,10 @@ if (!program.secret) { program.secret = 'shhhhh'; } -require('cluster-store').create().then(function (store) { - program.store = store; +//require('cluster-store').create().then(function (store) { + //program.store = store; - stunneld.connect(program); -}); + stunneld.create(program); +//}); }()); diff --git a/package.json b/package.json index b72f586..a1e8478 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,9 @@ "homepage": "https://github.com/Daplie/node-tunnel-server#readme", "dependencies": { "cluster-store": "^2.0.4", + "commander": "^2.9.0", "jsonwebtoken": "^7.1.9", + "localhost.daplie.com-certificates": "^1.2.3", "sni": "^1.0.0", "tunnel-packer": "^1.0.0", "ws": "^1.1.1" diff --git a/wstunneld.js b/wstunneld.js index e027752..7ae1d53 100644 --- a/wstunneld.js +++ b/wstunneld.js @@ -313,10 +313,10 @@ module.exports.create = function (opts) { wss.on('connection', onWsConnection); - opts.ports.forEach(function () { + opts.ports.forEach(function (port) { var tcp3000 = net.createServer(); - tcp3000.listen(3000, function () { - console.log('listening on 3000'); + tcp3000.listen(port, function () { + console.log('listening on ' + port); }); tcp3000.on('connection', onTcpConnection); });