Added full agent ping/pong support on SSH/SFTP sessions.
Ylian Saint-Hilaire committed
May 5, 2022 at 16:16 UTC
5869782bdf227343aa99502577cac28eb2ff046e
3 files changed
+61
-28
apprelays.js
+55
-27
@@ -212,9 +212,11 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
212
213
// When data is received from the web socket
214
// RDP default port is 3389
215
- ws.on('message', function (msg) {
215
+ ws.on('message', function (data) {
216
try {
217
- msg = JSON.parse(msg);
217
+ var msg = null;
218
+ try { msg = JSON.parse(data); } catch (ex) { }
219
+ if ((msg == null) || (typeof msg != 'object')) return;
220
switch (msg[0]) {
221
case 'infos': {
222
obj.infos = msg[1];
@@ -493,7 +495,13 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
495
ws._socket.resume();
496
}
497
} else {
496
- if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
498
+ if (typeof data == 'string') {
499
+ // Forward any ping/pong commands to the browser
500
+ var cmd = null;
501
+ try { cmd = JSON.parse(data); } catch (ex) { }
502
+ if ((cmd != null) && (cmd.ctrlChannel == '102938') && ((cmd.type == 'ping') || (cmd.type == 'pong'))) { obj.ws.send(data); }
503
+ return;
504
+ }
505
506
// Relay WS --> SSH
507
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
@@ -508,12 +516,15 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
516
517
// When data is received from the web socket
518
// SSH default port is 22
511
- ws.on('message', function (msg) {
519
+ ws.on('message', function (data) {
520
try {
513
- if (typeof msg != 'string') return;
514
- if (msg[0] == '{') {
521
+ if (typeof data != 'string') return;
522
+ if (data[0] == '{') {
523
// Control data
516
- msg = JSON.parse(msg);
524
+ var msg = null;
525
+ try { msg = JSON.parse(data); } catch (ex) { }
526
+ if ((msg == null) || (typeof msg != 'object')) return;
527
+ if ((msg.ctrlChannel == '102938') && ((msg.type == 'ping') || (msg.type == 'pong'))) { try { obj.wsClient.send(data); } catch (ex) { } return; }
528
if (typeof msg.action != 'string') return;
529
switch (msg.action) {
530
case 'connect': {
@@ -563,9 +574,9 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
574
break;
575
}
576
}
566
- } else if (msg[0] == '~') {
577
+ } else if (data[0] == '~') {
578
// Terminal data
568
- if (obj.sshShell != null) { obj.sshShell.write(msg.substring(1)); }
579
+ if (obj.sshShell != null) { obj.sshShell.write(data.substring(1)); }
580
}
581
} catch (ex) { obj.close(); }
582
});
@@ -790,7 +801,13 @@ module.exports.CreateSshTerminalRelay = function (parent, db, ws, req, domain, u
801
ws._socket.resume();
802
}
803
} else {
793
- if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
804
+ if (typeof data == 'string') {
805
+ // Forward any ping/pong commands to the browser
806
+ var cmd = null;
807
+ try { cmd = JSON.parse(data); } catch (ex) { }
808
+ if ((cmd != null) && (cmd.ctrlChannel == '102938') && ((cmd.type == 'ping') || (cmd.type == 'pong'))) { try { obj.ws.send(data); } catch (ex) { console.log(ex); } }
809
+ return;
810
+ }
811
812
// Relay WS --> SSH
813
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
@@ -808,13 +825,15 @@ module.exports.CreateSshTerminalRelay = function (parent, db, ws, req, domain, u
825
826
// When data is received from the web socket
827
// SSH default port is 22
811
- ws.on('message', function (msg) {
828
+ ws.on('message', function (data) {
829
try {
813
- if (typeof msg != 'string') return;
814
- if (msg[0] == '{') {
830
+ if (typeof data != 'string') return;
831
+ if (data[0] == '{') {
832
// Control data
816
- msg = JSON.parse(msg);
817
- if (typeof msg.action != 'string') return;
833
+ var msg = null;
834
+ try { msg = JSON.parse(data); } catch (ex) { }
835
+ if ((msg == null) || (typeof msg != 'object')) return;
836
+ if ((msg.ctrlChannel == '102938') && ((msg.type == 'ping') || (msg.type == 'pong'))) { try { obj.wsClient.send(data); } catch (ex) { } return; }
837
switch (msg.action) {
838
case 'sshauth': {
839
// Verify inputs
@@ -866,9 +885,9 @@ module.exports.CreateSshTerminalRelay = function (parent, db, ws, req, domain, u
885
break;
886
}
887
}
869
- } else if (msg[0] == '~') {
888
+ } else if (data[0] == '~') {
889
// Terminal data
871
- if (obj.sshShell != null) { obj.sshShell.write(msg.substring(1)); }
890
+ if (obj.sshShell != null) { obj.sshShell.write(data.substring(1)); }
891
}
892
} catch (ex) { obj.close(); }
893
});
@@ -1095,7 +1114,13 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
1114
ws._socket.resume();
1115
}
1116
} else {
1098
- if (typeof data == 'string') return; // Only process binary data, this will include ping/ping
1117
+ if (typeof data == 'string') {
1118
+ // Forward any ping/pong commands to the browser
1119
+ var cmd = null;
1120
+ try { cmd = JSON.parse(data); } catch (ex) { }
1121
+ if ((cmd != null) && (cmd.ctrlChannel == '102938') && ((cmd.type == 'ping') || (cmd.type == 'pong'))) { obj.ws.send(data); }
1122
+ return;
1123
+ }
1124
1125
// Relay WS --> SSH
1126
if ((data.length > 0) && (obj.ser != null)) { try { obj.ser.updateBuffer(data); } catch (ex) { console.log(ex); } }
@@ -1113,15 +1138,15 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
1138
1139
// When data is received from the web socket
1140
// SSH default port is 22
1116
- ws.on('message', function (msg) {
1141
+ ws.on('message', function (data) {
1142
//if ((obj.firstMessage === true) && (msg != 5)) { obj.close(); return; } else { delete obj.firstMessage; }
1143
try {
1119
- if (typeof msg != 'string') {
1120
- if (msg[0] == 123) {
1121
- msg = msg.toString();
1144
+ if (typeof data != 'string') {
1145
+ if (data[0] == 123) {
1146
+ data = data.toString();
1147
} else if ((obj.sftp != null) && (obj.uploadHandle != null)) {
1123
- const off = (msg[0] == 0) ? 1 : 0;
1124
- obj.sftp.write(obj.uploadHandle, msg, off, msg.length - off, obj.uploadPosition, function (err) {
1148
+ const off = (data[0] == 0) ? 1 : 0;
1149
+ obj.sftp.write(obj.uploadHandle, data, off, data.length - off, obj.uploadPosition, function (err) {
1150
if (err != null) {
1151
obj.sftp.close(obj.uploadHandle, function () { });
1152
try { obj.ws.send(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: obj.uploadReqid }))) } catch (ex) { }
@@ -1134,13 +1159,16 @@ module.exports.CreateSshFilesRelay = function (parent, db, ws, req, domain, user
1159
try { obj.ws.send(Buffer.from(JSON.stringify({ action: 'uploadack', reqid: obj.uploadReqid }))) } catch (ex) { }
1160
}
1161
});
1137
- obj.uploadPosition += (msg.length - off);
1162
+ obj.uploadPosition += (data.length - off);
1163
return;
1164
}
1165
}
1141
- if (msg[0] == '{') {
1166
+ if (data[0] == '{') {
1167
// Control data
1143
- msg = JSON.parse(msg);
1168
+ var msg = null;
1169
+ try { msg = JSON.parse(data); } catch (ex) { }
1170
+ if ((msg == null) || (typeof msg != 'object')) return;
1171
+ if ((msg.ctrlChannel == '102938') && ((msg.type == 'ping') || (msg.type == 'pong'))) { try { obj.wsClient.send(data); } catch (ex) { } return; }
1172
if (typeof msg.action != 'string') return;
1173
switch (msg.action) {
1174
case 'ls': {
public/scripts/agent-redir-ws-0.1.1.js
+2
@@ -109,6 +109,8 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
109
} else if (controlMsg.type == 'webrtc2') {
110
// TODO: Resume/Start sending data over WebRTC
111
}
112
+ } else if (controlMsg.type == 'ping') { // if we get a ping, respond with a pong.
113
+ obj.sendCtrlMsg('{"ctrlChannel":"102938","type":"pong"}');
114
}
115
}
116
views/ssh.handlebars
+4
-1
@@ -186,7 +186,10 @@
186
socket.onmessage = function (data) {
187
if (typeof data.data != 'string') return;
188
if (data.data[0] == '{') {
189
- var json = JSON.parse(data.data);
189
+ var json = null;
190
+ try { json = JSON.parse(data.data); } catch (ex) { }
191
+ if ((json == null) || (typeof json != 'object')) return;
192
+ if ((json.ctrlChannel == 102938) && (json.type == 'ping')) { socket.send('{"ctrlChannel":"102938","type":"pong"}'); return; }
193
switch (json.action) {
194
case 'connected': { state = 3; updateState(); term.focus(); break; }
195
case 'sshauth': {