mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	add webrelay to websocket and meshctrl #6484
Signed-off-by: si458 <simonsmith5521@gmail.com>
This commit is contained in:
		
							parent
							
								
									545bf58e8d
								
							
						
					
					
						commit
						dbb5b4ba11
					
				
					 3 changed files with 99 additions and 2 deletions
				
			
		
							
								
								
									
										48
									
								
								meshctrl.js
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								meshctrl.js
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -16,7 +16,7 @@ var settings = {};
 | 
			
		|||
const crypto = require('crypto');
 | 
			
		||||
const args = require('minimist')(process.argv.slice(2));
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'listevents', 'logintokens', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'removedevice', 'editdevice', 'addlocaldevice', 'addamtdevice', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing', 'devicepower', 'indexagenterrorlog', 'agentdownload', 'report', 'grouptoast', 'groupmessage'];
 | 
			
		||||
const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'listevents', 'logintokens', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'removedevice', 'editdevice', 'addlocaldevice', 'addamtdevice', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing', 'devicepower', 'indexagenterrorlog', 'agentdownload', 'report', 'grouptoast', 'groupmessage', 'webrelay'];
 | 
			
		||||
if (args.proxy != null) { try { require('https-proxy-agent'); } catch (ex) { console.log('Missing module "https-proxy-agent", type "npm install https-proxy-agent" to install it.'); return; } }
 | 
			
		||||
 | 
			
		||||
