mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-09 12:48:06 -05:00
Added swarm server IP filtering.
This commit is contained in:
parent
b22be096d7
commit
8d21e843a6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
46
meshagent.js
46
meshagent.js
@ -266,7 +266,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
// Decode the certificate
|
// Decode the certificate
|
||||||
var certlen = obj.common.ReadShort(msg, 2);
|
var certlen = obj.common.ReadShort(msg, 2);
|
||||||
obj.unauth = {};
|
obj.unauth = {};
|
||||||
try { obj.unauth.nodeid = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(msg.substring(4, 4 + certlen))).publicKey, { md: obj.forge.md.sha384.create() }).data, 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); } catch (e) { return; }
|
try { obj.unauth.nodeid = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(msg.substring(4, 4 + certlen))).publicKey, { md: obj.forge.md.sha384.create() }).data, 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); } catch (ex) { console.log(ex); return; }
|
||||||
obj.unauth.nodeCertPem = '-----BEGIN CERTIFICATE-----\r\n' + Buffer.from(msg.substring(4, 4 + certlen), 'binary').toString('base64') + '\r\n-----END CERTIFICATE-----';
|
obj.unauth.nodeCertPem = '-----BEGIN CERTIFICATE-----\r\n' + Buffer.from(msg.substring(4, 4 + certlen), 'binary').toString('base64') + '\r\n-----END CERTIFICATE-----';
|
||||||
|
|
||||||
// Check the agent signature if we can
|
// Check the agent signature if we can
|
||||||
@ -462,13 +462,43 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
// Verify the agent signature
|
// Verify the agent signature
|
||||||
function processAgentSignature(msg) {
|
function processAgentSignature(msg) {
|
||||||
if (obj.args.ignoreagenthashcheck !== true) {
|
if (obj.args.ignoreagenthashcheck !== true) {
|
||||||
// Verify the signature. This is the fast way, without using forge.
|
var verified = false;
|
||||||
const verify = obj.parent.crypto.createVerify('SHA384');
|
|
||||||
verify.end(Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the private key hash
|
if (msg.length != 384) {
|
||||||
if (verify.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) {
|
// Verify a PKCS7 signature.
|
||||||
const verify2 = obj.parent.crypto.createVerify('SHA384');
|
var msgDer = null;
|
||||||
verify2.end(Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the full cert hash
|
try { msgDer = obj.forge.asn1.fromDer(obj.forge.util.createBuffer(msg, 'binary')); } catch (ex) { }
|
||||||
if (verify2.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { return false; }
|
if (msgDer != null) {
|
||||||
|
try {
|
||||||
|
var p7 = obj.forge.pkcs7.messageFromAsn1(msgDer);
|
||||||
|
var sig = p7.rawCapture.signature;
|
||||||
|
|
||||||
|
// Verify with key hash
|
||||||
|
var buf = Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary');
|
||||||
|
var verifier = obj.parent.crypto.createVerify('RSA-SHA384');
|
||||||
|
verifier.update(buf);
|
||||||
|
verified = verifier.verify(obj.unauth.nodeCertPem, sig, 'binary');
|
||||||
|
if (verified == false) {
|
||||||
|
// Verify with full hash
|
||||||
|
buf = Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary');
|
||||||
|
verifier = obj.parent.crypto.createVerify('RSA-SHA384');
|
||||||
|
verifier.update(buf);
|
||||||
|
verified = verifier.verify(obj.unauth.nodeCertPem, sig, 'binary');
|
||||||
|
}
|
||||||
|
if (verified == false) { return false; } // Not a valid signature
|
||||||
|
} catch (ex) { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verified == false) {
|
||||||
|
// Verify the RSA signature. This is the fast way, without using forge.
|
||||||
|
const verify = obj.parent.crypto.createVerify('SHA384');
|
||||||
|
verify.end(Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the private key hash
|
||||||
|
if (verify.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) {
|
||||||
|
const verify2 = obj.parent.crypto.createVerify('SHA384');
|
||||||
|
verify2.end(Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the full cert hash
|
||||||
|
if (verify2.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { return false; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
||||||
|
|
||||||
// Check for invalid arguments
|
// Check for invalid arguments
|
||||||
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbimport', 'selfupdate', 'tlsoffload', 'userallowedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore'];
|
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbimport', 'selfupdate', 'tlsoffload', 'userallowedip', 'swarmallowedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore'];
|
||||||
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
||||||
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
||||||
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
||||||
@ -252,6 +252,7 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80;
|
if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80;
|
||||||
if (obj.args.minifycore === 0) obj.args.minifycore = false;
|
if (obj.args.minifycore === 0) obj.args.minifycore = false;
|
||||||
if (typeof obj.args.userallowedip == 'string') { if (obj.args.userallowedip == '') { obj.args.userallowedip = null; } else { obj.args.userallowedip = obj.args.userallowedip.split(','); } }
|
if (typeof obj.args.userallowedip == 'string') { if (obj.args.userallowedip == '') { obj.args.userallowedip = null; } else { obj.args.userallowedip = obj.args.userallowedip.split(','); } }
|
||||||
|
if (typeof obj.args.swarmallowedip == 'string') { if (obj.args.swarmallowedip == '') { obj.args.swarmallowedip = null; } else { obj.args.swarmallowedip = obj.args.swarmallowedip.split(','); } }
|
||||||
if (typeof obj.args.debug == 'number') obj.debugLevel = obj.args.debug;
|
if (typeof obj.args.debug == 'number') obj.debugLevel = obj.args.debug;
|
||||||
if (obj.args.debug == true) obj.debugLevel = 1;
|
if (obj.args.debug == true) obj.debugLevel = 1;
|
||||||
obj.db = require('./db.js').CreateDB(obj);
|
obj.db = require('./db.js').CreateDB(obj);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.2.5-y",
|
"version": "0.2.6-d",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -122,7 +122,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
|||||||
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
|
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true }, onConnection);
|
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true, rejectUnauthorized: false }, onConnection);
|
||||||
obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } });
|
obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } });
|
||||||
loadMigrationAgents();
|
loadMigrationAgents();
|
||||||
|
|
||||||
@ -147,6 +147,9 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
// Called when a legacy agent connects to this server
|
// Called when a legacy agent connects to this server
|
||||||
function onConnection(socket) {
|
function onConnection(socket) {
|
||||||
|
// Check for blocked IP address
|
||||||
|
if (checkSwarmIpAddress(socket, obj.args.swarmallowedip) == false) { Debug(1, "SWARM:New blocked agent connection"); return; }
|
||||||
|
|
||||||
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", socket: socket };
|
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", socket: socket };
|
||||||
socket.setEncoding('binary');
|
socket.setEncoding('binary');
|
||||||
socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
|
socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
|
||||||
@ -349,6 +352,16 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the source IP address is allowed for a given allowed list, return false if not
|
||||||
|
function checkSwarmIpAddress(socket, allowedIpList) {
|
||||||
|
if (allowedIpList == null) { return true; }
|
||||||
|
try {
|
||||||
|
var ip = socket.remoteAddress;
|
||||||
|
if (ip) { for (var i = 0; i < allowedIpList.length; i++) { if (require('ipcheck').match(ip, allowedIpList[i])) { return true; } } }
|
||||||
|
} catch (e) { console.log(e); }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
function Debug(lvl) {
|
function Debug(lvl) {
|
||||||
if (lvl > obj.parent.debugLevel) return;
|
if (lvl > obj.parent.debugLevel) return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user