1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-03-09 15:40:18 +00:00

Added support for MeshCmd routing.

This commit is contained in:
Ylian Saint-Hilaire 2017-10-31 16:19:58 -07:00
parent 951e6236f9
commit e75adafb05
21 changed files with 343 additions and 70 deletions

BIN
agents/MeshConsole.exe Normal file

Binary file not shown.

BIN
agents/MeshConsole64.exe Normal file

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.

170
agents/meshcmd.js Normal file
View file

@ -0,0 +1,170 @@
var fs = require('fs');
var os = require('os');
var net = require('net');
var http = require('http');
var dgram = require('dgram');
var httpHeaders = require('http-headers');
var tcpserver = null;
var broadcastSockets = {};
var multicastSockets = {};
var discoveryInterval = null;
var membershipIPv4 = '239.255.255.235';
var membershipIPv6 = 'FF02:0:0:0:0:0:0:FE';
/*
// Route Settings
var settings = {
action: 'route',
localPort: 1234,
remoteName: 'AmtMachine7',
remoteNodeId: 'node//nmiPnDhT3vHKu$zg296YC5RjK53Trgh3Cimx3K8GVrFh$xch0UAAett2rbJpeddc',
remotePort: 3389,
username: 'a',
password: 'a',
serverUrl: 'wss://devbox.mesh.meshcentral.com:443/meshrelay.ashx',
serverId: 'D99362D5ED8BAEA8BF9E743B34B242256370C460FD66CB62373C6CFCB204D6D707403E396CF0EF6DC2B3A42F735135FD', // SHA384 of server HTTPS public key
serverHttpsHash: 'D9DE9E27A229B5355708A3672FB23237CC994A680B3570D242A91E36B4AE5BC9', // SHA256 of server HTTPS certificate
debugLevel: 0
}
*/
// Check the server certificate fingerprint
function onVerifyServer(clientName, certs) {
try { for (var i in certs) { if (certs[i].fingerprint.replace(/:/g, '') == settings.serverHttpsHash) { return; } } } catch (e) { }
if (serverhash != null) { console.log('Error: Failed to verify server certificate.'); return false; }
}
// Print a debug message
function debug(level, message) { if ((settings.debugLevel != null) && (settings.debugLevel >= level)) { console.log(message); } }
// Start the router, start by listening to the local port
function run(argv) {
console.log('MeshCentral Command v1.0');
var actionpath = 'meshaction.txt';
if (argv.length >= 2) { actionpath = argv[1]; }
// Load the action file
var actionfile = null;
try { actionfile = fs.readFileSync(actionpath); } catch (e) { }
if (actionfile == null) { console.log('Unable to load \"' + actionpath + '\". Create this file or specify the location as the first argument.'); process.exit(1); }
try { settings = JSON.parse(actionfile); } catch (e) { console.log(actionpath, e); process.exit(1); }
// Validate meshaction.txt
if (settings.action == null) { console.log('No \"action\" specified.'); process.exit(1); }
settings.action = settings.action.toLowerCase();
if (settings.action == 'route') {
if ((settings.localPort == null) || (typeof settings.localPort != 'number') || (settings.localPort < 0) || (settings.localPort > 65535)) { console.log('No or invalid \"localPort\" specified.'); process.exit(1); }
if ((settings.remoteNodeId == null) || (typeof settings.remoteNodeId != 'string')) { console.log('No or invalid \"remoteNodeId\" specified.'); process.exit(1); }
if ((settings.username == null) || (typeof settings.username != 'string')) { console.log('No or invalid \"username\" specified.'); process.exit(1); }
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified.'); process.exit(1); }
if ((settings.serverId == null) || (typeof settings.serverId != 'string') || (settings.serverId.length != 96)) { console.log('No or invalid \"serverId\" specified.'); process.exit(1); }
if ((settings.serverHttpsHash == null) || (typeof settings.serverHttpsHash != 'string') || (settings.serverHttpsHash.length != 96)) { console.log('No or invalid \"serverHttpsHash\" specified.'); process.exit(1); }
if ((settings.remotePort == null) || (typeof settings.remotePort != 'number') || (settings.remotePort < 0) || (settings.remotePort > 65535)) { console.log('No or invalid \"remotePort\" specified.'); process.exit(1); }
} else {
console.log('Invalid \"action\" specified.'); process.exit(1);
}
debug(1, "Settings: " + JSON.stringify(settings));
if (settings.serverUrl != null) { startRouter(); } else { discoverMeshServer(); }
}
// Starts the router
function startRouter() {
tcpserver = net.createServer(OnTcpClientConnected);
tcpserver.on('error', function (err) { console.log(err); process.exit(0); });
tcpserver.listen(settings.localPort, function () {
// We started listening.
if (settings.remoteName == null) {
console.log('Redirecting local port ' + settings.localPort + ' to remote port ' + settings.remotePort + '.');
} else {
console.log('Redirecting local port ' + settings.localPort + ' to ' + settings.remoteName + ':' + settings.remotePort + '.');
}
console.log('Press ctrl-c to terminal.');
// If settings has a "cmd", run it now.
//process.exec("notepad.exe");
});
}
// Called when a TCP connect is received on the local port. Launch a tunnel.
function OnTcpClientConnected(c) {
try {
// 'connection' listener
debug(1, 'Client connected');
c.on('end', function () { disconnectTunnel(this, this.websocket, 'Client closed'); });
c.pause();
try {
options = http.parseUri(settings.serverUrl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remoteNodeId + '&tcpport=' + settings.remotePort);
} catch (e) { console.log('Unable to parse \"serverUrl\".'); process.exit(1); }
options.checkServerIdentity = onVerifyServer;
c.websocket = http.request(options);
c.websocket.tcp = c;
c.websocket.tunneling = false;
c.websocket.upgrade = OnWebSocket;
c.websocket.on('error', function (msg) { console.log(msg); });
c.websocket.end();
} catch (e) { debug(2, e); }
}
// Disconnect both TCP & WebSocket connections and display a message.
function disconnectTunnel(tcp, ws, msg) {
if (ws != null) { try { ws.end(); } catch (e) { debug(2, e); } }
if (tcp != null) { try { tcp.end(); } catch (e) { debug(2, e); } }
debug(1, 'Tunnel disconnected: ' + msg);
}
// Called when the web socket gets connected
function OnWebSocket(msg, s, head) {
debug(1, 'Websocket connected');
s.on('data', function (msg) {
if (this.parent.tunneling == false) {
msg = msg.toString();
if (msg == 'c') {
this.parent.tunneling = true; this.pipe(this.parent.tcp); this.parent.tcp.pipe(this); debug(1, 'Tunnel active');
} else if ((msg.length > 6) && (msg.substring(0, 6) == 'error:')) {
console.log(msg.substring(6));
disconnectTunnel(this.tcp, this, msg.substring(6));
}
}
});
s.on('error', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket error'); });
s.on('close', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket closed'); });
s.parent = this;
}
// Try to discover the location of the mesh server
function discoverMeshServer() { console.log('Looking for server...'); discoveryInterval = setInterval(discoverMeshServerOnce, 5000); discoverMeshServerOnce(); }
// Try to discover the location of the mesh server only once
function discoverMeshServerOnce() {
var interfaces = os.networkInterfaces();
for (var adapter in interfaces) {
if (interfaces.hasOwnProperty(adapter)) {
for (var i = 0 ; i < interfaces[adapter].length; ++i) {
var addr = interfaces[adapter][i];
multicastSockets[i] = dgram.createSocket({ type: (addr.family == "IPv4" ? "udp4" : "udp6") });
multicastSockets[i].bind({ address: addr.address, exclusive: false });
if (addr.family == "IPv4") {
multicastSockets[i].addMembership(membershipIPv4);
//multicastSockets[i].setMulticastLoopback(true);
multicastSockets[i].once('message', OnMulticastMessage);
multicastSockets[i].send(settings.serverId, 16989, membershipIPv4);
}
}
}
}
}
// Called when a multicast packet is received
function OnMulticastMessage(msg, rinfo) {
var m = msg.toString().split('|');
if ((m.length == 3) && (m[0] == 'MeshCentral2') && (m[1] == settings.serverId)) {
settings.serverUrl = m[2].replace('%s', rinfo.address).replace('/agent.ashx', '/meshrelay.ashx');
console.log('Found server at ' + settings.serverUrl + '.');
if (discoveryInterval != null) { clearInterval(discoveryInterval); discoveryInterval = null; }
startRouter();
}
}
try { run(process.argv); } catch (e) { /*console.log(e);*/ }

View file

@ -59,7 +59,7 @@ CheckInstallAgent() {
DownloadAgent $url $meshid $machineid
fi
else
echo "MeshID is not correct, must be 64 HEX characters long."
echo "MeshID is not correct, must be 64 characters long."
fi
else
echo "URI and/or MeshID have not been specified, must be passed in as arguments."
@ -78,7 +78,7 @@ DownloadAgent() {
wget $url/meshagents?id=$machineid -q --no-check-certificate -O /usr/local/mesh/meshagent
if [ $? -eq 0 ]
then
echo "Mesh agent download."
echo "Mesh agent downloaded."
# TODO: We could check the meshagent sha256 hash, but best to authenticate the server.
chmod 755 /usr/local/mesh/meshagent
wget $url/meshsettings?id=$meshid -q --no-check-certificate -O /usr/local/mesh/meshagent.msh
@ -97,6 +97,7 @@ DownloadAgent() {
ln -s /usr/local/mesh/meshagent /etc/rc3.d/S20mesh
ln -s /usr/local/mesh/meshagent /etc/rc5.d/S20mesh
fi
echo "Mesh agent started."
else
echo "Unable to download mesh settings at: $url/meshsettings?id=$meshid."
fi