Added AgentIssues command to server console.

Ylian Saint-Hilaire committed Feb 3, 2021 at 15:36 UTC 45e3b8efed27acec20cffc6fd2b09f8c178ad16a
3 files changed +29 -1
meshagent.js
+13
@@ -247,6 +247,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
247 if (agentUpdateMethod === 2) { // Use meshcore agent update system
248 // Send the recovery core to the agent, if the agent is capable of running one
249 if (((obj.agentInfo.capabilities & 16) != 0) && (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core != null)) {
250 + parent.agentStats.agentMeshCoreBinaryUpdate++;
251 obj.agentCoreUpdate = true;
252 obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0)); // Ask to clear the core
253 obj.sendBinary(common.ShortToStr(11) + common.ShortToStr(0)); // Ask for meshcore hash
@@ -433,6 +434,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
434 parent.parent.updateProxyCertificates(false);
435 }
436 parent.agentStats.agentBadWebCertHashCount++;
437 + parent.setAgentIssue(obj, "BadWebCertHash: " + Buffer.from(msg.substring(2, 50), 'binary').toString('hex'));
438 parent.parent.debug('agent', 'Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (Buffer.from(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').');
439 parent.parent.debug('agent', 'Agent reported web cert hash:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex')) + '.');
440 console.log('Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (Buffer.from(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').');
@@ -471,6 +473,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
473 if (obj.unauthsign != null) {
474 if (processAgentSignature(obj.unauthsign) == false) {
475 parent.agentStats.agentBadSignature1Count++;
476 + parent.setAgentIssue(obj, "BadSignature1");
477 parent.parent.debug('agent', 'Agent connected with bad signature, holding connection (' + obj.remoteaddrport + ').');
478 console.log('Agent connected with bad signature, holding connection (' + obj.remoteaddrport + ').'); return;
479 } else { completeAgentConnection(); }
@@ -491,6 +494,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
494 if (obj.agentnonce == null) { obj.unauthsign = msg.substring(4 + certlen); } else {
495 if (processAgentSignature(msg.substring(4 + certlen)) == false) {
496 parent.agentStats.agentBadSignature2Count++;
497 + parent.setAgentIssue(obj, "BadSignature2");
498 parent.parent.debug('agent', 'Agent connected with bad signature, holding connection (' + obj.remoteaddrport + ').');
499 console.log('Agent connected with bad signature, holding connection (' + obj.remoteaddrport + ').'); return;
500 }
@@ -749,6 +753,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
753 if (mesh == null) {
754 // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
755 parent.agentStats.invalidDomainMesh2Count++;
756 + parent.setAgentIssue(obj, "invalidDomainMesh2");
757 parent.parent.debug('agent', 'Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
758 console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
759 return;
@@ -758,6 +763,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
763 if (mesh.mtype != 2) {
764 // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
765 parent.agentStats.invalidMeshType2Count++;
766 + parent.setAgentIssue(obj, "invalidMeshType2");
767 parent.parent.debug('agent', 'Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
768 console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
769 return;
@@ -809,6 +815,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
815 if (mesh == null) {
816 // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
817 parent.agentStats.invalidDomainMeshCount++;
818 + parent.setAgentIssue(obj, "invalidDomainMesh");
819 parent.parent.debug('agent', 'Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
820 console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
821 return;
@@ -818,6 +825,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
825 if (mesh.mtype != 2) {
826 // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
827 parent.agentStats.invalidMeshTypeCount++;
828 + parent.setAgentIssue(obj, "invalidMeshType");
829 parent.parent.debug('agent', 'Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
830 console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
831 return;
@@ -864,6 +872,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
872
873 // Close the duplicate agent
874 parent.agentStats.duplicateAgentCount++;
875 + parent.setAgentIssue(obj, "duplicateAgent");
876 if (obj.nodeid != null) { parent.parent.debug('agent', 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddrport + ')'); }
877 dupAgent.close(3);
878 } else {
@@ -964,6 +973,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
973 const mesh = parent.meshes[obj.dbMeshKey];
974 if (mesh == null) {
975 parent.agentStats.meshDoesNotExistCount++;
976 + parent.setAgentIssue(obj, "meshDoesNotExist");
977 // TODO: Mark this agent as part of a mesh that does not exists.
978 return; // Probably not worth doing anything else. Hold this agent.
979 }
@@ -1103,6 +1113,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1113 if (verified !== true) {
1114 // Not a valid signature
1115 parent.agentStats.invalidPkcsSignatureCount++;
1116 + parent.setAgentIssue(obj, "invalidPkcsSignature");
1117 return false;
1118 }
1119 } catch (ex) { };
@@ -1118,6 +1129,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1129 verify2.end(Buffer.from(getWebCertFullHash(domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the full cert hash
1130 if (verify2.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) {
1131 parent.agentStats.invalidRsaSignatureCount++;
1132 + parent.setAgentIssue(obj, "invalidRsaSignature");
1133 return false;
1134 }
1135 }
@@ -1146,6 +1158,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1158 try { command = JSON.parse(str); } catch (ex) {
1159 // If the command can't be parsed, ignore it.
1160 parent.agentStats.invalidJsonCount++;
1161 + parent.setAgentIssue(obj, "invalidJson (" + str.length + "): " + str);
1162 parent.parent.debug('agent', 'Unable to parse agent JSON (' + obj.remoteaddrport + ')');
1163 console.log('Unable to parse agent JSON (' + obj.remoteaddrport + '): ' + str, ex);
1164 return;
meshuser.js
+10 -1
@@ -883,7 +883,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
883
884 switch (cmd) {
885 case 'help': {
886 - var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,sms,amtacm,certhashes,watchdog,amtmanager';
886 + var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,sms,amtacm,certhashes,watchdog,amtmanager';
887 if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
888 availcommands = availcommands.split(',').sort();
889 while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
@@ -1049,6 +1049,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1049 }
1050 break;
1051 }
1052 + case 'agentissues': {
1053 + var stats = parent.getAgentIssues();
1054 + if (stats.length == 0) {
1055 + r = "No agent issues.";
1056 + } else {
1057 + for (var i in stats) { r += stats[i].join(', ') + '\r\n'; }
1058 + }
1059 + break;
1060 + }
1061 case 'webstats': {
1062 var stats = parent.getStats();
1063 for (var i in stats) {
webserver.js
+6
@@ -308,6 +308,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
308 createMeshAgentCount: 0,
309 agentClose: 0,
310 agentBinaryUpdate: 0,
311 + agentMeshCoreBinaryUpdate: 0,
312 coreIsStableCount: 0,
313 verifiedAgentConnectionCount: 0,
314 clearingCoreCount: 0,
@@ -331,6 +332,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
332 }
333 obj.getAgentStats = function () { return obj.agentStats; }
334
335 + // Keep a record of the last agent issues.
336 + obj.getAgentIssues = function () { return obj.agentIssues; }
337 + obj.setAgentIssue = function (agent, issue) { obj.agentIssues.push([new Date().toLocaleTimeString(), agent.remoteaddrport, issue]); while (obj.setAgentIssue.length > 50) { obj.agentIssues.shift(); } }
338 + obj.agentIssues = [];
339 +
340 // Authenticate the user
341 obj.authenticate = function (name, pass, domain, fn) {
342 if ((typeof (name) != 'string') || (typeof (pass) != 'string') || (typeof (domain) != 'object')) { fn(new Error('invalid fields')); return; }