Added full agent ping/pong support on RDP sessions.

This commit is contained in:
Ylian Saint-Hilaire 2022-05-05 13:17:34 -07:00
parent 4ce9e09e91
commit 93e8f2cdcf
2 changed files with 177 additions and 152 deletions

View File

@ -116,7 +116,16 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
obj.relaySocket.resume(); obj.relaySocket.resume();
} }
} else { } else {
if (typeof data == 'string') return; // Only process binary data, this will include ping/ping if (typeof data == 'string') {
// Forward any ping/pong commands to the browser
var cmd = null;
try { cmd = JSON.parse(data); } catch (ex) { }
if ((cmd != null) && (cmd.ctrlChannel == '102938')) {
if (cmd.type == 'ping') { send(['ping']); }
else if (cmd.type == 'pong') { send(['pong']); }
}
return;
}
obj.wsClient._socket.pause(); obj.wsClient._socket.pause();
try { try {
obj.relaySocket.write(data, function () { obj.relaySocket.write(data, function () {
@ -280,6 +289,8 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
case 'wheel': { if (rdpClient) { rdpClient.sendWheelEvent(msg[1], msg[2], msg[3], msg[4]); } break; } case 'wheel': { if (rdpClient) { rdpClient.sendWheelEvent(msg[1], msg[2], msg[3], msg[4]); } break; }
case 'scancode': { if (rdpClient) { rdpClient.sendKeyEventScancode(msg[1], msg[2]); } break; } case 'scancode': { if (rdpClient) { rdpClient.sendKeyEventScancode(msg[1], msg[2]); } break; }
case 'unicode': { if (rdpClient) { rdpClient.sendKeyEventUnicode(msg[1], msg[2]); } break; } case 'unicode': { if (rdpClient) { rdpClient.sendKeyEventUnicode(msg[1], msg[2]); } break; }
case 'ping': { try { obj.wsClient.send('{"ctrlChannel":102938,"type":"ping"}'); } catch (ex) { } break; }
case 'pong': { try { obj.wsClient.send('{"ctrlChannel":102938,"type":"pong"}'); } catch (ex) { } break; }
case 'disconnect': { obj.close(); break; } case 'disconnect': { obj.close(); break; }
} }
} catch (ex) { } catch (ex) {
@ -416,12 +427,13 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
const protocol = (args.tlsoffload) ? 'ws' : 'wss'; const protocol = (args.tlsoffload) ? 'ws' : 'wss';
var domainadd = ''; var domainadd = '';
if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' } if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?noping=1&p=11&auth=' + obj.xcookie; // Protocol 11 is Web-SSH const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?p=11&auth=' + obj.xcookie; // Protocol 11 is Web-SSH
parent.parent.debug('relay', 'SSH: Connection websocket to ' + url); parent.parent.debug('relay', 'SSH: Connection websocket to ' + url);
obj.wsClient = new WebSocket(url, options); obj.wsClient = new WebSocket(url, options);
obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); }); obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); });
obj.wsClient.on('message', function (data) { // Make sure to handle flow control. obj.wsClient.on('message', function (data) { // Make sure to handle flow control.
if ((obj.relayActive == false) && (data == 'c')) { if (obj.relayActive == false) {
if ((data == 'c') || (data == 'cr')) {
obj.relayActive = true; obj.relayActive = true;
// Create a serial tunnel && SSH module // Create a serial tunnel && SSH module
@ -479,7 +491,10 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
// We are all set, start receiving data // We are all set, start receiving data
ws._socket.resume(); ws._socket.resume();
}
} else { } else {
if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
// Relay WS --> SSH // Relay WS --> SSH
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } } if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
} }
@ -708,12 +723,13 @@ module.exports.CreateSshTerminalRelay = function (parent, db, ws, req, domain, u
const protocol = (args.tlsoffload) ? 'ws' : 'wss'; const protocol = (args.tlsoffload) ? 'ws' : 'wss';
var domainadd = ''; var domainadd = '';
if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' } if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?noping=1&p=11&auth=' + authCookie // Protocol 11 is Web-SSH const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?p=11&auth=' + authCookie // Protocol 11 is Web-SSH
parent.parent.debug('relay', 'SSH: Connection websocket to ' + url); parent.parent.debug('relay', 'SSH: Connection websocket to ' + url);
obj.wsClient = new WebSocket(url, options); obj.wsClient = new WebSocket(url, options);
obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); }); obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); });
obj.wsClient.on('message', function (data) { // Make sure to handle flow control. obj.wsClient.on('message', function (data) { // Make sure to handle flow control.
if ((obj.relayActive == false) && (data == 'c')) { if (obj.relayActive == false) {
if ((data == 'c') || (data == 'cr')) {
obj.relayActive = true; obj.relayActive = true;
// Create a serial tunnel && SSH module // Create a serial tunnel && SSH module
@ -772,7 +788,10 @@ module.exports.CreateSshTerminalRelay = function (parent, db, ws, req, domain, u
// We are all set, start receiving data // We are all set, start receiving data
ws._socket.resume(); ws._socket.resume();
}
} else { } else {
if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
// Relay WS --> SSH // Relay WS --> SSH
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } } if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
} }
@ -1015,12 +1034,13 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
const protocol = (args.tlsoffload) ? 'ws' : 'wss'; const protocol = (args.tlsoffload) ? 'ws' : 'wss';
var domainadd = ''; var domainadd = '';
if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' } if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?noping=1&p=13&auth=' + authCookie // Protocol 13 is Web-SSH-Files const url = protocol + '://localhost:' + args.port + '/' + domainadd + (((obj.mtype == 3) && (obj.relaynodeid == null)) ? 'local' : 'mesh') + 'relay.ashx?p=13&auth=' + authCookie // Protocol 13 is Web-SSH-Files
parent.parent.debug('relay', 'SSH: Connection websocket to ' + url); parent.parent.debug('relay', 'SSH: Connection websocket to ' + url);
obj.wsClient = new WebSocket(url, options); obj.wsClient = new WebSocket(url, options);
obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); }); obj.wsClient.on('open', function () { parent.parent.debug('relay', 'SSH: Relay websocket open'); });
obj.wsClient.on('message', function (data) { // Make sure to handle flow control. obj.wsClient.on('message', function (data) { // Make sure to handle flow control.
if ((obj.relayActive == false) && (data == 'c')) { if (obj.relayActive == false) {
if ((data == 'c') || (data == 'cr')) {
obj.relayActive = true; obj.relayActive = true;
// Create a serial tunnel && SSH module // Create a serial tunnel && SSH module
@ -1039,7 +1059,7 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
parent.parent.DispatchEvent(['*', obj.nodeid, user._id, obj.meshid], obj, event); parent.parent.DispatchEvent(['*', obj.nodeid, user._id, obj.meshid], obj, event);
} catch (ex) { console.log(ex); } } catch (ex) { console.log(ex); }
obj.sshClient.sftp(function(err, sftp) { obj.sshClient.sftp(function (err, sftp) {
if (err) { obj.close(); return; } if (err) { obj.close(); return; }
obj.connected = true; obj.connected = true;
obj.sftp = sftp; obj.sftp = sftp;
@ -1073,7 +1093,10 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
// We are all set, start receiving data // We are all set, start receiving data
ws._socket.resume(); ws._socket.resume();
}
} else { } else {
if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
// Relay WS --> SSH // Relay WS --> SSH
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } } if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
} }

View File

@ -83,6 +83,8 @@ var CreateRDPDesktop = function (canvasid) {
obj.Stop(); obj.Stop();
break; break;
} }
case 'ping': { obj.socket.send('["pong"]'); break; }
case 'pong': { break; }
} }
} else { } else {
// This is binary bitmap data, store it. // This is binary bitmap data, store it.