diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index ac92e729..5c5966b0 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index c9c58f9f..b8c3ad4b 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index 87ed94df..12ebd898 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index dcad7136..1e2b303b 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 5b92436f..2658f07b 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 79e1cb6b..a71ddd46 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshagent_arm b/agents/meshagent_arm index 224bd165..af5ea1be 100644 Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ diff --git a/agents/meshagent_arm-linaro b/agents/meshagent_arm-linaro index 3bb448fe..6562df75 100644 Binary files a/agents/meshagent_arm-linaro and b/agents/meshagent_arm-linaro differ diff --git a/agents/meshagent_mips b/agents/meshagent_mips index 7d37ab0e..4e40d71f 100644 Binary files a/agents/meshagent_mips and b/agents/meshagent_mips differ diff --git a/agents/meshagent_osx-x86-64 b/agents/meshagent_osx-x86-64 index 9028008f..f7f09497 100644 Binary files a/agents/meshagent_osx-x86-64 and b/agents/meshagent_osx-x86-64 differ diff --git a/agents/meshagent_pogo b/agents/meshagent_pogo index d1295fe7..deda2c94 100644 Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ diff --git a/agents/meshagent_poky b/agents/meshagent_poky index b2949596..d3a797d0 100644 Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ diff --git a/agents/meshagent_poky64 b/agents/meshagent_poky64 index c0554e44..7c8e0cf1 100644 Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ diff --git a/agents/meshagent_x86 b/agents/meshagent_x86 index 9c410ccd..58f6bbcb 100644 Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ diff --git a/agents/meshagent_x86-64 b/agents/meshagent_x86-64 index c025a1ce..b712f54d 100644 Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ diff --git a/agents/meshagent_x86-64_nokvm b/agents/meshagent_x86-64_nokvm index af1a33d6..efaad834 100644 Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ diff --git a/agents/meshagent_x86_nokvm b/agents/meshagent_x86_nokvm index 34970a27..091ee451 100644 Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ diff --git a/agents/meshinstall-linux.sh b/agents/meshinstall-linux.sh index e4dd190d..2a89bcf2 100644 --- a/agents/meshinstall-linux.sh +++ b/agents/meshinstall-linux.sh @@ -95,13 +95,13 @@ DownloadAgent() { mkdir -p /usr/local/mesh cd /usr/local/mesh echo "Downloading Mesh agent #$machineid..." - wget $url/meshagents?id=$machineid -q --no-check-certificate -O /usr/local/mesh/meshagent + wget $url/meshagents?id=$machineid --no-check-certificate {{{noproxy}}}-O /usr/local/mesh/meshagent # If it did not work, try again using http if [ $? != 0 ] then url=${url/"https://"/"http://"} - wget $url/meshagents?id=$machineid -q -O /usr/local/mesh/meshagent + wget $url/meshagents?id=$machineid {{{noproxy}}}-O /usr/local/mesh/meshagent fi if [ $? -eq 0 ] @@ -109,12 +109,12 @@ DownloadAgent() { 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 + wget $url/meshsettings?id=$meshid --no-check-certificate {{{noproxy}}}-O /usr/local/mesh/meshagent.msh # If it did not work, try again using http if [ $? -ne 0 ] then - wget $url/meshsettings?id=$meshid -q -O /usr/local/mesh/meshagent.msh + wget $url/meshsettings?id=$meshid {{{noproxy}}}-O /usr/local/mesh/meshagent.msh fi if [ $? -eq 0 ] @@ -141,7 +141,7 @@ DownloadAgent() { if [ $starttype -eq 3 ] then # initd - wget $url/meshagents?script=2 -q --no-check-certificate -O /etc/init.d/meshagent + wget $url/meshagents?script=2 --no-check-certificate {{{noproxy}}}-O /etc/init.d/meshagent chmod +x /etc/init.d/meshagent update-rc.d meshagent defaults # creates symlinks for rc.d service meshagent start diff --git a/meshagent.js b/meshagent.js index e6ac32c6..45565a8c 100644 --- a/meshagent.js +++ b/meshagent.js @@ -759,29 +759,29 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (nodes.length != 1) return; var device = nodes[0]; if (device.agent) { - var changes = [], change = 0; + var changes = [], change = 0, log = 0; //if (command.users) { console.log(command.users); } // Check if anything changes - if (command.name && (command.name != device.name)) { change = 1; device.name = command.name; changes.push('name'); } - if ((command.caps != null) && (device.agent.core != command.value)) { if ((command.value == null) && (device.agent.core != null)) { delete device.agent.core; } else { device.agent.core = command.value; } change = 1; changes.push('agent core'); } - if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; changes.push('agent capabilities'); } // Allow Javascript on the agent to change all capabilities except console and javascript support - if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; changes.push('os desc'); } + if (command.name && (command.name != device.name)) { change = 1; log = 1; device.name = command.name; changes.push('name'); } + if ((command.caps != null) && (device.agent.core != command.value)) { if ((command.value == null) && (device.agent.core != null)) { delete device.agent.core; } else { device.agent.core = command.value; } change = 1; } // Don't save this as an event to the db. + if ((command.caps != null) && ((device.agent.caps & 0xFFFFFFE7) != (command.caps & 0xFFFFFFE7))) { device.agent.caps = ((device.agent.caps & 24) + (command.caps & 0xFFFFFFE7)); change = 1; } // Allow Javascript on the agent to change all capabilities except console and javascript support, Don't save this as an event to the db. + if ((command.osdesc != null) && (device.osdesc != command.osdesc)) { device.osdesc = command.osdesc; change = 1; log = 1; changes.push('os desc'); } if (command.intelamt) { if (!device.intelamt) { device.intelamt = {}; } - if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; } - if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { changes.push('AMT state'); device.intelamt.state = command.intelamt.state; change = 1; } + if ((command.intelamt.ver != null) && (device.intelamt.ver != command.intelamt.ver)) { changes.push('AMT version'); device.intelamt.ver = command.intelamt.ver; change = 1; log = 1; } + if ((command.intelamt.state != null) && (device.intelamt.state != command.intelamt.state)) { changes.push('AMT state'); device.intelamt.state = command.intelamt.state; change = 1; log = 1; } if ((command.intelamt.flags != null) && (device.intelamt.flags != command.intelamt.flags)) { if (device.intelamt.flags) { changes.push('AMT flags (' + device.intelamt.flags + ' --> ' + command.intelamt.flags + ')'); } else { changes.push('AMT flags (' + command.intelamt.flags + ')'); } - device.intelamt.flags = command.intelamt.flags; change = 1; + device.intelamt.flags = command.intelamt.flags; change = 1; log = 1; } - if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { changes.push('AMT host'); device.intelamt.host = command.intelamt.host; change = 1; } - if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.uuid; change = 1; } + if ((command.intelamt.host != null) && (device.intelamt.host != command.intelamt.host)) { changes.push('AMT host'); device.intelamt.host = command.intelamt.host; change = 1; log = 1; } + if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.uuid; change = 1; log = 1; } } - if ((command.users != null) && (device.users != command.users)) { device.users = command.users; change = 1; } // Would be nice not to save this to the db. + if ((command.users != null) && (device.users != command.users)) { device.users = command.users; change = 1; } // Don't save this to the db. if (mesh.mtype == 2) { - if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); } + if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; log = 1; changes.push('host'); } // TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match. } @@ -793,9 +793,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id }; if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } - if ((obj.agentInfo.capabilities & 0x20) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes + if ((log == 0) || (obj.agentInfo.capabilities & 0x20) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes var device2 = obj.common.Clone(device); - if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this. event.node = device; obj.parent.parent.DispatchEvent(['*', device.meshid], obj, event); } diff --git a/meshcentral.js b/meshcentral.js index 59288545..037173b9 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -59,7 +59,7 @@ function CreateMeshCentralServer(config, args) { obj.serverKey = Buffer.from(obj.crypto.randomBytes(48), 'binary'); obj.loginCookieEncryptionKey = null; obj.serverSelfWriteAllowed = true; - obj.taskLimiter = obj.common.createTaskLimiterQueue(10, 20, 60); // This is a task limiter queue to smooth out server work. + obj.taskLimiter = obj.common.createTaskLimiterQueue(30, 20, 60); // This is a task limiter queue to smooth out server work. try { obj.currentVer = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'package.json'), 'utf8')).version; } catch (e) { } // Fetch server version // Setup the default configuration and files paths @@ -95,7 +95,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. // 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', 'dbexportmin', 'dbimport', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'swarmallowedip', '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', 'dbexportmin', 'dbimport', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', '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; } } 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. @@ -251,6 +251,9 @@ function CreateMeshCentralServer(config, args) { if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; } obj.config.domains[i].id = i; if (typeof obj.config.domains[i].userallowedip == 'string') { if (obj.config.domains[i].userallowedip == '') { obj.config.domains[i].userallowedip = null; } else { obj.config.domains[i].userallowedip = obj.config.domains[i].userallowedip.split(','); } } + if (typeof obj.config.domains[i].userblockedip == 'string') { if (obj.config.domains[i].userblockedip == '') { obj.config.domains[i].userblockedip = null; } else { obj.config.domains[i].userblockedip = obj.config.domains[i].userallowedip.split(','); } } + if (typeof obj.config.domains[i].agentallowedip == 'string') { if (obj.config.domains[i].agentallowedip == '') { obj.config.domains[i].agentallowedip = null; } else { obj.config.domains[i].agentallowedip = obj.config.domains[i].agentallowedip.split(','); } } + if (typeof obj.config.domains[i].agentblockedip == 'string') { if (obj.config.domains[i].agentblockedip == '') { obj.config.domains[i].agentblockedip = null; } else { obj.config.domains[i].agentblockedip = obj.config.domains[i].agentblockedip.split(','); } } } // Log passed arguments into Windows Service Log @@ -268,6 +271,9 @@ function CreateMeshCentralServer(config, args) { if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80; 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.userblockedip == 'string') { if (obj.args.userblockedip == '') { obj.args.userblockedip = null; } else { obj.args.userblockedip = obj.args.userblockedip.split(','); } } + if (typeof obj.args.agentallowedip == 'string') { if (obj.args.agentallowedip == '') { obj.args.agentallowedip = null; } else { obj.args.agentallowedip = obj.args.agentallowedip.split(','); } } + if (typeof obj.args.agentblockedip == 'string') { if (obj.args.agentblockedip == '') { obj.args.agentblockedip = null; } else { obj.args.agentblockedip = obj.args.agentblockedip.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 (obj.args.debug == true) obj.debugLevel = 1; @@ -1053,7 +1059,8 @@ function CreateMeshCentralServer(config, args) { var stream = null; try { stream = obj.fs.createReadStream(scriptpath); - stream.on('data', function (data) { this.hash.update(data, 'binary'); }); + stream.xdata = ''; + stream.on('data', function (data) { this.hash.update(data, 'binary'); this.xdata += data; }); stream.on('error', function (data) { // If there is an error reading this file, make sure this agent is not in the agent table if (obj.meshAgentInstallScripts[this.info.id] != null) { delete obj.meshAgentInstallScripts[this.info.id]; } @@ -1063,6 +1070,7 @@ function CreateMeshCentralServer(config, args) { obj.meshAgentInstallScripts[this.info.id] = obj.common.Clone(this.info); obj.meshAgentInstallScripts[this.info.id].hash = this.hash.digest('hex'); obj.meshAgentInstallScripts[this.info.id].path = this.agentpath; + obj.meshAgentInstallScripts[this.info.id].data = this.xdata; obj.meshAgentInstallScripts[this.info.id].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + obj.args.port + '/meshagents?script=' + this.info.id; var stats = null; try { stats = obj.fs.statSync(this.agentpath); } catch (e) { } diff --git a/public/scripts/agent-desktop-0.0.2.js b/public/scripts/agent-desktop-0.0.2.js index bf4b9c30..7558892d 100644 --- a/public/scripts/agent-desktop-0.0.2.js +++ b/public/scripts/agent-desktop-0.0.2.js @@ -180,7 +180,16 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { obj.ProcessDataEx = function (str) { if (obj.debugmode > 1) { console.log("KRecv(" + str.length + "): " + rstr2hex(str.substring(0, Math.min(str.length, 40)))); } if (str.length < 4) return; - var cmdmsg = null, X = 0, Y = 0, command = ReadShort(str, 0), cmdsize = ReadShort(str, 2); + var cmdmsg = null, X = 0, Y = 0, command = ReadShort(str, 0), cmdsize = ReadShort(str, 2), jumboAdd = 0; + if ((command == 27) && (cmdsize == 8)) { + // Jumbo packet + if (str.length < 12) return; + command = ReadShort(str, 8) + cmdsize = ReadInt(str, 4); + str = str.substring(8); + jumboAdd = 8; + //console.log('JUMBO', command, cmdsize, str.length); + } if ((cmdsize != str.length) && (obj.debugmode > 0)) { console.log(cmdsize, str.length, cmdsize == str.length); } if ((command >= 18) && (command != 65)) { console.error("Invalid KVM command " + command + " of size " + cmdsize); console.log("Invalid KVM data", str.length, str, rstr2hex(str)); return; } if (cmdsize > str.length) { console.error("KVM invalid command size", cmdsize, str.length); return; } @@ -254,7 +263,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { if (str[0] != '.') { console.log(str); alert('KVM: ' + str); } else { console.log('KVM: ' + str.substring(1)); } break; } - return cmdsize; + return cmdsize + jumboAdd; } // Keyboard and Mouse I/O. diff --git a/sample-config.json b/sample-config.json index 0771250c..3e30ef31 100644 --- a/sample-config.json +++ b/sample-config.json @@ -15,7 +15,10 @@ "_WebRTC": false, "_ClickOnce": false, "_SelfUpdate": true, - "_UserAllowedIP": "127.0.0.1,::1,192.168.0.100", + "_UserAllowedIP": "127.0.0.1,192.168.1.0/24", + "_UserBlockedIP": "127.0.0.1,::1,192.168.0.100", + "_AgentAllowedIP": "192.168.0.100/24", + "_AgentBlockedIP": "127.0.0.1,::1", "_LocalDiscovery": { "name": "Local server name", "info": "Information about this server" }, "_TlsOffload": true, "_MpsTlsOffload": true, @@ -31,8 +34,12 @@ "NewAccounts": 1, "Footer": "Twitter", "_CertUrl": "https://192.168.2.106:443/", + "_PasswordRequirements": { "min": 8, "max": 128, "upper": 1, "lower": 1, "numeric": 1, "nonalpha": 1 }, + "_AgentNoProxy": true, "_UserAllowedIP": "127.0.0.1,192.168.1.0/24", - "_PasswordRequirements": { "min": 8, "max": 128, "upper": 1, "lower": 1, "numeric": 1, "nonalpha": 1 } + "_UserBlockedIP": "127.0.0.1,::1,192.168.0.100", + "_AgentAllowedIP": "192.168.0.100/24", + "_AgentBlockedIP": "127.0.0.1,::1" }, "customer1": { "DNS": "customer1.myserver.com", diff --git a/views/default-min.handlebars b/views/default-min.handlebars index 6ceb3519..581046a1 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default-mobile-min.handlebars b/views/default-mobile-min.handlebars index 6dbcc5b3..f646ef07 100644 --- a/views/default-mobile-min.handlebars +++ b/views/default-mobile-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}
\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}
\ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index b01a8202..0e912280 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2310,14 +2310,15 @@ var servername = serverinfo.name; if ((servername == 'un-configured') || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name. + var noProxy = ((features & 0x2000) != 0)?'--no-proxy ':''; // Server asked that agent be installed to preferably not use a HTTP proxy. if (serverinfo.https == true) { var portStr = (serverinfo.port == 443)?'':(":" + serverinfo.port); - Q('agins_linux_area').value = "wget https://" + servername + portStr + "/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + servername + portStr + " '" + meshid.split('/')[2] + "'\r\n"; - Q('agins_linux_area_un').value = "wget https://" + servername + portStr + "/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n"; + Q('agins_linux_area').value = "wget https://" + servername + portStr + "/meshagents?script=1 " + noProxy + "--no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + servername + portStr + " '" + meshid.split('/')[2] + "'\r\n"; + Q('agins_linux_area_un').value = "wget https://" + servername + portStr + "/meshagents?script=1 " + noProxy + "--no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n"; } else { var portStr = (serverinfo.port == 80)?'':(":" + serverinfo.port); - Q('agins_linux_area').value = "wget http://" + servername + portStr + "/meshagents?script=1 -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + servername + portStr + " '" + meshid.split('/')[2] + "'\r\n"; - Q('agins_linux_area_un').value = "wget http://" + servername + portStr + "/meshagents?script=1 -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n"; + Q('agins_linux_area').value = "wget http://" + servername + portStr + "/meshagents?script=1 " + noProxy + "-O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + servername + portStr + " '" + meshid.split('/')[2] + "'\r\n"; + Q('agins_linux_area_un').value = "wget http://" + servername + portStr + "/meshagents?script=1 " + noProxy + "-O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n"; } Q('aginsSelect').focus(); addAgentToMeshClick(); diff --git a/webserver.js b/webserver.js index 9830b440..8f895605 100644 --- a/webserver.js +++ b/webserver.js @@ -74,9 +74,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.users = {}; obj.meshes = {}; obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users + obj.agentAllowedIp = args.agentallowedip; // List of allowed IP addresses for agents + obj.agentBlockedIp = args.agentblockedip; // List of blocked IP addresses for agents obj.tlsSniCredentials = null; obj.dnsDomains = {}; - //obj.agentConnCount = 0; // Mesh Rights const MESHRIGHT_EDITMESH = 1; @@ -268,15 +269,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { }; */ - // Check if the source IP address is allowed for a given allowed list, return false if not - function checkUserIpAddressEx(req, res, allowedIpList) { - if (allowedIpList == null) { return true; } + // Check if the source IP address is in the IP list, return false if not. + function checkIpAddressEx(req, res, ipList, closeIfThis) { try { var ip; if (req.connection) { // HTTP(S) request ip = req.ip; - if (ip) { for (var i = 0; i < allowedIpList.length; i++) { if (require('ipcheck').match(ip, allowedIpList[i])) { return true; } } } - res.sendStatus(401); + if (ip) { for (var i = 0; i < ipList.length; i++) { if (require('ipcheck').match(ip, ipList[i])) { if (closeIfThis === true) { res.sendStatus(401); } return true; } } } + if (closeIfThis === false) { res.sendStatus(401); } } else if (req._socket) { // WebSocket request ip = req._socket.remoteAddress; @@ -284,18 +284,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // This is not done automatically for web socket like it's done for HTTP requests. if ((obj.args.tlsoffload) && (res.headers['x-forwarded-for']) && ((obj.args.tlsoffload === true) || (obj.args.tlsoffload === ip) || (('::ffff:') + obj.args.tlsoffload === ip))) { ip = res.headers['x-forwarded-for']; } - if (ip) { for (var i = 0; i < allowedIpList.length; i++) { if (require('ipcheck').match(ip, allowedIpList[i])) { return true; } } } - try { req.close(); } catch (e) { } + if (ip) { for (var i = 0; i < ipList.length; i++) { if (require('ipcheck').match(ip, ipList[i])) { if (closeIfThis === true) { try { req.close(); } catch (e) { } } return true; } } } + if (closeIfThis === false) { try { req.close(); } catch (e) { } } } - } catch (e) { console.log(e); } + } catch (e) { console.log(e); } // Should never happen return false; } // Check if the source IP address is allowed, return domain if allowed function checkUserIpAddress(req, res) { - if (checkUserIpAddressEx(req, res, obj.userAllowedIp) == false) { return null; } + if ((obj.userBlockedIp != null) && (checkIpAddressEx(req, res, obj.userBlockedIp, true) == true)) { return null; } + if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) == false)) { return null; } const domain = (req.url ? getDomain(req) : getDomain(res)); - if (checkUserIpAddressEx(req, res, domain.userallowedip) == false) { return null; } + if ((domain.userblockedip != null) && (checkIpAddressEx(req, res, domain.userblockedip, true) == true)) { return null; } + if ((domain.userallowedip != null) && (checkIpAddressEx(req, res, domain.userallowedip, false) == false)) { return null; } + return domain; + } + + // Check if the source IP address is allowed, return domain if allowed + function checkAgentIpAddress(req, res) { + if ((obj.agentBlockedIp != null) && (checkIpAddressEx(req, res, obj.agentBlockedIp, null) == true)) { return null; } + if ((obj.agentAllowedIp != null) && (checkIpAddressEx(req, res, obj.agentAllowedIp, null) == false)) { return null; } + const domain = (req.url ? getDomain(req) : getDomain(res)); + if ((domain.agentblockedip != null) && (checkIpAddressEx(req, res, domain.agentblockedip, null) == true)) { return null; } + if ((domain.agentallowedip != null) && (checkIpAddressEx(req, res, domain.agentallowedip, null) == false)) { return null; } return domain; } @@ -796,6 +808,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.lanonly == true || obj.args.mpsport == 0) { features += 0x0400; } // No CIRA if ((obj.parent.serverSelfWriteAllowed == true) && (user != null) && (user.siteadmin == 0xFFFFFFFF)) { features += 0x0800; } // Server can self-write (Allows self-update) if ((domain.auth != 'sspi') && (obj.parent.certificates.CommonName != 'un-configured') && (obj.args.lanonly !== true) && (obj.args.nousers !== true)) { features += 0x1000; } // 2-step login supported + if (domain.agentnoproxy === true) { features += 0x2000; } // Indicates that agents should be installed without using a HTTP proxy // Create a authentication cookie const authCookie = obj.parent.encodeCookie({ userid: user._id, domainid: domain.id }, obj.parent.loginCookieEncryptionKey); @@ -909,14 +922,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Returns the mesh server root certificate function handleRootCertRequest(req, res) { - if (checkUserIpAddressEx(req, res, obj.userAllowedIp) === false) { return; } // Check server-wide IP filter only. + if (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false) { return; } // Check server-wide IP filter only. res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + certificates.RootName + '.cer' }); res.send(Buffer.from(getRootCertBase64(), 'base64')); } // Returns an mescript for Intel AMT configuration function handleMeScriptRequest(req, res) { - if (checkUserIpAddressEx(req, res, obj.userAllowedIp) === false) { return; } // Check server-wide IP filter only. + if (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false) { return; } // Check server-wide IP filter only. if (req.query.type == 1) { var filename = 'cira_setup.mescript'; res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + filename }); @@ -1631,6 +1644,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + obj.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; } if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; } if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; } + if (domain.agentnoproxy === true) { meshsettings += "ignoreProxyFile=1\r\n"; } res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + argentInfo.rname }); obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe }); @@ -1640,7 +1654,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var scriptInfo = obj.parent.meshAgentInstallScripts[req.query.script]; if (scriptInfo == null) { res.sendStatus(404); return; } res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=' + scriptInfo.rname }); - res.sendFile(scriptInfo.path); + res.send(scriptInfo.data.split('{{{noproxy}}}').join((domain.agentnoproxy === true)?'--no-proxy ':'')); } else if (req.query.meshcmd != null) { // Send meshcmd for a specific platform back var agentid = parseInt(req.query.meshcmd); @@ -1850,6 +1864,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.lanonly != true) { meshsettings += "MeshServer=ws" + (obj.args.notls ? '' : 's') + "://" + obj.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "agent.ashx\r\n"; } else { meshsettings += "MeshServer=local"; } if (req.query.tag != null) { meshsettings += "Tag=" + req.query.tag + "\r\n"; } if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += "InstallFlags=" + req.query.installflags + "\r\n"; } + if (domain.agentnoproxy === true) { meshsettings += "ignoreProxyFile=1\r\n"; } res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' }); res.send(meshsettings); @@ -1973,14 +1988,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Receive mesh agent connections obj.app.ws(url + 'agent.ashx', function (ws, req) { - //console.log(++obj.agentConnCount); - /* - var ip, port, type; - if (req.connection) { ip = req.connection.remoteAddress; port = req.connection.remotePort; type = 1; } // HTTP(S) request - else if (req._socket) { ip = req._socket.remoteAddress; port = req._socket.remotePort; type = 2; } // WebSocket request - console.log('AgentConnect', ip, port, type); - */ - try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, getDomain(req)); } catch (e) { console.log(e); } + var domain = checkAgentIpAddress(ws, req); + if (domain == null) { Debug(1, 'Got agent connection from blocked IP address ' + ws._socket.remoteAddress + ', holding.'); return; } + // console.log('Agent connect: ' + ws._socket.remoteAddress); + try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); } }); // Creates a login token using the user/pass that is passed in as URL arguments.