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