if (args['_'].length == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +65,7 @@ if (args['_'].length == 0) {
 | 
			
		|||
    console.log("  Shell                       - Access command shell of a remote device.");
 | 
			
		||||
    console.log("  Upload                      - Upload a file to a remote device.");
 | 
			
		||||
    console.log("  Download                    - Download a file from a remote device.");
 | 
			
		||||
    console.log("  WebRelay                    - Creates a HTTP/HTTPS webrelay link for a remote device.");
 | 
			
		||||
    console.log("  DeviceOpenUrl               - Open a URL on a remote device.");
 | 
			
		||||
    console.log("  DeviceMessage               - Open a message box on a remote device.");
 | 
			
		||||
    console.log("  DeviceToast                 - Display a toast notification on a remote device.");
 | 
			
		||||
| 
						 | 
				
			
			@ -277,6 +278,12 @@ if (args['_'].length == 0) {
 | 
			
		|||
            else { ok = true; }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case 'webrelay': {
 | 
			
		||||
            if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); }
 | 
			
		||||
            else if (args.type == null) { console.log(winRemoveSingleQuotes("Missing protocol type, use --type [http,https]")); }
 | 
			
		||||
            else { ok = true; }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case 'deviceopenurl': {
 | 
			
		||||
            if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); }
 | 
			
		||||
            else if (args.openurl == null) { console.log("Remote URL, use --openurl [url] specify the link to open."); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1015,6 +1022,21 @@ if (args['_'].length == 0) {
 | 
			
		|||
                        console.log("  --target [localpath]   - The local path to download the file to.");
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    case 'webrelay': {
 | 
			
		||||
                        console.log("Generate a webrelay URL to access a HTTP/HTTPS service on a remote device, Example usages:\r\n");
 | 
			
		||||
                        console.log(winRemoveSingleQuotes("  MeshCtrl WebRelay --id 'deviceid' --type http --port 80"));
 | 
			
		||||
                        console.log(winRemoveSingleQuotes("  MeshCtrl WebRelay --id 'deviceid' --type https --port 443"));
 | 
			
		||||
                        console.log("\r\nRequired arguments:\r\n");
 | 
			
		||||
                        if (process.platform == 'win32') {
 | 
			
		||||
                            console.log("  --id [deviceid]     - The device identifier.");
 | 
			
		||||
                        } else {
 | 
			
		||||
                            console.log("  --id '[deviceid]'     - The device identifier.");
 | 
			
		||||
                        }
 | 
			
		||||
                        console.log("  --type [http,https]   - Type of relay from remote device, http or https.");
 | 
			
		||||
                        console.log("\r\nOptional arguments:\r\n");
 | 
			
		||||
                        console.log("  --port [portnumber]   - Set alternative port for http or https, default is 80 for http and 443 for https.");
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    case 'deviceopenurl': {
 | 
			
		||||
                        console.log("Open a web page on a remote device, Example usages:\r\n");
 | 
			
		||||
                        console.log(winRemoveSingleQuotes("  MeshCtrl DeviceOpenUrl --id 'deviceid' --openurl http://meshcentral.com"));
 | 
			
		||||
| 
						 | 
				
			
			@ -1804,6 +1826,29 @@ function serverConnect() {
 | 
			
		|||
                req.end()
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'webrelay': {
 | 
			
		||||
                var protocol = null;
 | 
			
		||||
                if (args.type != null) {
 | 
			
		||||
                    if (args.type == 'http') {
 | 
			
		||||
                        protocol = 1;
 | 
			
		||||
                    } else if (args.type == 'https') {
 | 
			
		||||
                        protocol = 2;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        console.log("Unknown protocol type: " + args.type); process.exit(1);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                var port = null;
 | 
			
		||||
                if (typeof args.port == 'number') {
 | 
			
		||||
                    if ((args.port < 1) || (args.port > 65535)) { console.log("Port number must be between 1 and 65535."); process.exit(1); }
 | 
			
		||||
                    port = args.port;
 | 
			
		||||
                } else if (protocol == 1) {
 | 
			
		||||
                    port = 80;
 | 
			
		||||
                } else if (protocol == 2) {
 | 
			
		||||
                    port = 443;
 | 
			
		||||
                }
 | 
			
		||||
                ws.send(JSON.stringify({ action: 'webrelay', nodeid: args.id, port: port, appid: protocol, responseid: 'meshctrl' }));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'devicesharing': {
 | 
			
		||||
                if (args.add) {
 | 
			
		||||
                    if (args.add.length == 0) { console.log("Invalid guest name."); process.exit(1); }
 | 
			
		||||
| 
						 | 
				
			
			@ -2208,6 +2253,7 @@ function serverConnect() {
 | 
			
		|||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 'createDeviceShareLink':
 | 
			
		||||
            case 'webrelay':
 | 
			
		||||
                if (data.result == 'OK') {
 | 
			
		||||
                    if (data.publicid) { console.log('ID: ' + data.publicid); }
 | 
			
		||||
                    console.log('URL: ' + data.url);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								meshuser.js
									
										
									
									
									
								
							
							
						
						
									
										42
									
								
								meshuser.js
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2948,6 +2948,48 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
 | 
			
		|||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            case 'webrelay': 
 | 
			
		||||
                {
 | 
			
		||||
                    if (common.validateString(command.nodeid, 8, 128) == false) { err = 'Invalid node id'; } // Check the nodeid
 | 
			
		||||
                    else if (command.nodeid.indexOf('/') == -1) { command.nodeid = 'node/' + domain.id + '/' + command.nodeid; }
 | 
			
		||||
                    else if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
 | 
			
		||||
                    else if ((command.port != null) && (common.validateInt(command.port, 1, 65535) == false)) { err = 'Invalid port value'; } // Check the port if present
 | 
			
		||||
                    else {
 | 
			
		||||
                        if (command.nodeid.split('/').length == 1) { command.nodeid = 'node/' + domain.id + '/' + command.nodeid; }
 | 
			
		||||
                        var snode = command.nodeid.split('/');
 | 
			
		||||
                        if ((snode.length != 3) || (snode[0] != 'node') || (snode[1] != domain.id)) { err = 'Invalid node id'; }
 | 
			
		||||
                    }
 | 
			
		||||
                    // Handle any errors
 | 
			
		||||
                    if (err != null) {
 | 
			
		||||
                        if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'webrelay', responseid: command.responseid, result: err })); } catch (ex) { } }
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    // Get the device rights
 | 
			
		||||
                    parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
 | 
			
		||||
                        // If node not found or we don't have remote control, reject.
 | 
			
		||||
                        if (node == null) {
 | 
			
		||||
                            if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'webrelay', responseid: command.responseid, result: 'Invalid node id' })); } catch (ex) { } }
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        var relayid = null;
 | 
			
		||||
                        var addr = null;
 | 
			
		||||
                        if (node.mtype == 3) { // Setup device relay if needed
 | 
			
		||||
                            var mesh = parent.meshes[node.meshid];
 | 
			
		||||
                            if (mesh && mesh.relayid) { relayid = mesh.relayid; addr = node.host; }
 | 
			
		||||
                        }
 | 
			
		||||
                        var webRelayDns = (args.relaydns != null) ? args.relaydns[0] : obj.getWebServerName(domain, req);
 | 
			
		||||
                        var webRelayPort = ((args.relaydns != null) ? ((typeof args.aliasport == 'number') ? args.aliasport : args.port) : ((parent.webrelayserver != null) ? ((typeof args.relayaliasport == 'number') ? args.relayaliasport : parent.webrelayserver.port) : 0));
 | 
			
		||||
                        if (webRelayPort == 0) { try { ws.send(JSON.stringify({ action: 'webrelay',  responseid: command.responseid, result: 'WebRelay Disabled' })); return; } catch (ex) { } }
 | 
			
		||||
                        const authRelayCookie = parent.parent.encodeCookie({ ruserid: user._id, x: req.session.x }, parent.parent.loginCookieEncryptionKey);
 | 
			
		||||
                        var url = 'https://' + webRelayDns + ':' + webRelayPort + '/control-redirect.ashx?n=' + command.nodeid + '&p=' + command.port + '&appid=' + command.appid + '&c=' + authRelayCookie;
 | 
			
		||||
                        if (addr != null) { url += '&addr=' + addr; }
 | 
			
		||||
                        if (relayid != null) { url += '&relayid=' + relayid }
 | 
			
		||||
                        command.url = url;
 | 
			
		||||
                        if (command.responseid != null) { command.result = 'OK'; }
 | 
			
		||||
                        try { ws.send(JSON.stringify(command)); } catch (ex) { }
 | 
			
		||||
                    });
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            case 'runcommands':
 | 
			
		||||
                {
 | 
			
		||||
                    if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8036,6 +8036,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
 | 
			
		|||
                                            parent.debug('web', 'Invalid login, asking for email validation');
 | 
			
		||||
                                            try { ws.send(JSON.stringify({ action: 'close', cause: 'emailvalidation', msg: 'emailvalidationrequired', email2fa: email2fa, sms2fa: sms2fa, msg2fa: msg2fa, email2fasent: true })); ws.close(); } catch (e) { }
 | 
			
		||||
                                        } else {
 | 
			
		||||
                                            req.session.userid = user._id;
 | 
			
		||||
                                            req.session.ip = req.clientIp;
 | 
			
		||||
                                            setSessionRandom(req);
 | 
			
		||||
                                            func(ws, req, domain, user, null, authData);
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -8051,6 +8054,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
 | 
			
		|||
                                try { ws.send(JSON.stringify({ action: 'close', cause: 'emailvalidation', msg: 'emailvalidationrequired', email2fa: email2fa, sms2fa: sms2fa, msg2fa: msg2fa, email2fasent: true })); ws.close(); } catch (e) { }
 | 
			
		||||
                            } else {
 | 
			
		||||
                                // We are authenticated
 | 
			
		||||
                                req.session.userid = user._id;
 | 
			
		||||
                                req.session.ip = req.clientIp;
 | 
			
		||||
                                setSessionRandom(req);
 | 
			
		||||
                                func(ws, req, domain, user);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			@ -8180,6 +8186,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
 | 
			
		|||
                                parent.debug('web', 'Invalid login, asking for email validation');
 | 
			
		||||
                                try { ws.send(JSON.stringify({ action: 'close', cause: 'emailvalidation', msg: 'emailvalidationrequired', email2fa: email2fa, email2fasent: true })); ws.close(); } catch (e) { }
 | 
			
		||||
                            } else {                                
 | 
			
		||||
                                req.session.userid = user._id;
 | 
			
		||||
                                req.session.ip = req.clientIp;
 | 
			
		||||
                                setSessionRandom(req);
 | 
			
		||||
                                func(ws, req, domain, user);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue