Improved session recording and logs.

This commit is contained in:
Ylian Saint-Hilaire 2019-08-06 13:27:24 -07:00
parent 3f5e60b148
commit 321f35ede8
6 changed files with 51 additions and 27 deletions

View File

@ -166,24 +166,36 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
// Setup session recording // Setup session recording
var sessionUser = user; var sessionUser = user;
if (sessionUser == null) { sessionUser = obj.peer.user; } if (sessionUser == null) { sessionUser = obj.peer.user; }
if (domain.sessionrecording) { if (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(req.query.p)) >= 0)))) {
try { parent.parent.fs.mkdirSync(parent.parent.recordpath); } catch (e) { } var recFilename = 'relaysession' + ((domain.id == '') ? '' : '-') + domain.id + '-' + Date.now() + '-' + obj.id + '.mcrec'
var recFilename = 'relaysession' + ((domain.id == '') ? '' : '-') + domain.id + '-' + Date.now() + '-' + sessionUser.name + '-' + obj.id + '.mcrec' var recFullFilename = null;
var recFullFilename = parent.parent.path.join(parent.parent.recordpath, recFilename); if (domain.sessionrecording.filepath) {
try { parent.parent.fs.mkdirSync(domain.sessionrecording.filepath); } catch (e) { }
recFullFilename = parent.parent.path.join(domain.sessionrecording.filepath, recFilename);
} else {
try { parent.parent.fs.mkdirSync(parent.parent.recordpath); } catch (e) { }
recFullFilename = parent.parent.path.join(parent.parent.recordpath, recFilename);
}
parent.parent.fs.open(recFullFilename, 'w', function (err, fd) { parent.parent.fs.open(recFullFilename, 'w', function (err, fd) {
// Write the recording file header if (err != null) {
var firstBlock = Buffer.from(JSON.stringify({ magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(ws._socket.remoteAddress), ipaddr2: cleanRemoteAddr(obj.peer.ws._socket.remoteAddress), time: new Date().toLocaleString() })); // Unable to record
var header = Buffer.alloc(16); // Type (2) + Flags (2) + Size(4) + Time(8)
header.writeInt16BE(1, 0); // Type (1 = Header, 2 = Network Data)
header.writeInt16BE(0, 2); // Flags (1 = Binary, 2 = User)
header.writeInt32BE(firstBlock.length, 4); // Size
header.writeIntBE(ws.time, 10, 6); // Time
var block = Buffer.concat([header, firstBlock]);
parent.parent.fs.write(fd, block, 0, block.length, function (err, bytesWritten, buffer) {
relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false };
ws.send('c'); // Send connect to both peers ws.send('c'); // Send connect to both peers
relayinfo.peer1.ws.send('c'); relayinfo.peer1.ws.send('c');
}); } else {
// Write the recording file header
var firstBlock = Buffer.from(JSON.stringify({ magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(ws._socket.remoteAddress), ipaddr2: cleanRemoteAddr(obj.peer.ws._socket.remoteAddress), time: new Date().toLocaleString(), protocol: req.query.p, nodeid: req.query.nodeid }));
var header = Buffer.alloc(16); // Type (2) + Flags (2) + Size(4) + Time(8)
header.writeInt16BE(1, 0); // Type (1 = Header, 2 = Network Data)
header.writeInt16BE(0, 2); // Flags (1 = Binary, 2 = User)
header.writeInt32BE(firstBlock.length, 4); // Size
header.writeIntBE(ws.time, 10, 6); // Time
var block = Buffer.concat([header, firstBlock]);
parent.parent.fs.write(fd, block, 0, block.length, function (err, bytesWritten, buffer) {
relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false };
ws.send('c'); // Send connect to both peers
relayinfo.peer1.ws.send('c');
});
}
}); });
} else { } else {
// Send session start // Send session start
@ -195,7 +207,11 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
// Log the connection // Log the connection
if (sessionUser) { if (sessionUser) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: sessionUser._id, username: sessionUser.name, msg: 'Started relay session \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress) }; var msg = 'Started relay session';
if (req.query.p == 1) { msg = 'Started terminal session'; }
else if (req.query.p == 2) { msg = 'Started desktop session'; }
else if (req.query.p == 5) { msg = 'Started file management session'; }
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: sessionUser._id, username: sessionUser.name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress), protocol: req.query.p, nodeid: req.query.nodeid };
parent.parent.DispatchEvent(['*', user._id], obj, event); parent.parent.DispatchEvent(['*', user._id], obj, event);
} }
} else { } else {
@ -308,11 +324,15 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
// Log the disconnection // Log the disconnection
if (ws.time) { if (ws.time) {
var msg = 'Ended relay session';
if (req.query.p == 1) { msg = 'Ended terminal session'; }
else if (req.query.p == 2) { msg = 'Ended desktop session'; }
else if (req.query.p == 5) { msg = 'Ended file management session'; }
if (user) { if (user) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: parent.users[user._id].name, msg: 'Ended relay session \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)' }; var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: parent.users[user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: req.query.p, nodeid: req.query.nodeid };
parent.parent.DispatchEvent(['*', user._id], obj, event); parent.parent.DispatchEvent(['*', user._id], obj, event);
} else if (peer.user) { } else if (peer.user) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: parent.users[peer.user._id].name, msg: 'Ended relay session \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)' }; var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: parent.users[peer.user._id].name, msg: msg + ' \"' + obj.id + '\" from ' + cleanRemoteAddr(obj.peer.ws._socket.remoteAddress) + ' to ' + cleanRemoteAddr(ws._socket.remoteAddress) + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: req.query.p, nodeid: req.query.nodeid };
parent.parent.DispatchEvent(['*', peer.user._id], obj, event); parent.parent.DispatchEvent(['*', peer.user._id], obj, event);
} }
} }
@ -422,7 +442,7 @@ about this recording. It looks something like this:
} }
The rest of the data blocks are all network traffic that was relayed thru the server. They are of TYPE 2 and have The rest of the data blocks are all network traffic that was relayed thru the server. They are of TYPE 2 and have
a given size and timestamp. When looking at network traffic the flags are imporant. a given size and timestamp. When looking at network traffic the flags are important:
- If traffic has the first (0x0001) flag set, the data is binary otherwise it's a string. - If traffic has the first (0x0001) flag set, the data is binary otherwise it's a string.
- If the traffic has the second (0x0002) flag set, traffic is coming from the user's browser, if not, it's coming from the MeshAgent. - If the traffic has the second (0x0002) flag set, traffic is coming from the user's browser, if not, it's coming from the MeshAgent.

View File

@ -35,7 +35,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
//obj.debug = function (msg) { console.log(msg); } //obj.debug = function (msg) { console.log(msg); }
obj.Start = function (nodeid) { obj.Start = function (nodeid) {
var url2, url = window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/meshrelay.ashx?browser=1&id=" + obj.tunnelid; var url2, url = window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/meshrelay.ashx?browser=1&p=" + obj.protocol + "&nodeid=" + nodeid + "&id=" + obj.tunnelid;
//if (serverPublicNamePort) { url2 = window.location.protocol.replace("http", "ws") + "//" + serverPublicNamePort + "/meshrelay.ashx?id=" + obj.tunnelid; } else { url2 = url; } //if (serverPublicNamePort) { url2 = window.location.protocol.replace("http", "ws") + "//" + serverPublicNamePort + "/meshrelay.ashx?id=" + obj.tunnelid; } else { url2 = url; }
if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; } if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; }
obj.nodeid = nodeid; obj.nodeid = nodeid;
@ -48,7 +48,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
obj.socket.onclose = obj.xxOnSocketClosed; obj.socket.onclose = obj.xxOnSocketClosed;
obj.xxStateChange(1); obj.xxStateChange(1);
//obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: url2 }); //obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: url2 });
obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: "*" + domainUrl + "meshrelay.ashx?id=" + obj.tunnelid, usage: obj.protocol }); obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: "*" + domainUrl + "meshrelay.ashx?p=" + obj.protocol + "&nodeid=" + nodeid + "&id=" + obj.tunnelid, usage: obj.protocol });
//obj.debug("Agent Redir Start: " + url); //obj.debug("Agent Redir Start: " + url);
} }

