forked from Ylianst/MeshCentral
-
Notifications
You must be signed in to change notification settings - Fork 0
/
swarmserver.js
434 lines (400 loc) · 26.4 KB
/
swarmserver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
/**
* @description MeshCentral v1 legacy Swarm Server, used to update agents and get them on MeshCentral2
* @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018-2020
* @license Apache-2.0
* @version v0.0.1
*/
/*jslint node: true */
/*jshint node: true */
/*jshint strict:false */
/*jshint -W097 */
/*jshint esversion: 6 */
"use strict";
// Construct a legacy Swarm Server server object
module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
var obj = {};
obj.parent = parent;
obj.db = db;
obj.args = args;
obj.certificates = certificates;
obj.legacyAgentConnections = {};
obj.migrationAgents = {};
obj.agentActionCount = {};
obj.stats = { blockedConnect: 0, connectCount: 0, clientCertConnectCount: 0, noCertConnectCount: 0, bytesIn: 0, bytesOut: 0, httpGetRequest: 0, pushedAgents: {}, close: 0, onclose: 0, agentType: {} }
const tls = require('tls');
const forge = require('node-forge');
const common = require('./common.js');
const LegacyMeshProtocol = {
NODEPUSH: 1, // Used to send a node block to another peer.
NODEPULL: 2, // Used to send a pull block to another peer.
NODENOTIFY: 3, // Used to indicate the node ID to other peers.
NODECHALLENGE: 4, // Used to challenge a node identity.
NODECRESPONSE: 5, // Used to respond to a node challenge.
TARGETSTATUS: 6, // Used to send the peer connection status list.
LOCALEVENT: 7, // Used to send local events to subscribers.
AESCRYPTO: 8, // Used to send an encrypted block of data.
SESSIONKEY: 9, // Used to send a session key to a remote node.
SYNCSTART: 10, // Used to send kick off the SYNC request, send the start NodeID.
SYNCMETADATA: 11, // Used to send a sequence of NodeID & serial numbers.
SYNCREQUEST: 12, // Used to send a sequence of NodeID's to request.
NODEID: 13, // Used to send the NodeID in the clear. Used for multicast.
AGENTID: 14, // Used to send the AgentID & version to the other node.
PING: 15, // Used to query a target for the presence of the mesh agent (PB_NODEID response expected).
SETUPADMIN: 16, // Used to set the trusted mesh identifier, this code can only be used from local settings file.
POLICY: 17, // Used to send a policy block to another peer.
POLICYSECRET: 18, // Used to encode the PKCS12 private key of a policy block.
EVENTMASK: 19, // Used by the mesh service to change the event mask.
RECONNECT: 20, // Used by the mesh service to indicate disconnect & reconnection after n seconds.
GETSTATE: 21, // Used by the mesh service to obtain agent state.
CERTENCRYPTED: 22, // Used to send a certificate encrypted message to a node.
GETCOOKIE: 23, // Used to request a certificate encryption anti-replay cookie.
COOKIE: 24, // Used to carry an anti-replay cookie to a requestor.
SESSIONCKEY: 25, // Used to send a session key to a remote console.
INTERFACE: 26, // Used to send a local interface blob to a management console.
MULTICAST: 27, // Used by the mesh service to cause the agent to send a multicast.
SELFEXE: 28, // Used to transfer our own agent executable.
LEADERBADGE: 29, // User to send a leadership badge.
NODEINFO: 30, // Used to indicate a block information update to the web service.
TARGETEVENT: 31, // Used to send a single target update event.
DEBUG: 33, // Used to send debug information to web service.
TCPRELAY: 34, // Used to operate mesh leader TCP relay sockets
CERTSIGNED: 35, // Used to send a certificate signed message to a node.
ERRORCODE: 36, // Used to notify of an error.
MESSAGE: 37, // Used to route messages between nodes.
CMESSAGE: 38, // Used to embed a interface identifier along with a PB_MESSAGE.
EMESSAGE: 39, // Used to embed a target encryption certificate along with a MESSAGE or CMESSAGE.
SEARCH: 40, // Used to send a custom search to one or more remote nodes.
MESSAGERELAY: 41, // Used by no-certificate consoles to send hopping messages to nodes.
USERINPUT: 42, // Used to send user keyboard input to a target computer
APPID: 43, // Used to send a block of data to a specific application identifier.
APPSUBSCRIBE: 44, // Used to perform local app subscription to an agent.
APPDIRECT: 45, // Used to send message directly to remote applications.
APPREQACK: 46, // Used to request an ack message.
APPACK: 47, // Used to ack a received message.
SERVERECHO: 48, // Server will echo this message, used for testing.
KVMINFO: 49, // Used to send local KVM secondary process information to mesh agent.
REMOTEWAKE: 50, // Used to send remote wake information to server.
NEWCONNECTTOKEN: 51, // Used to send a new connection token to the Swarm Server.
WIFISCAN: 52, // Used to send visible WIFI AP's to the server.
AMTPROVISIONING: 53, // Used by the agent to send Intel AMT provisioning information to the server.
ANDROIDCOMMAND: 54, // Send a Android OS specific command (Android only).
NODEAPPDATA: 55, // Used to send application specific data block to the server for storage.
PROXY: 56, // Used to indicate the currently used proxy setting string.
FILEOPERATION: 57, // Used to perform short file operations.
APPSUBSCRIBERS: 58, // Used request and send to the mesh server the list of subscribed applications
CUSTOM: 100, // Message containing application specific data.
USERAUTH: 1000, // Authenticate a user to the swarm server.
USERMESH: 1001, // Request or return the mesh list for this console.
USERMESHS: 1002, // Send mesh overview information to the console.
USERNODES: 1003, // Send node overview information to the console.
JUSERMESHS: 1004, // Send mesh overview information to the console in JSON format.
JUSERNODES: 1005, // Send node overview information to the console in JSON format.
USERPOWERSTATE: 1006, // Used to send a power command from the console to the server.
JMESHPOWERTIMELINE: 1007, // Send the power timeline for all nodes in a mesh.
JMESHPOWERSUMMARY: 1008, // Send the power summary for sum of all nodes in a mesh.
USERCOMMAND: 1009, // Send a user admin text command to and from the server.
POWERBLOCK: 1010, // Request/Response of block of power state information.
MESHACCESSCHANGE: 1011, // Notify a console of a change in accessible meshes.
COOKIEAUTH: 1012, // Authenticate a user using a crypto cookie.
NODESTATECHANGE: 1013, // Indicates a node has changed power state.
JUSERNODE: 1014, // Send node overview information to the console in JSON format.
AMTWSMANEVENT: 1015, // Intel AMT WSMAN event sent to consoles.
ROUTINGCOOKIE: 1016, // Used by a console to request a routing cookie.
JCOLLABORATION: 1017, // Request/send back JSON collaboration state.
JRELATIONS: 1018, // Request/send back JSON relations state.
SETCOLLABSTATE: 1019, // Set the collaboration state for this session.
ADDRELATION: 1020, // Request that a new relation be added.
DELETERELATION: 1021, // Request a relation be deleted.
ACCEPTRELATION: 1022, // Request relation invitation be accepted.
RELATIONCHANGEEVENT: 1023, // Notify that a relation has changed.
COLLBCHANGEEVENT: 1024, // Notify that a collaboration state has change.
MULTICONSOLEMESSAGE: 1025, // Send a message to one or more console id's.
CONSOLEID: 1026, // Notify a console of it's console id.
CHANGERELATIONDATA: 1027, // Request that relation data be changed.
SETUSERDATA: 1028, // Set user data
GETUSERDATA: 1029, // Get user data
SERVERAUTH: 1030, // Used to verify the certificate of the server
USERAUTH2: 1031, // Authenticate a user to the swarm server (Uses SHA1 SALT)
GUESTREMOTEDESKTOP: 2001, // Guest usage: Remote Desktop
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
};
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true, rejectUnauthorized: false }, onConnection);
obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } });
loadMigrationAgents();
// Load all migration agents along with full executable in memory
function loadMigrationAgents() {
var migrationAgentsDir = null, migrationAgentsPath = obj.parent.path.join(obj.parent.datapath, 'migrationagents');
try { migrationAgentsDir = obj.parent.fs.readdirSync(migrationAgentsPath); } catch (e) { }
if (migrationAgentsDir != null) {
for (var i in migrationAgentsDir) {
if (migrationAgentsDir[i].toLowerCase().startsWith('meshagent-')) {
var migrationAgentName = obj.parent.path.join(migrationAgentsPath, migrationAgentsDir[i]);
var agentInfo = migrationAgentsDir[i].substring(10).split('.');
var agentVersion = parseInt(agentInfo[0]);
var agentArch = parseInt(agentInfo[1]);
if (obj.migrationAgents[agentArch] == null) { obj.migrationAgents[agentArch] = {}; }
if (obj.migrationAgents[agentArch][agentVersion] == null) { obj.migrationAgents[agentArch][agentVersion] = { arch: agentArch, ver: agentVersion, path: migrationAgentName }; }
}
}
}
}
function onData(data) {
if (this.relaySocket) { var ps = this; try { this.relaySocket.write(data, 'binary', function () { ps.resume(); }); } catch (ex) { } return; }
if (args.swarmdebug) { var buf = Buffer.from(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
obj.stats.bytesIn += data.length;
this.tag.accumulator += data;
// Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
if (this.tag.first == true) {
if (this.tag.accumulator.length < 3) return;
if ((this.tag.accumulator.substring(0, 3) == 'GET') || (this.tag.accumulator.substring(0, 3) == 'POS')) {
obj.stats.httpGetRequest++;
/*console.log("Swarm Connection, HTTP GET detected: " + socket.remoteAddress);*/
//socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>MeshCentral2 legacy swarm server.<br />MeshCentral1 mesh agents should connect here for updates.</body></html>');
//socket.end();
// Relay this connection to the main TLS port
this.pause();
var relaySocket = tls.connect(obj.args.port, { rejectUnauthorized: false }, function () { this.write(this.parentSocket.tag.accumulator); this.parentSocket.resume(); });
relaySocket.on('data', function (data) { try { var rs = this; this.pause(); this.parentSocket.write(data, 'binary', function () { rs.resume(); }); } catch (ex) { } });
relaySocket.on('error', function (err) { try { this.parentSocket.end(); } catch (ex) { } });
relaySocket.on('end', function () { try { this.parentSocket.end(); } catch (ex) { } });
this.relaySocket = relaySocket;
relaySocket.parentSocket = this;
return;
}
this.tag.first = false;
}
// A client certificate is required
if ((this.tag.clientCert == null) || (this.tag.clientCert.subject == null)) {
/*console.log("Swarm Connection, no client cert: " + socket.remoteAddress);*/
this.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 legacy swarm server.\r\nNo client certificate given.');
//this.end(); // If we don't close the connection, it may lead to less reconnection traffic.
return;
}
try {
// Parse all of the agent binary command data we can
var l = 0;
do { l = ProcessCommand(this); if (l > 0) { this.tag.accumulator = this.tag.accumulator.substring(l); } } while (l > 0);
if (l < 0) { this.end(); }
} catch (e) {
console.log(e);
}
}
// Process one AFP command
function ProcessCommand(socket) {
if (socket.tag.accumulator.length < 4) return 0;
var cmd = common.ReadShort(socket.tag.accumulator, 0);
var len = common.ReadShort(socket.tag.accumulator, 2);
if (len > socket.tag.accumulator.length) return 0;
var data = socket.tag.accumulator.substring(4, len);
//console.log('Swarm: Cmd=' + cmd + ', Len=' + len + '.');
switch (cmd) {
case LegacyMeshProtocol.NODEPUSH: {
parent.debug('swarmcmd', 'NODEPUSH');
var nodeblock = obj.decodeNodeBlock(data);
if ((nodeblock != null) && (nodeblock.agenttype != null) && (nodeblock.agentversion != null)) {
if (socket.pingTimer == null) { socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000); }
parent.debug('swarmcmd', 'NODEPUSH:' + JSON.stringify(nodeblock));
// Log the agent type
if (obj.stats.agenttype[nodeblock.agenttype] == null) { obj.stats.agenttype[nodeblock.agenttype] = 1; } else { obj.stats.agenttype[nodeblock.agenttype]++; }
// Check if this agent is asking of updates over and over again.
var actionCount = obj.agentActionCount[nodeblock.nodeidhex];
if (actionCount == null) { actionCount = 0; }
if (actionCount > 2) {
// Already tried to update this agent two times, something is not right.
//console.log('SWARM: ' + actionCount + ' update actions on ' + nodeblock.nodeidhex + ', holding.');
} else {
// Figure out what is the next agent version we need.
var nextAgentVersion = 0;
if (nodeblock.agentversion < 201) { nextAgentVersion = 201; } // If less then 201, move to transitional MC1 agent.
if (nodeblock.agentversion == 201) { nextAgentVersion = 202; } // If at 201, move to first MC2 agent.
// See if we need to start the agent update
if ((nextAgentVersion > 0) && (obj.migrationAgents[nodeblock.agenttype] != null) && (obj.migrationAgents[nodeblock.agenttype][nextAgentVersion] != null)) {
// Start the update
socket.tag.update = obj.migrationAgents[nodeblock.agenttype][nextAgentVersion];
socket.tag.updatePtr = 0;
//console.log('Performing legacy agent update from ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' to ' + socket.tag.update.ver + '.' + socket.tag.update.arch + ' on ' + nodeblock.agentname + '.');
// Update stats
if (obj.stats.pushedAgents[nodeblock.agenttype] == null) { obj.stats.pushedAgents[nodeblock.agenttype] = {}; }
if (obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] == null) { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] = 1; } else { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion]++; }
// Start the agent download using the task limiter so not to flood the server. Low priority task
obj.parent.taskLimiter.launch(function (socket, taskid, taskLimiterQueue) {
if (socket.xclosed == 1) {
// Socket is closed, do nothing
obj.parent.taskLimiter.completed(taskid); // Indicate this task complete
} else {
// Start the agent update
socket.tag.taskid = taskid;
obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(5) + common.IntToStr(0)); // agent.SendQuery(5, 0); // Start the agent download
}
}, socket, 2);
} else {
//console.log('No legacy agent update for ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' on ' + nodeblock.agentname + '.');
}
}
// Mark this agent
obj.agentActionCount[nodeblock.nodeidhex] = ++actionCount;
}
break;
}
case LegacyMeshProtocol.AMTPROVISIONING: {
parent.debug('swarmcmd', 'AMTPROVISIONING');
obj.SendCommand(socket, LegacyMeshProtocol.AMTPROVISIONING, common.ShortToStr(1));
break;
}
case LegacyMeshProtocol.GETSTATE: {
parent.debug('swarmcmd', 'GETSTATE');
if (len < 12) break;
var statecmd = common.ReadInt(data, 0);
//var statesync = common.ReadInt(data, 4);
switch (statecmd) {
case 6: { // Ask for agent block
if (socket.tag.update != null) {
// Send an agent block
if (socket.tag.update.binary == null) { socket.tag.update.binary = obj.parent.fs.readFileSync(socket.tag.update.path); }
var l = Math.min(socket.tag.update.binary.length - socket.tag.updatePtr, 16384);
obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(6) + common.IntToStr(socket.tag.updatePtr) + socket.tag.update.binary.toString('binary', socket.tag.updatePtr, socket.tag.updatePtr + l)); // agent.SendQuery(6, AgentFileLen + AgentBlock);
parent.debug('swarmcmd', 'Sending agent block, ptr = ' + socket.tag.updatePtr + ', len = ' + l);
socket.tag.updatePtr += l;
if (socket.tag.updatePtr >= socket.tag.update.binary.length) {
// Send end-of-transfer
obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(7) + common.IntToStr(socket.tag.update.binary.length)); //agent.SendQuery(7, AgentFileLen);
parent.debug('swarmcmd', 'Sending end of agent, ptr = ' + socket.tag.updatePtr);
obj.parent.taskLimiter.completed(socket.tag.taskid); // Indicate this task complete
delete socket.tag.taskid;
delete socket.tag.update;
delete socket.tag.updatePtr;
}
}
break;
}
default: {
// All other state commands from the legacy agent must be ignored.
break;
}
}
break;
}
case LegacyMeshProtocol.APPSUBSCRIBERS: {
parent.debug('swarmcmd', 'APPSUBSCRIBERS');
break;
}
default: {
parent.debug('swarmcmd', 'Unknown command: ' + cmd + ' of len ' + len + '.');
}
}
return len;
}
// Called when a legacy agent connects to this server
function onConnection(socket) {
// Check for blocked IP address
if (checkSwarmIpAddress(socket, obj.args.swarmallowedip) == false) { obj.stats.blockedConnect++; parent.debug('swarm', "New blocked agent connection"); return; }
obj.stats.connectCount++;
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "" };
parent.debug('swarm', 'New legacy agent connection');
if ((socket.tag.clientCert == null) || (socket.tag.clientCert.subject == null)) { obj.stats.noCertConnectCount++; } else { obj.stats.clientCertConnectCount++; }
socket.addListener("data", onData);
socket.addListener("close", function () {
obj.stats.onclose++;
parent.debug('swarm', 'Connection closed');
// Perform aggressive cleanup
if (this.relaySocket) { try { this.relaySocket.end(); this.relaySocket.removeAllListeners(["data", "end", "error"]); delete this.relaySocket; } catch (ex) { } }
if (this.pingTimer != null) { clearInterval(this.pingTimer); delete this.pingTimer; }
if (this.tag && (typeof this.tag.taskid == 'number')) {
obj.parent.taskLimiter.completed(this.tag.taskid); // Indicate this task complete
delete this.tag.taskid;
}
if (this.tag) {
if (this.tag.accumulator) { delete this.tag.accumulator; }
if (this.tag.clientCert) { delete this.tag.clientCert; }
delete this.tag;
}
this.removeAllListeners([ "data", "close", "error" ]);
});
socket.addListener("error", function () {
//console.log("Swarm Error: " + socket.remoteAddress);
});
}
function getTagClass(data, tagClass, type) {
if ((data == null) || (data.value == null)) return;
for (var i in data.value) {
//console.log(JSON.stringify(data.value[i]));
if ((data.value[i].tagClass == tagClass) && (data.value[i].type == type)) {
return data.value[i];
}
}
}
// Decode a node push block
obj.decodeNodeBlock = function (data) {
try {
// Traverse the DER to get the raw data (Not sure if this works all the time)
var info = {}, ptr = 68, der = forge.asn1.fromDer(forge.util.createBuffer(data, 'binary'));
der = getTagClass(der, 128, 0);
der = getTagClass(der, 0, 16);
der = getTagClass(der, 0, 16);
der = getTagClass(der, 128, 0);
der = getTagClass(der, 0, 4);
var binarydata = der.value;
// Get the basic header values
info.certhashhex = common.rstr2hex(binarydata.substring(0, 32)); // Hash of the complete mesh agent certificate
info.nodeidhex = common.rstr2hex(binarydata.substring(32, 64)); // Old mesh agent nodeid
info.serialNumber = common.ReadIntX(binarydata, 64); // Block serial number
// Got thru the sub-blocks
while (ptr < binarydata.length) {
var btyp = common.ReadShort(binarydata, ptr), blen = common.ReadShort(binarydata, ptr + 2), bdata = binarydata.substring(ptr + 4, ptr + 4 + blen);
switch (btyp) {
case 1: { // PBST_COMPUTERINFO
info.agenttype = common.ReadShortX(bdata, 0);
info.agentbuild = common.ReadShortX(bdata, 2);
info.agentversion = common.ReadIntX(bdata, 4);
info.agentname = bdata.substring(8, 64 + 8);
var xx = info.agentname.indexOf('\u0000');
if (xx >= 0) { info.agentname = info.agentname.substring(0, xx); }
info.agentosdesc = bdata.substring(64 + 8, 64 + 64 + 8);
xx = info.agentosdesc.indexOf('\u0000');
if (xx >= 0) { info.agentosdesc = info.agentosdesc.substring(0, xx); }
return info;
}
default: {
// All other commands from the legacy agent must be ignored.
break;
}
}
ptr += blen;
}
return info;
} catch (e) { }
return null;
};
// Disconnect legacy agent connection
obj.close = function (socket) {
obj.stats.close++;
try { socket.close(); } catch (e) { }
socket.xclosed = 1;
};
obj.SendCommand = function (socket, cmdid, data) {
if (data == null) { data = ''; }
Write(socket, common.ShortToStr(cmdid) + common.ShortToStr(data.length + 4) + data);
};
function Write(socket, data) {
obj.stats.bytesOut += data.length;
if (args.swarmdebug) {
// Print out sent bytes
var buf = Buffer.from(data, "binary");
console.log('SWARM --> (' + buf.length + '):' + buf.toString('hex'));
socket.write(buf);
} else {
socket.write(Buffer.from(data, "binary"));
}
}
// Check if the source IP address is allowed for a given allowed list, return false if not
function checkSwarmIpAddress(socket, allowedIpList) {
if (allowedIpList == null) { return true; }
try {
var ip = socket.remoteAddress;
if (ip) { for (var i = 0; i < allowedIpList.length; i++) { if (require('ipcheck').match(ip, allowedIpList[i])) { return true; } } }
} catch (e) { console.log(e); }
return false;
}
return obj;
};