Updated all agents except macOS and FreeBSD. New agents support compression.

This commit is contained in:
Ylian Saint-Hilaire 2020-07-21 16:20:17 -07:00
parent e020fe8dee
commit 193c85972c
24 changed files with 64 additions and 3501 deletions

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.

Binary file not shown.

Binary file not shown.

View File

@ -1189,20 +1189,22 @@ function createMeshCore(agent) {
var tunnel = tunnels[this.httprequest.index];
if (tunnel == null) return; // Stop duplicate calls.
// Sent tunnel statistics to the server
mesh.SendCommand({
action: 'tunnelCloseStats',
url: tunnel.url,
userid: tunnel.userid,
protocol: tunnel.protocol,
sessionid: tunnel.sessionid,
sent: this.bytesSent_uncompressed + '',
sentActual: this.bytesSent_actual + '',
sentRatio: this.bytesSent_ratio,
received: this.bytesReceived_uncompressed + '',
receivedActual: this.bytesReceived_actual + '',
receivedRatio: this.bytesReceived_ratio
});
// Sent tunnel statistics to the server, only send this if compression was used.
if (this.bytesSent_uncompressed.toString() != this.bytesSent_actual.toString()) {
mesh.SendCommand({
action: 'tunnelCloseStats',
url: tunnel.url,
userid: tunnel.userid,
protocol: tunnel.protocol,
sessionid: tunnel.sessionid,
sent: this.bytesSent_uncompressed.toString(),
sentActual: this.bytesSent_actual.toString(),
sentRatio: this.bytesSent_ratio,
received: this.bytesReceived_uncompressed.toString(),
receivedActual: this.bytesReceived_actual.toString(),
receivedRatio: this.bytesReceived_ratio
});
}
//sendConsoleText("Tunnel #" + this.httprequest.index + " closed. Sent -> " + this.bytesSent_uncompressed + ' bytes (uncompressed), ' + this.bytesSent_actual + ' bytes (actual), ' + this.bytesSent_ratio + '% compression', this.httprequest.sessionid);
delete tunnels[this.httprequest.index];
@ -1340,7 +1342,7 @@ function createMeshCore(agent) {
var consentMessage = this.httprequest.username + " requesting remote terminal access. Grant access?", consentTitle = 'MeshCentral';
if (this.httprequest.soptions != null) {
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
if (this.httprequest.soptions.consentMsgTerminal != null) { consentMessage = this.httprequest.soptions.consentMsgTerminal.replace('{0}', this.httprequest.username); }
if (this.httprequest.soptions.consentMsgTerminal != null) { consentMessage = this.httprequest.soptions.consentMsgTerminal.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
}
this.httprequest.tpromise._consent = require('message-box').create(consentTitle, consentMessage, 30);
this.httprequest.tpromise._consent.retPromise = this.httprequest.tpromise;
@ -1547,7 +1549,7 @@ function createMeshCore(agent) {
var notifyMessage = this.ws.httprequest.username + " started a remote terminal session.", notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null) {
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace('{0}', this.ws.httprequest.username); }
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
}
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
}

File diff suppressed because it is too large Load Diff

View File

@ -179,7 +179,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
var taskLimiterOptions = { hash: meshcorehash, core: parent.parent.defaultMeshCores[corename], name: corename };
// If the agent supports compression, sent the core compressed.
if ((obj.agentInfo.capabilities & 0x80) && (parent.parent.defaultMeshCoresDeflate[corename])) { args.core = parent.parent.defaultMeshCoresDeflate[corename]; }
if ((obj.agentInfo.capabilities & 0x80) && (parent.parent.defaultMeshCoresDeflate[corename])) {
args.core = parent.parent.defaultMeshCoresDeflate[corename];
}
// Update new core with task limiting so not to flood the server. This is a high priority task.
obj.agentCoreUpdatePending = true;
@ -297,12 +299,10 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Send compressed data
obj.agentUpdate.agentUpdateData = obj.agentExeInfo.zdata;
obj.agentUpdate.agentUpdateHash = obj.agentExeInfo.zhash;
//console.log('Sending compressed update agent', obj.agentExeInfo.zhashhex);
} else {
// Send uncompressed data
obj.agentUpdate.agentUpdateData = obj.agentExeInfo.data;
obj.agentUpdate.agentUpdateHash = obj.agentExeInfo.hash;
//console.log('Sending uncompressed update agent', obj.agentExeInfo.hashhex);
}
const len = Math.min(parent.parent.agentUpdateBlockSize, obj.agentUpdate.agentUpdateData.length - obj.agentUpdate.ptr);
@ -1415,6 +1415,10 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
case 'tunnelCloseStats': {
// TODO: This this extra stats from the tunnel, you can merge this into the tunnel event in the database.
//console.log(command);
// Event the session closed compression data.
var event = { etype: 'node', action: 'sessioncompression', nodeid: obj.dbNodeKey, domain: domain.id, sent: command.sent, sentActual: command.sentActual, msg: 'Agent closed session with ' + command.sentRatio + '% agent to server compression. Sent: ' + command.sent + ', Compressed: ' + command.sentActual + '.' };
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event);
break;
}
case 'plugin': {

View File

@ -51,6 +51,7 @@
"selfUpdate": { "type": "boolean", "default": false, "description": "When true, this server will attempt to self-update everyday after midnight." },
"browserPing": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the browser at x seconds interval and expects a response from the browser." },
"browserPong": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the browser at x seconds interval." },
"agentsInRam": { "type": "boolean", "default": false, "description": "Loads all agent binaries in RAM for faster agent updates." },
"agentPing": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the agent at x seconds interval and expects a response from the agent." },
"agentPong": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the agent at x seconds interval." },
"agentIdleTimeout": { "type": "integer", "minimum": 1 },

View File

@ -649,14 +649,12 @@ function CreateMeshCentralServer(config, args) {
if (typeof obj.args.tlsoffload == 'string') { obj.args.tlsoffload = obj.args.tlsoffload.split(' ').join('').split(','); }
// Check if WebSocket compression is supported. It's broken in NodeJS v11.11 to v12.15
if ((obj.args.wscompression == true) || (obj.args.agentwscompression == true)) {
const verSplit = process.version.substring(1).split('.');
var ver = parseInt(verSplit[0]) + (parseInt(verSplit[1]) / 100);
if ((ver >= 11.11) && (ver <= 12.15)) {
obj.args.wscompression = obj.args.agentwscompression = false;
obj.config.settings.wscompression = obj.config.settings.agentwscompression = false;
addServerWarning('WebSocket compression is disabled, this feature is broken in NodeJS v11.11 to v12.15.');
}
const verSplit = process.version.substring(1).split('.');
var ver = parseInt(verSplit[0]) + (parseInt(verSplit[1]) / 100);
if ((ver >= 11.11) && (ver <= 12.15)) {
if ((obj.args.wscompression === true) || (obj.args.agentwscompression === true)) { addServerWarning('WebSocket compression is disabled, this feature is broken in NodeJS v11.11 to v12.15.'); }
obj.args.wscompression = obj.args.agentwscompression = false;
obj.config.settings.wscompression = obj.config.settings.agentwscompression = false;
}
// Local console tracing
@ -2218,6 +2216,37 @@ function CreateMeshCentralServer(config, args) {
} else {
// Load the agent as-is
obj.meshAgentBinaries[archid].data = obj.fs.readFileSync(agentpath);
// Compress the agent using ZIP
var archive = require('archiver')('zip', { level: 9 }); // Sets the compression method.
const onZipData = function onZipData(buffer) { onZipData.x.zacc.push(buffer); }
const onZipEnd = function onZipEnd() {
// Concat all the buffer for create compressed zip agent
var concatData = Buffer.concat(onZipData.x.zacc);
delete onZipData.x.zacc;
// Hash the compressed binary
var hash = obj.crypto.createHash('sha384').update(concatData);
onZipData.x.zhash = hash.digest('binary');
onZipData.x.zhashhex = Buffer.from(onZipData.x.zhash, 'binary').toString('hex');
// Set the agent
onZipData.x.zdata = concatData;
onZipData.x.zsize = concatData.length;
console.log('Packed', onZipData.x.size, onZipData.x.zsize);
}
const onZipError = function onZipError() { delete onZipData.x.zacc; }
obj.meshAgentBinaries[archid].zacc = [];
onZipData.x = obj.meshAgentBinaries[archid];
onZipEnd.x = obj.meshAgentBinaries[archid];
onZipError.x = obj.meshAgentBinaries[archid];
archive.on('data', onZipData);
archive.on('end', onZipEnd);
archive.on('error', onZipError);
archive.append(obj.meshAgentBinaries[archid].data, { name: 'meshagent' });
archive.finalize();
}
}

View File

@ -40,6 +40,7 @@
"_compression": true,
"_wscompression": false,
"_agentwscompression": true,
"_agentsInRam": false,
"_webRTC": false,
"_nice404": false,
"_clickOnce": false,