View File

@ -101,7 +101,11 @@
}, },
"_yubikey": { "id": "0000", "secret": "xxxxxxxxxxxxxxxxxxxxx", "_proxy": "http://myproxy.domain.com:80" }, "_yubikey": { "id": "0000", "secret": "xxxxxxxxxxxxxxxxxxxxx", "_proxy": "http://myproxy.domain.com:80" },
"_httpheaders": { "Strict-Transport-Security": "max-age=360000" }, "_httpheaders": { "Strict-Transport-Security": "max-age=360000" },
"_agentConfig": [ "webSocketMaskOverride=1" ] "_agentConfig": [ "webSocketMaskOverride=1" ],
"_SessionRecording": {
"_filepath": "C:\\temp",
"protocols": [ 1, 2 ]
}
}, },
"customer1": { "customer1": {
"DNS": "customer1.myserver.com", "DNS": "customer1.myserver.com",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5992,7 +5992,6 @@
var icon = 'si3'; var icon = 'si3';
if (event.etype == 'user') icon = 'm2'; if (event.etype == 'user') icon = 'm2';
if (event.etype == 'server') icon = 'si3'; if (event.etype == 'server') icon = 'si3';
if (event.etype == 'relay') icon = 'relayIcon16';
var msg = EscapeHtml(event.msg).split('(R)').join('®'); var msg = EscapeHtml(event.msg).split('(R)').join('®');
if (event.username) { if (event.username) {
@ -6002,6 +6001,7 @@
msg = EscapeHtml(event.username) + ' → ' + msg; msg = EscapeHtml(event.username) + ' → ' + msg;
} }
} }
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
x += '<tr onclick=showEventDetails(' + event.h + ',1) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>'; x += '<tr onclick=showEventDetails(' + event.h + ',1) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>';
} }
} }
@ -7379,7 +7379,6 @@
var icon = 'si3'; var icon = 'si3';
if (event.etype == 'user') icon = 'm2'; if (event.etype == 'user') icon = 'm2';
if (event.etype == 'server') icon = 'si3'; if (event.etype == 'server') icon = 'si3';
if (event.etype == 'relay') icon = 'relayIcon16';
var msg = EscapeHtml(event.msg).split('(R)').join('&reg;'); var msg = EscapeHtml(event.msg).split('(R)').join('&reg;');
if (event.nodeid) { if (event.nodeid) {
@ -7396,6 +7395,7 @@
msg = EscapeHtml(event.username) + ' &rarr; ' + msg; msg = EscapeHtml(event.username) + ' &rarr; ' + msg;
} }
} }
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
x += '<tr onclick=showEventDetails(' + event.h + ',2) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>'; x += '<tr onclick=showEventDetails(' + event.h + ',2) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>';
} }
} }
@ -8085,7 +8085,6 @@
var icon = 'si3'; var icon = 'si3';
if (event.etype == 'user') icon = 'm2'; if (event.etype == 'user') icon = 'm2';
if (event.etype == 'server') icon = 'si3'; if (event.etype == 'server') icon = 'si3';
if (event.etype == 'relay') icon = 'relayIcon16';
var msg = EscapeHtml(event.msg).split('(R)').join('&reg;'); var msg = EscapeHtml(event.msg).split('(R)').join('&reg;');
if (event.nodeid) { if (event.nodeid) {
@ -8102,6 +8101,7 @@
msg = EscapeHtml(event.username) + ' &rarr; ' + msg; msg = EscapeHtml(event.username) + ' &rarr; ' + msg;
} }
} }
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
x += '<tr onclick=showEventDetails(' + event.h + ',3) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>'; x += '<tr onclick=showEventDetails(' + event.h + ',3) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1>&nbsp;</td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2>&nbsp;</td></tr><tr style=height:2px></tr>';
} }
} }