changed method for mapping services to local ports
This commit is contained in:
parent
a9326c3eb0
commit
ae15111b0f
104
bin/stunnel.js
104
bin/stunnel.js
|
@ -13,7 +13,6 @@ function collectDomains(val, memo) {
|
||||||
|
|
||||||
function parseProxy(location) {
|
function parseProxy(location) {
|
||||||
// john.example.com
|
// john.example.com
|
||||||
// https:3443
|
|
||||||
// http:john.example.com:3000
|
// http:john.example.com:3000
|
||||||
// http://john.example.com:3000
|
// http://john.example.com:3000
|
||||||
var parts = location.split(':');
|
var parts = location.split(':');
|
||||||
|
@ -144,19 +143,11 @@ function connectTunnel() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
program.locals.forEach(function (proxy) {
|
Object.keys(program.services).forEach(function (protocol) {
|
||||||
var port = proxy.port;
|
var subServices = program.services[protocol];
|
||||||
if (!proxy.port) {
|
Object.keys(subServices).forEach(function (hostname) {
|
||||||
if ('http' === proxy.protocol) {
|
console.info('[local proxy]', protocol + '://' + hostname + ' => ' + subServices[hostname]);
|
||||||
port = hasHttp;
|
});
|
||||||
}
|
|
||||||
else if ('https' === proxy.protocol) {
|
|
||||||
port = hasHttps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (proxy.protocol) {
|
|
||||||
console.info('[local proxy]', proxy.protocol + '://' + proxy.hostname + ' => ' + port);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
console.info('');
|
console.info('');
|
||||||
|
|
||||||
|
@ -179,22 +170,22 @@ function rawTunnel() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!program.token) {
|
||||||
var jwt = require('jsonwebtoken');
|
var jwt = require('jsonwebtoken');
|
||||||
var tokenData = {
|
var tokenData = {
|
||||||
domains: null
|
domains: Object.keys(domainsMap).filter(Boolean)
|
||||||
};
|
};
|
||||||
var location = url.parse(program.stunneld);
|
|
||||||
|
|
||||||
|
program.token = jwt.sign(tokenData, program.secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
var location = url.parse(program.stunneld);
|
||||||
if (!location.protocol || /\./.test(location.protocol)) {
|
if (!location.protocol || /\./.test(location.protocol)) {
|
||||||
program.stunneld = 'wss://' + program.stunneld;
|
program.stunneld = 'wss://' + program.stunneld;
|
||||||
location = url.parse(program.stunneld);
|
location = url.parse(program.stunneld);
|
||||||
}
|
}
|
||||||
program.stunneld = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
|
program.stunneld = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
|
||||||
|
|
||||||
tokenData.domains = Object.keys(domainsMap).filter(Boolean);
|
|
||||||
|
|
||||||
program.token = program.token || jwt.sign(tokenData, program.secret);
|
|
||||||
|
|
||||||
connectTunnel();
|
connectTunnel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,45 +225,50 @@ function daplieTunnel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var domainsMap = {};
|
var domainsMap = {};
|
||||||
var hasHttp;
|
var services = {};
|
||||||
var hasHttps;
|
|
||||||
|
|
||||||
program.locals = program.locals || [];
|
program.locals = (program.locals || []).concat(program.domains || []);
|
||||||
program.locals = program.locals.concat(program.domains || []);
|
|
||||||
program.locals.forEach(function (proxy) {
|
|
||||||
if ('*' === proxy.hostname) {
|
|
||||||
if ('http' === proxy.protocol) {
|
|
||||||
hasHttp = proxy.port;
|
|
||||||
}
|
|
||||||
else if ('https' === proxy.protocol) {
|
|
||||||
hasHttps = proxy.port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!hasHttp) {
|
|
||||||
program.locals.push({
|
|
||||||
protocol: 'http'
|
|
||||||
, hostname: '*'
|
|
||||||
, port: 8443
|
|
||||||
});
|
|
||||||
hasHttp = 8443;
|
|
||||||
}
|
|
||||||
if (!hasHttps) {
|
|
||||||
program.locals.push({
|
|
||||||
protocol: 'https'
|
|
||||||
, hostname: '*'
|
|
||||||
, port: 8443
|
|
||||||
});
|
|
||||||
hasHttps = 8443;
|
|
||||||
}
|
|
||||||
program.locals.forEach(function (proxy) {
|
program.locals.forEach(function (proxy) {
|
||||||
|
// Create a map from which we can derive a list of all domains we want forwarded to us.
|
||||||
|
if (proxy.hostname && proxy.hostname !== '*') {
|
||||||
domainsMap[proxy.hostname] = true;
|
domainsMap[proxy.hostname] = true;
|
||||||
});
|
|
||||||
if (domainsMap.hasOwnProperty('*')) {
|
|
||||||
delete domainsMap['*'];
|
|
||||||
//domainsMap['*'] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a map of which port different protocols should be forwarded to, allowing for specific
|
||||||
|
// domains to go to different ports if need be (though that only works for HTTP and HTTPS).
|
||||||
|
if (proxy.protocol && proxy.port) {
|
||||||
|
services[proxy.protocol] = services[proxy.protocol] || {};
|
||||||
|
|
||||||
|
if (/http/.test(proxy.protocol) && proxy.hostname && proxy.hostname !== '*') {
|
||||||
|
services[proxy.protocol][proxy.hostname] = proxy.port;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (services[proxy.protocol]['*'] && services[proxy.protocol]['*'] !== proxy.port) {
|
||||||
|
console.error('cannot forward generic', proxy.protocol, 'traffic to multiple ports');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
services[proxy.protocol]['*'] = proxy.port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(domainsMap).length === 0) {
|
||||||
|
console.error('no domains specified');
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have generic ports for HTTP and HTTPS
|
||||||
|
services.https = services.https || {};
|
||||||
|
services.https['*'] = services.https['*'] || 8443;
|
||||||
|
|
||||||
|
services.http = services.http || {};
|
||||||
|
services.http['*'] = services.http['*'] || services.https['*'];
|
||||||
|
|
||||||
|
program.services = services;
|
||||||
|
|
||||||
if (!(program.secret || program.token) && !program.stunneld) {
|
if (!(program.secret || program.token) && !program.stunneld) {
|
||||||
daplieTunnel();
|
daplieTunnel();
|
||||||
}
|
}
|
||||||
|
|
28
wsclient.js
28
wsclient.js
|
@ -7,13 +7,6 @@ var Packer = require('tunnel-packer');
|
||||||
var authenticated = false;
|
var authenticated = false;
|
||||||
|
|
||||||
function run(copts) {
|
function run(copts) {
|
||||||
// TODO pair with hostname / sni
|
|
||||||
copts.services = {};
|
|
||||||
copts.locals.forEach(function (proxy) {
|
|
||||||
//program.services = { 'ssh': 22, 'http': 80, 'https': 443 };
|
|
||||||
copts.services[proxy.protocol] = proxy.port;
|
|
||||||
});
|
|
||||||
|
|
||||||
var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + copts.token;
|
var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + copts.token;
|
||||||
var wstunneler;
|
var wstunneler;
|
||||||
var localclients = {};
|
var localclients = {};
|
||||||
|
@ -26,9 +19,10 @@ function run(copts) {
|
||||||
onmessage: function (opts) {
|
onmessage: function (opts) {
|
||||||
var net = copts.net || require('net');
|
var net = copts.net || require('net');
|
||||||
var cid = Packer.addrToId(opts);
|
var cid = Packer.addrToId(opts);
|
||||||
var service = opts.service;
|
var service = opts.service.toLowerCase();
|
||||||
var port = copts.services[service];
|
var portList = copts.services[service];
|
||||||
var servername;
|
var servername;
|
||||||
|
var port;
|
||||||
var str;
|
var str;
|
||||||
var m;
|
var m;
|
||||||
|
|
||||||
|
@ -39,7 +33,12 @@ function run(copts) {
|
||||||
localclients[cid].write(opts.data);
|
localclients[cid].write(opts.data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ('http' === service) {
|
if (!portList) {
|
||||||
|
handlers._onLocalError(cid, opts, new Error("unsupported service '" + service + "'"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('http' === service) {
|
||||||
str = opts.data.toString();
|
str = opts.data.toString();
|
||||||
m = str.match(/(?:^|[\r\n])Host: ([^\r\n]+)[\r\n]*/im);
|
m = str.match(/(?:^|[\r\n])Host: ([^\r\n]+)[\r\n]*/im);
|
||||||
servername = (m && m[1].toLowerCase() || '').split(':')[0];
|
servername = (m && m[1].toLowerCase() || '').split(':')[0];
|
||||||
|
@ -48,20 +47,19 @@ function run(copts) {
|
||||||
servername = sni(opts.data);
|
servername = sni(opts.data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
handlers._onLocalError(cid, opts, new Error("unsupported service '" + service + "'"));
|
servername = '*';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!servername) {
|
if (!servername) {
|
||||||
console.info("[error] missing servername for '" + cid + "'", opts.data.byteLength);
|
|
||||||
//console.warn(opts.data.toString());
|
//console.warn(opts.data.toString());
|
||||||
wstunneler.send(Packer.pack(opts, null, 'error'), { binary: true });
|
handlers._onLocalError(cid, opts, new Error("missing servername for '" + cid + "' " + opts.data.byteLength));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
port = portList[servername] || portList['*'];
|
||||||
|
|
||||||
console.info("[connect] new client '" + cid + "' for '" + servername + "' (" + (handlers._numClients() + 1) + " clients)");
|
console.info("[connect] new client '" + cid + "' for '" + servername + "' (" + (handlers._numClients() + 1) + " clients)");
|
||||||
|
|
||||||
console.log('port', port, opts.port, service, copts.services);
|
console.log('port', port, opts.port, service, portList);
|
||||||
localclients[cid] = net.createConnection({
|
localclients[cid] = net.createConnection({
|
||||||
port: port
|
port: port
|
||||||
, host: '127.0.0.1'
|
, host: '127.0.0.1'
|
||||||
|
|
Loading…
Reference in New Issue