Added alternate agent port support.

Ylian Saint-Hilaire committed May 3, 2020 at 10:46 UTC dec34998d852fd1d2780dc9a0b1990b0a95ffc21
2 files changed +68 -2
sample-config.json
+4
@@ -23,9 +23,13 @@
23 "_Port": 443,
24 "_AliasPort": 444,
25 "_RedirPort": 80,
26 + "_RedirAliasPort": 80,
27 + "_AgentPort": 1234,
28 "_ExactPorts": true,
29 "_AllowLoginToken": true,
30 "_AllowFraming": true,
31 + "_CookieIpCheck": false,
32 + "_CookieEncoding": "hex",
33 "_WebRTC": false,
34 "_Nice404": false,
35 "_ClickOnce": false,
webserver.js
+64 -2
@@ -67,15 +67,16 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
67 obj.webauthn = require('./webauthn.js').CreateWebAuthnModule();
68
69 // Variables
70 + obj.args = args;
71 obj.parent = parent;
72 obj.filespath = parent.filespath;
73 obj.db = db;
74 obj.app = obj.express();
75 + if (obj.args.agentport) { obj.agentapp = obj.express(); }
76 obj.app.use(require('compression')());
77 obj.tlsServer = null;
78 obj.tcpServer = null;
79 obj.certificates = certificates;
78 - obj.args = args;
80 obj.users = {}; // UserID --> User
81 obj.meshes = {}; // MeshID --> Mesh (also called device group)
82 obj.userGroups = {}; // UGrpID --> User Group
@@ -3789,6 +3790,25 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3790 obj.expressWs = require('express-ws')(obj.app, obj.tlsServer);
3791 }
3792
3793 + // Start a second agent-only server if needed
3794 + if (obj.args.agentport) {
3795 + if (obj.args.notls || obj.args.tlsoffload) {
3796 + // Setup the HTTP server without TLS
3797 + obj.expressWsAlt = require('express-ws')(obj.agentapp);
3798 + } else {
3799 + // Setup the agent HTTP server with TLS, use only TLS 1.2 and higher with perfect forward secrecy (PFS).
3800 + const tlsOptions = { cert: obj.certificates.web.cert, key: obj.certificates.web.key, ca: obj.certificates.web.ca, rejectUnauthorized: true, ciphers: "HIGH:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_CHACHA20_POLY1305_SHA256", secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE | constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1 };
3801 + if (obj.tlsSniCredentials != null) { tlsOptions.SNICallback = TlsSniCallback; } // We have multiple web server certificate used depending on the domain name
3802 + obj.tlsAltServer = require('https').createServer(tlsOptions, obj.agentapp);
3803 + obj.tlsAltServer.on('secureConnection', function () { /*console.log('tlsAltServer secureConnection');*/ });
3804 + obj.tlsAltServer.on('error', function (err) { console.log('tlsAltServer error', err); });
3805 + //obj.tlsAltServer.on('tlsClientError', function (err) { console.log('tlsClientError', err); });
3806 + obj.tlsAltServer.on('newSession', function (id, data, cb) { if (tlsSessionStoreCount > 1000) { tlsSessionStoreCount = 0; tlsSessionStore = {}; } tlsSessionStore[id.toString('hex')] = data; tlsSessionStoreCount++; cb(); });
3807 + obj.tlsAltServer.on('resumeSession', function (id, cb) { cb(null, tlsSessionStore[id.toString('hex')] || null); });
3808 + obj.expressWsAlt = require('express-ws')(obj.agentapp, obj.tlsAltServer);
3809 + }
3810 + }
3811 +
3812 // Setup middleware
3813 obj.app.engine('handlebars', obj.exphbs({ defaultLayout: null })); // defaultLayout: 'main'
3814 obj.app.set('view engine', 'handlebars');
@@ -3970,6 +3990,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3990 });
3991 }
3992
3993 + // Setup the alternative agent-only port
3994 + if (obj.args.agentport) {
3995 + // Receive mesh agent connections on alternate port
3996 + obj.agentapp.ws(url + 'agent.ashx', function (ws, req) {
3997 + var domain = checkAgentIpAddress(ws, req);
3998 + if (domain == null) { parent.debug('web', 'Got agent connection with bad domain or blocked IP address ' + cleanRemoteAddr(req.ip) + ', holding.'); return; }
3999 + //console.log('Agent connect: ' + cleanRemoteAddr(req.ip));
4000 + try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); }
4001 + });
4002 +
4003 + // Setup mesh relay on alternative agent-only port
4004 + obj.agentapp.ws(url + 'meshrelay.ashx', function (ws, req) {
4005 + PerformWSSessionAuth(ws, req, true, function (ws1, req1, domain, user, cookie) {
4006 + if (((parent.config.settings.desktopmultiplex === true) || (domain.desktopmultiplex === true)) && (req.query.p == 2)) {
4007 + obj.meshDesktopMultiplexHandler.CreateMeshRelay(obj, ws1, req1, domain, user, cookie); // Desktop multiplexor 1-to-n
4008 + } else {
4009 + obj.meshRelayHandler.CreateMeshRelay(obj, ws1, req1, domain, user, cookie); // Normal relay 1-to-1
4010 + }
4011 + });
4012 + });
4013 + }
4014 +
4015 // Memory Tracking
4016 if (typeof obj.args.memorytracking == 'number') {
4017 obj.app.get(url + 'memorytracking.csv', function (req, res) {
@@ -4030,8 +4072,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4072 });
4073 }
4074
4033 - // Start server on a free port
4075 + // Start server on a free port.
4076 CheckListenPort(obj.args.port, StartWebServer);
4077 +
4078 + // Start on a second agent-only alternative port if needed.
4079 + if (obj.args.agentport) { CheckListenPort(obj.args.agentport, StartAltWebServer); }
4080 }
4081
4082 // Authenticates a session and forwards
@@ -4284,6 +4329,23 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4329 }
4330 }
4331
4332 + // Start the ExpressJS web server on agent-only alternative port
4333 + function StartAltWebServer(port) {
4334 + if ((port < 1) || (port > 65535)) return;
4335 + if (obj.tlsAltServer != null) {
4336 + if (obj.args.lanonly == true) {
4337 + obj.tcpAltServer = obj.tlsAltServer.listen(port, function () { console.log('MeshCentral HTTPS agent-only server running on port ' + port + ((args.aliasport != null) ? (', alias port ' + args.aliasport) : '') + '.'); });
4338 + } else {
4339 + obj.tcpAltServer = obj.tlsAltServer.listen(port, function () { console.log('MeshCentral HTTPS agent-only server running on ' + certificates.CommonName + ':' + port + ((args.aliasport != null) ? (', alias port ' + args.aliasport) : '') + '.'); });
4340 + }
4341 + if (obj.parent.authlog) { obj.parent.authLog('https', 'Server listening on 0.0.0.0 port ' + port + '.'); }
4342 + obj.parent.updateServerState('https-agent-port', port);
4343 + } else {
4344 + obj.tcpAltServer = obj.app.listen(port, function () { console.log('MeshCentral HTTP agent-only server running on port ' + port + ((args.aliasport != null) ? (', alias port ' + args.aliasport) : '') + '.'); });
4345 + obj.parent.updateServerState('http-agent-port', port);
4346 + }
4347 + }
4348 +
4349 // Force mesh agent disconnection
4350 obj.forceMeshAgentDisconnect = function (user, domain, nodeid, disconnectMode) {
4351 if (nodeid == null) return;