added tunnel server
This commit is contained in:
parent
30777af804
commit
61018d9303
|
@ -9,6 +9,16 @@ tcp:
|
||||||
- 22
|
- 22
|
||||||
address: '127.0.0.1:8022'
|
address: '127.0.0.1:8022'
|
||||||
|
|
||||||
|
# tunnel: jwt
|
||||||
|
# tunnel:
|
||||||
|
# - jwt1
|
||||||
|
# - jwt2
|
||||||
|
|
||||||
|
tunnel_server:
|
||||||
|
secret: abc123
|
||||||
|
servernames:
|
||||||
|
- 'tunnel.localhost.com'
|
||||||
|
|
||||||
tls:
|
tls:
|
||||||
acme:
|
acme:
|
||||||
email: 'joe.shmoe@example.com'
|
email: 'joe.shmoe@example.com'
|
||||||
|
|
|
@ -155,7 +155,7 @@ module.exports = function (myDeps, conf, overrideHttp) {
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
console.log('got a token from the tunnel server?');
|
console.log('got a token from the tunnel server?');
|
||||||
result.owner = owner;
|
result.owner = owner;
|
||||||
return deps.tunneler.add(result);
|
return deps.tunnelClients.add(result);
|
||||||
});
|
});
|
||||||
/*
|
/*
|
||||||
});
|
});
|
||||||
|
|
|
@ -176,7 +176,8 @@ module.exports.create = function (deps, config) {
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
deps.tunneler = require('./tunnel-manager').create(deps, config);
|
deps.tunnelClients = require('./tunnel-client-manager').create(deps, config);
|
||||||
|
deps.tunnelServer = require('./tunnel-server-manager').create(deps, config);
|
||||||
|
|
||||||
var listenPromises = [];
|
var listenPromises = [];
|
||||||
var tcpPortMap = {};
|
var tcpPortMap = {};
|
||||||
|
|
|
@ -151,11 +151,19 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acmeServer;
|
var acmeServer;
|
||||||
function checkACME(conn, opts, headers) {
|
function checkAcme(conn, opts, headers) {
|
||||||
if (headers.url.indexOf('/.well-known/acme-challenge/') !== 0) {
|
if (headers.url.indexOf('/.well-known/acme-challenge/') !== 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deps.tunnelServer.isClientDomain(separatePort(headers.host).host)) {
|
||||||
|
deps.tunnelServer.handleClientConn(conn);
|
||||||
|
process.nextTick(function () {
|
||||||
|
conn.unshift(opts.firstChunk);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!acmeServer) {
|
if (!acmeServer) {
|
||||||
acmeServer = require('http').createServer(greenlockMiddleware);
|
acmeServer = require('http').createServer(greenlockMiddleware);
|
||||||
}
|
}
|
||||||
|
@ -177,19 +185,29 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
||||||
return emitConnection(httpsRedirectServer, conn, opts);
|
return emitConnection(httpsRedirectServer, conn, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var adminDomains;
|
||||||
var adminServer;
|
var adminServer;
|
||||||
function checkAdmin(conn, opts, headers) {
|
function checkAdmin(conn, opts, headers) {
|
||||||
var host = separatePort(headers.host).host;
|
var host = separatePort(headers.host).host;
|
||||||
var admin = require('./admin').adminDomains.some(function (domain) {
|
|
||||||
return host === domain;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (admin) {
|
if (!adminDomains) {
|
||||||
|
adminDomains = require('./admin').adminDomains;
|
||||||
|
}
|
||||||
|
if (adminDomains.indexOf(host) !== -1) {
|
||||||
if (!adminServer) {
|
if (!adminServer) {
|
||||||
adminServer = require('./admin').create(deps, conf);
|
adminServer = require('./admin').create(deps, conf);
|
||||||
}
|
}
|
||||||
return emitConnection(adminServer, conn, opts);
|
return emitConnection(adminServer, conn, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deps.tunnelServer.isAdminDomain(host)) {
|
||||||
|
deps.tunnelServer.handleAdminConn(conn);
|
||||||
|
process.nextTick(function () {
|
||||||
|
conn.unshift(opts.firstChunk);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +404,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
||||||
var opts = conn.__opts;
|
var opts = conn.__opts;
|
||||||
parseHeaders(conn, opts)
|
parseHeaders(conn, opts)
|
||||||
.then(function (headers) {
|
.then(function (headers) {
|
||||||
if (checkACME(conn, opts, headers)) { return; }
|
if (checkAcme(conn, opts, headers)) { return; }
|
||||||
if (checkHttps(conn, opts, headers)) { return; }
|
if (checkHttps(conn, opts, headers)) { return; }
|
||||||
if (checkAdmin(conn, opts, headers)) { return; }
|
if (checkAdmin(conn, opts, headers)) { return; }
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,16 @@ module.exports.create = function (deps, config, netHandler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deps.tunnelServer.isClientDomain(opts.servername)) {
|
||||||
|
deps.tunnelServer.handleClientConn(socket);
|
||||||
|
if (!opts.hyperPeek) {
|
||||||
|
process.nextTick(function () {
|
||||||
|
socket.unshift(opts.firstChunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function checkModule(mod) {
|
function checkModule(mod) {
|
||||||
if (mod.name === 'proxy') {
|
if (mod.name === 'proxy') {
|
||||||
return proxy(socket, opts, mod);
|
return proxy(socket, opts, mod);
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports.create = function (deps, config) {
|
||||||
|
if (!config.tunnelServer || !Array.isArray(config.tunnelServer.servernames) || !config.tunnelServer.secret) {
|
||||||
|
return {
|
||||||
|
isAdminDomain: function () { return false; },
|
||||||
|
isClientDomain: function () { return false; },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var tunnelOpts = Object.assign({}, config.tunnelServer);
|
||||||
|
// This function should not be called because connections to the admin domains
|
||||||
|
// should already be decrypted, and connections to non-client domains should never
|
||||||
|
// be given to us in the first place.
|
||||||
|
tunnelOpts.httpsTunnel = function (servername, conn) {
|
||||||
|
console.error('tunnel server received encrypted connection to', servername);
|
||||||
|
conn.end();
|
||||||
|
};
|
||||||
|
tunnelOpts.httpsInvalid = tunnelOpts.httpsTunnel;
|
||||||
|
// This function should not be called because ACME challenges should be handled
|
||||||
|
// before admin domain connections are given to us, and the only non-encrypted
|
||||||
|
// client connections that should be given to us are ACME challenges.
|
||||||
|
tunnelOpts.handleHttp = function (servername, conn) {
|
||||||
|
console.error('tunnel server received un-encrypted connection to', servername);
|
||||||
|
conn.end([
|
||||||
|
'HTTP/1.1 404 Not Found'
|
||||||
|
, 'Date: ' + (new Date()).toUTCString()
|
||||||
|
, 'Connection: close'
|
||||||
|
, 'Content-Type: text/html'
|
||||||
|
, 'Content-Length: 9'
|
||||||
|
, ''
|
||||||
|
, 'Not Found'
|
||||||
|
].join('\r\n'));
|
||||||
|
};
|
||||||
|
tunnelOpts.handleInsecureHttp = tunnelOpts.handleHttp;
|
||||||
|
|
||||||
|
var tunnelServer = require('stunneld').create(tunnelOpts);
|
||||||
|
|
||||||
|
var httpServer = require('http').createServer(function (req, res) {
|
||||||
|
// status code 426 = Upgrade Required
|
||||||
|
res.statusCode = 426;
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify({error: {
|
||||||
|
message: 'Only websockets accepted for tunnel server'
|
||||||
|
}}));
|
||||||
|
});
|
||||||
|
var wsServer = new (require('ws').Server)({ server: httpServer });
|
||||||
|
wsServer.on('connection', tunnelServer.ws);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isAdminDomain: function (domain) {
|
||||||
|
return config.tunnelServer.servernames.indexOf(domain) !== -1;
|
||||||
|
},
|
||||||
|
handleAdminConn: function (conn) {
|
||||||
|
httpServer.emit('connection', conn);
|
||||||
|
},
|
||||||
|
|
||||||
|
isClientDomain: tunnelServer.isClientDomain,
|
||||||
|
handleClientConn: tunnelServer.tcp
|
||||||
|
};
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -41,7 +41,7 @@
|
||||||
"bluebird": "^3.4.6",
|
"bluebird": "^3.4.6",
|
||||||
"body-parser": "git+https://github.com/expressjs/body-parser.git#1.16.1",
|
"body-parser": "git+https://github.com/expressjs/body-parser.git#1.16.1",
|
||||||
"commander": "^2.9.0",
|
"commander": "^2.9.0",
|
||||||
"dns-suite": "git+https://git@git.daplie.com:Daplie/dns-suite#v1",
|
"dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1",
|
||||||
"express": "git+https://github.com/expressjs/express.git#4.x",
|
"express": "git+https://github.com/expressjs/express.git#4.x",
|
||||||
"finalhandler": "^0.4.0",
|
"finalhandler": "^0.4.0",
|
||||||
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
|
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
|
||||||
|
@ -65,6 +65,8 @@
|
||||||
"sni": "^1.0.0",
|
"sni": "^1.0.0",
|
||||||
"socket-pair": "^1.0.1",
|
"socket-pair": "^1.0.1",
|
||||||
"stunnel": "git+https://git.daplie.com/Daplie/node-tunnel-client.git#v1",
|
"stunnel": "git+https://git.daplie.com/Daplie/node-tunnel-client.git#v1",
|
||||||
"tunnel-packer": "^1.3.0"
|
"stunneld": "git+https://git.daplie.com/Daplie/node-tunnel-server.git#v1",
|
||||||
|
"tunnel-packer": "^1.3.0",
|
||||||
|
"ws": "^2.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ module.exports.create = function (deps, conf) {
|
||||||
isAuthorized(req, res, function () {
|
isAuthorized(req, res, function () {
|
||||||
if ('POST' !== req.method) {
|
if ('POST' !== req.method) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
return deps.tunneler.get(req.userId).then(function (result) {
|
return deps.tunnelClients.get(req.userId).then(function (result) {
|
||||||
res.end(JSON.stringify(result));
|
res.end(JSON.stringify(result));
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
|
|
Loading…
Reference in New Issue