@serve.zone/dcrouter 13.39.0 → 13.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +2 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +53 -19
- package/dist_ts/opsserver/handlers/security.handler.d.ts +2 -0
- package/dist_ts/opsserver/handlers/security.handler.js +50 -73
- package/dist_ts/radius/classes.radius.server.d.ts +0 -5
- package/dist_ts/radius/classes.radius.server.js +19 -65
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/monitoring/classes.metricsmanager.ts +59 -21
- package/ts/opsserver/handlers/security.handler.ts +57 -109
- package/ts/radius/classes.radius.server.ts +19 -69
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -84,7 +84,6 @@ export declare class RadiusServer {
|
|
|
84
84
|
private vlanManager;
|
|
85
85
|
private accountingManager;
|
|
86
86
|
private config;
|
|
87
|
-
private clientSecrets;
|
|
88
87
|
private running;
|
|
89
88
|
private stats;
|
|
90
89
|
constructor(config: IRadiusServerConfig);
|
|
@@ -124,10 +123,6 @@ export declare class RadiusServer {
|
|
|
124
123
|
* Build client secrets map from configuration
|
|
125
124
|
*/
|
|
126
125
|
private buildClientSecretsMap;
|
|
127
|
-
private resolveClientSecret;
|
|
128
|
-
private normalizeClientAddress;
|
|
129
|
-
private clientIpMatchesCidr;
|
|
130
|
-
private ipv4ToNumber;
|
|
131
126
|
/**
|
|
132
127
|
* Add a RADIUS client
|
|
133
128
|
*/
|
|
@@ -14,7 +14,6 @@ export class RadiusServer {
|
|
|
14
14
|
vlanManager;
|
|
15
15
|
accountingManager;
|
|
16
16
|
config;
|
|
17
|
-
clientSecrets = new Map();
|
|
18
17
|
running = false;
|
|
19
18
|
// Statistics
|
|
20
19
|
stats = {
|
|
@@ -52,21 +51,16 @@ export class RadiusServer {
|
|
|
52
51
|
if (this.config.vlanAssignment?.mappings) {
|
|
53
52
|
await this.vlanManager.importMappings(this.config.vlanAssignment.mappings);
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
this.buildClientSecretsMap();
|
|
54
|
+
const cidrSecrets = this.buildClientSecretsMap();
|
|
57
55
|
// Create the RADIUS server
|
|
58
56
|
this.radiusServer = new plugins.smartradius.RadiusServer({
|
|
59
57
|
authPort: this.config.authPort,
|
|
60
58
|
acctPort: this.config.acctPort,
|
|
61
59
|
bindAddress: this.config.bindAddress,
|
|
62
|
-
|
|
60
|
+
cidrSecrets,
|
|
63
61
|
authenticationHandler: this.handleAuthentication.bind(this),
|
|
64
62
|
accountingHandler: this.handleAccounting.bind(this),
|
|
65
63
|
});
|
|
66
|
-
// Configure per-client secrets
|
|
67
|
-
for (const [ip, secret] of this.clientSecrets) {
|
|
68
|
-
this.radiusServer.setClientSecret(ip, secret);
|
|
69
|
-
}
|
|
70
64
|
// Start the server
|
|
71
65
|
await this.radiusServer.start();
|
|
72
66
|
this.running = true;
|
|
@@ -104,6 +98,7 @@ export class RadiusServer {
|
|
|
104
98
|
calledStationId: request.calledStationId,
|
|
105
99
|
callingStationId: request.callingStationId,
|
|
106
100
|
serviceType: request.serviceType !== undefined ? String(request.serviceType) : undefined,
|
|
101
|
+
framedMtu: request.framedMtu,
|
|
107
102
|
};
|
|
108
103
|
logger.log('debug', `RADIUS Auth Request: user=${authData.username}, NAS=${authData.nasIpAddress}`);
|
|
109
104
|
// Perform MAC Authentication Bypass (MAB)
|
|
@@ -173,6 +168,8 @@ export class RadiusServer {
|
|
|
173
168
|
outputPackets: request.outputPackets,
|
|
174
169
|
sessionTime: request.sessionTime,
|
|
175
170
|
terminateCause: request.terminateCause !== undefined ? String(request.terminateCause) : undefined,
|
|
171
|
+
framedIpAddress: request.framedIpAddress,
|
|
172
|
+
serviceType: request.serviceType !== undefined ? String(request.serviceType) : undefined,
|
|
176
173
|
};
|
|
177
174
|
try {
|
|
178
175
|
switch (statusType) {
|
|
@@ -263,61 +260,14 @@ export class RadiusServer {
|
|
|
263
260
|
* Build client secrets map from configuration
|
|
264
261
|
*/
|
|
265
262
|
buildClientSecretsMap() {
|
|
266
|
-
|
|
263
|
+
const cidrSecrets = {};
|
|
267
264
|
for (const client of this.config.clients) {
|
|
268
265
|
if (!client.enabled) {
|
|
269
266
|
continue;
|
|
270
267
|
}
|
|
271
|
-
|
|
272
|
-
this.clientSecrets.set(client.ipRange, client.secret);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
resolveClientSecret(clientAddress) {
|
|
277
|
-
const normalizedClientAddress = this.normalizeClientAddress(clientAddress);
|
|
278
|
-
if (!normalizedClientAddress)
|
|
279
|
-
return undefined;
|
|
280
|
-
const exactSecret = this.clientSecrets.get(normalizedClientAddress);
|
|
281
|
-
if (exactSecret !== undefined)
|
|
282
|
-
return exactSecret;
|
|
283
|
-
for (const client of this.config.clients) {
|
|
284
|
-
if (!client.enabled || !client.ipRange.includes('/'))
|
|
285
|
-
continue;
|
|
286
|
-
if (this.clientIpMatchesCidr(normalizedClientAddress, client.ipRange))
|
|
287
|
-
return client.secret;
|
|
268
|
+
cidrSecrets[client.ipRange] = client.secret;
|
|
288
269
|
}
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
normalizeClientAddress(clientAddress) {
|
|
292
|
-
const trimmedAddress = clientAddress.trim();
|
|
293
|
-
const normalizedAddress = trimmedAddress.startsWith('::ffff:')
|
|
294
|
-
? trimmedAddress.slice('::ffff:'.length)
|
|
295
|
-
: trimmedAddress;
|
|
296
|
-
return plugins.net.isIP(normalizedAddress) ? normalizedAddress : undefined;
|
|
297
|
-
}
|
|
298
|
-
clientIpMatchesCidr(clientAddress, cidr) {
|
|
299
|
-
const [networkAddress, rawPrefix] = cidr.trim().split('/');
|
|
300
|
-
const normalizedNetworkAddress = this.normalizeClientAddress(networkAddress || '');
|
|
301
|
-
if (!normalizedNetworkAddress || rawPrefix === undefined)
|
|
302
|
-
return false;
|
|
303
|
-
const clientIp = this.ipv4ToNumber(clientAddress);
|
|
304
|
-
const networkIp = this.ipv4ToNumber(normalizedNetworkAddress);
|
|
305
|
-
if (clientIp === undefined || networkIp === undefined)
|
|
306
|
-
return false;
|
|
307
|
-
const prefix = Number(rawPrefix);
|
|
308
|
-
if (!Number.isInteger(prefix) || prefix < 0 || prefix > 32)
|
|
309
|
-
return false;
|
|
310
|
-
const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
|
|
311
|
-
return ((clientIp & mask) >>> 0) === ((networkIp & mask) >>> 0);
|
|
312
|
-
}
|
|
313
|
-
ipv4ToNumber(ipAddress) {
|
|
314
|
-
if (plugins.net.isIP(ipAddress) !== 4)
|
|
315
|
-
return undefined;
|
|
316
|
-
const parts = ipAddress.split('.').map((part) => Number(part));
|
|
317
|
-
if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
|
|
318
|
-
return undefined;
|
|
319
|
-
}
|
|
320
|
-
return (((parts[0] * 256 + parts[1]) * 256 + parts[2]) * 256 + parts[3]) >>> 0;
|
|
270
|
+
return cidrSecrets;
|
|
321
271
|
}
|
|
322
272
|
/**
|
|
323
273
|
* Add a RADIUS client
|
|
@@ -325,15 +275,20 @@ export class RadiusServer {
|
|
|
325
275
|
async addClient(client) {
|
|
326
276
|
// Check if client already exists
|
|
327
277
|
const existingIndex = this.config.clients.findIndex(c => c.name === client.name);
|
|
278
|
+
const previousClient = existingIndex >= 0 ? this.config.clients[existingIndex] : undefined;
|
|
328
279
|
if (existingIndex >= 0) {
|
|
329
280
|
this.config.clients[existingIndex] = client;
|
|
330
281
|
}
|
|
331
282
|
else {
|
|
332
283
|
this.config.clients.push(client);
|
|
333
284
|
}
|
|
334
|
-
this.
|
|
335
|
-
|
|
336
|
-
|
|
285
|
+
if (this.running && this.radiusServer) {
|
|
286
|
+
if (previousClient) {
|
|
287
|
+
this.radiusServer.removeNetworkSecret(previousClient.ipRange);
|
|
288
|
+
}
|
|
289
|
+
if (client.enabled) {
|
|
290
|
+
this.radiusServer.setNetworkSecret(client.ipRange, client.secret);
|
|
291
|
+
}
|
|
337
292
|
}
|
|
338
293
|
logger.log('info', `RADIUS client ${client.enabled ? 'added' : 'disabled'}: ${client.name} (${client.ipRange})`);
|
|
339
294
|
}
|
|
@@ -345,9 +300,8 @@ export class RadiusServer {
|
|
|
345
300
|
if (index >= 0) {
|
|
346
301
|
const client = this.config.clients[index];
|
|
347
302
|
this.config.clients.splice(index, 1);
|
|
348
|
-
this.
|
|
349
|
-
|
|
350
|
-
this.radiusServer.removeClientSecret(client.ipRange);
|
|
303
|
+
if (this.radiusServer) {
|
|
304
|
+
this.radiusServer.removeNetworkSecret(client.ipRange);
|
|
351
305
|
}
|
|
352
306
|
logger.log('info', `RADIUS client removed: ${name}`);
|
|
353
307
|
return true;
|
|
@@ -395,4 +349,4 @@ export class RadiusServer {
|
|
|
395
349
|
return this.running;
|
|
396
350
|
}
|
|
397
351
|
}
|
|
398
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yYWRpdXMuc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcmFkaXVzL2NsYXNzZXMucmFkaXVzLnNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQWlELE1BQU0sMkJBQTJCLENBQUM7QUFDdkcsT0FBTyxFQUFFLGlCQUFpQixFQUEwRCxNQUFNLGlDQUFpQyxDQUFDO0FBOEU1SDs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUNmLFlBQVksQ0FBb0M7SUFDaEQsV0FBVyxDQUFjO0lBQ3pCLGlCQUFpQixDQUFvQjtJQUNyQyxNQUFNLENBQXNCO0lBQzVCLGFBQWEsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMvQyxPQUFPLEdBQVksS0FBSyxDQUFDO0lBRWpDLGFBQWE7SUFDTCxLQUFLLEdBQUc7UUFDZCxZQUFZLEVBQUUsQ0FBQztRQUNmLFdBQVcsRUFBRSxDQUFDO1FBQ2QsV0FBVyxFQUFFLENBQUM7UUFDZCxrQkFBa0IsRUFBRSxDQUFDO1FBQ3JCLFNBQVMsRUFBRSxDQUFDO0tBQ2IsQ0FBQztJQUVGLFlBQVksTUFBMkI7UUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxJQUFJLElBQUk7WUFDakMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLElBQUksSUFBSTtZQUNqQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsSUFBSSxTQUFTO1lBQzVDLEdBQUcsTUFBTTtTQUNWLENBQUM7UUFFRiwwQkFBMEI7UUFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFMUQsZ0NBQWdDO1FB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
|
|
352
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yYWRpdXMuc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcmFkaXVzL2NsYXNzZXMucmFkaXVzLnNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQWlELE1BQU0sMkJBQTJCLENBQUM7QUFDdkcsT0FBTyxFQUFFLGlCQUFpQixFQUEwRCxNQUFNLGlDQUFpQyxDQUFDO0FBOEU1SDs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUNmLFlBQVksQ0FBb0M7SUFDaEQsV0FBVyxDQUFjO0lBQ3pCLGlCQUFpQixDQUFvQjtJQUNyQyxNQUFNLENBQXNCO0lBQzVCLE9BQU8sR0FBWSxLQUFLLENBQUM7SUFFakMsYUFBYTtJQUNMLEtBQUssR0FBRztRQUNkLFlBQVksRUFBRSxDQUFDO1FBQ2YsV0FBVyxFQUFFLENBQUM7UUFDZCxXQUFXLEVBQUUsQ0FBQztRQUNkLGtCQUFrQixFQUFFLENBQUM7UUFDckIsU0FBUyxFQUFFLENBQUM7S0FDYixDQUFDO0lBRUYsWUFBWSxNQUEyQjtRQUNyQyxJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ1osUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLElBQUksSUFBSTtZQUNqQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJO1lBQ2pDLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVyxJQUFJLFNBQVM7WUFDNUMsR0FBRyxNQUFNO1NBQ1YsQ0FBQztRQUVGLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUUxRCxnQ0FBZ0M7UUFDaEMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksaUJBQWlC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
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/dcrouter',
|
|
6
|
-
version: '13.
|
|
6
|
+
version: '13.40.0',
|
|
7
7
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsc0JBQXNCO0lBQzVCLE9BQU8sRUFBRSxTQUFTO0lBQ2xCLFdBQVcsRUFBRSwwRUFBMEU7Q0FDeEYsQ0FBQSJ9
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.40.0",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"@push.rocks/smartnetwork": "^4.7.2",
|
|
51
51
|
"@push.rocks/smartpath": "^6.0.0",
|
|
52
52
|
"@push.rocks/smartpromise": "^4.2.4",
|
|
53
|
-
"@push.rocks/smartproxy": "^27.
|
|
54
|
-
"@push.rocks/smartradius": "^1.
|
|
53
|
+
"@push.rocks/smartproxy": "^27.12.1",
|
|
54
|
+
"@push.rocks/smartradius": "^1.3.0",
|
|
55
55
|
"@push.rocks/smartrequest": "^5.0.3",
|
|
56
56
|
"@push.rocks/smartrx": "^3.0.10",
|
|
57
57
|
"@push.rocks/smartstate": "^2.3.1",
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -143,8 +143,9 @@ export class MetricsManager {
|
|
|
143
143
|
public async getServerStats() {
|
|
144
144
|
return this.metricsCache.get('serverStats', async () => {
|
|
145
145
|
const smartMetricsData = await this.smartMetrics.getMetrics();
|
|
146
|
-
const
|
|
147
|
-
const
|
|
146
|
+
const smartProxy = this.dcRouter.smartProxy;
|
|
147
|
+
const proxyMetrics = smartProxy ? smartProxy.getMetrics() : null;
|
|
148
|
+
const proxyStats = smartProxy ? await smartProxy.getStatistics() : null;
|
|
148
149
|
const { heapUsed, heapTotal, external, rss } = process.memoryUsage();
|
|
149
150
|
|
|
150
151
|
return {
|
|
@@ -291,27 +292,44 @@ export class MetricsManager {
|
|
|
291
292
|
});
|
|
292
293
|
}
|
|
293
294
|
|
|
295
|
+
public async getActiveConnectionSnapshots(
|
|
296
|
+
options: plugins.smartproxy.IActiveConnectionSnapshotOptions = {},
|
|
297
|
+
): Promise<plugins.smartproxy.IActiveConnectionSnapshot[]> {
|
|
298
|
+
const cacheKey = `activeConnectionSnapshots:${options.limit ?? 1000}:${options.routeId ?? ''}`;
|
|
299
|
+
return await this.metricsCache.get<plugins.smartproxy.IActiveConnectionSnapshot[]>(cacheKey, async () => {
|
|
300
|
+
if (!this.dcRouter.smartProxy) {
|
|
301
|
+
return [];
|
|
302
|
+
}
|
|
303
|
+
return this.dcRouter.smartProxy.getActiveConnectionSnapshots(options);
|
|
304
|
+
}, 500);
|
|
305
|
+
}
|
|
306
|
+
|
|
294
307
|
// Get connection info from SmartProxy
|
|
295
308
|
public async getConnectionInfo() {
|
|
296
|
-
return this.metricsCache.get('connectionInfo', () => {
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
309
|
+
return this.metricsCache.get('connectionInfo', async () => {
|
|
310
|
+
const snapshots = await this.getActiveConnectionSnapshots({ limit: 10000 });
|
|
311
|
+
const connectionsByRoute = new Map<string, { count: number; lastActivity: Date }>();
|
|
312
|
+
|
|
313
|
+
for (const snapshot of snapshots) {
|
|
314
|
+
const source = snapshot.routeId || snapshot.domain || `${snapshot.protocol || 'connection'}:${snapshot.localPort}`;
|
|
315
|
+
const existing = connectionsByRoute.get(source) || { count: 0, lastActivity: new Date(snapshot.startedAtMs) };
|
|
316
|
+
existing.count++;
|
|
317
|
+
if (snapshot.startedAtMs > existing.lastActivity.getTime()) {
|
|
318
|
+
existing.lastActivity = new Date(snapshot.startedAtMs);
|
|
319
|
+
}
|
|
320
|
+
connectionsByRoute.set(source, existing);
|
|
301
321
|
}
|
|
302
322
|
|
|
303
|
-
const connectionsByRoute = proxyMetrics.connections.byRoute();
|
|
304
323
|
const connectionInfo: Array<{ type: string; count: number; source: string; lastActivity: Date }> = [];
|
|
305
|
-
|
|
306
|
-
for (const [routeName, count] of connectionsByRoute) {
|
|
324
|
+
for (const [source, info] of connectionsByRoute) {
|
|
307
325
|
connectionInfo.push({
|
|
308
326
|
type: 'https',
|
|
309
|
-
count,
|
|
310
|
-
source
|
|
311
|
-
lastActivity:
|
|
327
|
+
count: info.count,
|
|
328
|
+
source,
|
|
329
|
+
lastActivity: info.lastActivity,
|
|
312
330
|
});
|
|
313
331
|
}
|
|
314
|
-
|
|
332
|
+
|
|
315
333
|
return connectionInfo;
|
|
316
334
|
});
|
|
317
335
|
}
|
|
@@ -547,7 +565,8 @@ export class MetricsManager {
|
|
|
547
565
|
public async getNetworkStats() {
|
|
548
566
|
// Use shorter cache TTL for network stats to ensure real-time updates
|
|
549
567
|
return this.metricsCache.get('networkStats', async () => {
|
|
550
|
-
const
|
|
568
|
+
const smartProxy = this.dcRouter.smartProxy;
|
|
569
|
+
const proxyMetrics = smartProxy ? smartProxy.getMetrics() : null;
|
|
551
570
|
|
|
552
571
|
if (!proxyMetrics) {
|
|
553
572
|
return {
|
|
@@ -568,8 +587,22 @@ export class MetricsManager {
|
|
|
568
587
|
};
|
|
569
588
|
}
|
|
570
589
|
|
|
571
|
-
|
|
572
|
-
|
|
590
|
+
const activeConnectionSnapshots = await this.getActiveConnectionSnapshots({ limit: 10000 });
|
|
591
|
+
|
|
592
|
+
const connectionsByIP = new Map<string, number>();
|
|
593
|
+
const connectionsByRoute = new Map<string, number>();
|
|
594
|
+
const activeConnectionsByDomain = new Map<string, number>();
|
|
595
|
+
|
|
596
|
+
for (const snapshot of activeConnectionSnapshots) {
|
|
597
|
+
connectionsByIP.set(snapshot.sourceIp, (connectionsByIP.get(snapshot.sourceIp) || 0) + 1);
|
|
598
|
+
if (snapshot.routeId) {
|
|
599
|
+
connectionsByRoute.set(snapshot.routeId, (connectionsByRoute.get(snapshot.routeId) || 0) + 1);
|
|
600
|
+
}
|
|
601
|
+
if (snapshot.domain) {
|
|
602
|
+
activeConnectionsByDomain.set(snapshot.domain, (activeConnectionsByDomain.get(snapshot.domain) || 0) + 1);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
573
606
|
const instantThroughput = proxyMetrics.throughput.instant();
|
|
574
607
|
|
|
575
608
|
// Get throughput rate
|
|
@@ -578,8 +611,11 @@ export class MetricsManager {
|
|
|
578
611
|
bytesOutPerSecond: instantThroughput.out
|
|
579
612
|
};
|
|
580
613
|
|
|
581
|
-
// Get top IPs by connection count
|
|
582
|
-
const topIPs =
|
|
614
|
+
// Get top IPs by active connection count
|
|
615
|
+
const topIPs = Array.from(connectionsByIP.entries())
|
|
616
|
+
.sort((a, b) => b[1] - a[1])
|
|
617
|
+
.slice(0, 10)
|
|
618
|
+
.map(([ip, count]) => ({ ip, count }));
|
|
583
619
|
|
|
584
620
|
// Get total data transferred
|
|
585
621
|
const totalDataTransferred = {
|
|
@@ -738,7 +774,6 @@ export class MetricsManager {
|
|
|
738
774
|
const topASNs = await this.buildTopASNs(observedIps, allIPData);
|
|
739
775
|
|
|
740
776
|
// Build domain activity using per-IP domain request counts from Rust engine
|
|
741
|
-
const connectionsByRoute = proxyMetrics.connections.byRoute();
|
|
742
777
|
const throughputByRoute = proxyMetrics.throughput.byRoute();
|
|
743
778
|
|
|
744
779
|
// Aggregate per-IP domain request counts into per-domain totals
|
|
@@ -773,6 +808,9 @@ export class MetricsManager {
|
|
|
773
808
|
for (const entry of protocolCache) {
|
|
774
809
|
if (entry.domain) allKnownDomains.add(entry.domain);
|
|
775
810
|
}
|
|
811
|
+
for (const snapshot of activeConnectionSnapshots) {
|
|
812
|
+
if (snapshot.domain) allKnownDomains.add(snapshot.domain);
|
|
813
|
+
}
|
|
776
814
|
|
|
777
815
|
// Build reverse map: concrete domain → canonical route key(s)
|
|
778
816
|
const domainToRoutes = new Map<string, string[]>();
|
|
@@ -844,7 +882,7 @@ export class MetricsManager {
|
|
|
844
882
|
}
|
|
845
883
|
|
|
846
884
|
domainAgg.set(domain, {
|
|
847
|
-
activeConnections: Math.round(totalConns),
|
|
885
|
+
activeConnections: activeConnectionsByDomain.get(domain) ?? Math.round(totalConns),
|
|
848
886
|
bytesInPerSec: totalIn,
|
|
849
887
|
bytesOutPerSec: totalOut,
|
|
850
888
|
routeCount: routeKeys.length,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
3
|
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
-
import { MetricsManager } from '../../monitoring/index.js';
|
|
5
4
|
import { requireOpsAuth } from '../helpers/auth.js';
|
|
6
5
|
|
|
7
6
|
export class SecurityHandler {
|
|
@@ -46,18 +45,7 @@ export class SecurityHandler {
|
|
|
46
45
|
'getActiveConnections',
|
|
47
46
|
async (dataArg, toolsArg) => {
|
|
48
47
|
await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
|
|
49
|
-
const
|
|
50
|
-
const connectionInfos: interfaces.data.IConnectionInfo[] = connections.map(conn => ({
|
|
51
|
-
id: conn.id,
|
|
52
|
-
remoteAddress: conn.source.ip,
|
|
53
|
-
localAddress: conn.destination.ip,
|
|
54
|
-
startTime: conn.startTime,
|
|
55
|
-
protocol: conn.type === 'http' ? 'https' : conn.type as any,
|
|
56
|
-
state: conn.status === 'active' ? 'connected' : conn.status as any,
|
|
57
|
-
bytesReceived: (conn as any)._throughputIn || 0,
|
|
58
|
-
bytesSent: (conn as any)._throughputOut || 0,
|
|
59
|
-
connectionCount: conn.bytesTransferred || 1,
|
|
60
|
-
}));
|
|
48
|
+
const connectionInfos = await this.getActiveConnections(dataArg.protocol, dataArg.state);
|
|
61
49
|
const totalConnections = connectionInfos.reduce((sum, conn) => sum + (conn.connectionCount || 1), 0);
|
|
62
50
|
|
|
63
51
|
const summary = {
|
|
@@ -362,106 +350,66 @@ export class SecurityHandler {
|
|
|
362
350
|
private async getActiveConnections(
|
|
363
351
|
protocol?: 'http' | 'https' | 'smtp' | 'smtps',
|
|
364
352
|
state?: string
|
|
365
|
-
): Promise<
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
port: number;
|
|
371
|
-
country?: string;
|
|
372
|
-
};
|
|
373
|
-
destination: {
|
|
374
|
-
ip: string;
|
|
375
|
-
port: number;
|
|
376
|
-
service?: string;
|
|
377
|
-
};
|
|
378
|
-
startTime: number;
|
|
379
|
-
bytesTransferred: number;
|
|
380
|
-
status: 'active' | 'idle' | 'closing';
|
|
381
|
-
}>> {
|
|
382
|
-
const connections: Array<{
|
|
383
|
-
id: string;
|
|
384
|
-
type: 'http' | 'smtp' | 'dns';
|
|
385
|
-
source: {
|
|
386
|
-
ip: string;
|
|
387
|
-
port: number;
|
|
388
|
-
country?: string;
|
|
389
|
-
};
|
|
390
|
-
destination: {
|
|
391
|
-
ip: string;
|
|
392
|
-
port: number;
|
|
393
|
-
service?: string;
|
|
394
|
-
};
|
|
395
|
-
startTime: number;
|
|
396
|
-
bytesTransferred: number;
|
|
397
|
-
status: 'active' | 'idle' | 'closing';
|
|
398
|
-
}> = [];
|
|
399
|
-
|
|
400
|
-
// Get connection info and network stats from MetricsManager if available
|
|
401
|
-
if (this.opsServerRef.dcRouterRef.metricsManager) {
|
|
402
|
-
const connectionInfo = await this.opsServerRef.dcRouterRef.metricsManager.getConnectionInfo();
|
|
403
|
-
const networkStats = await this.opsServerRef.dcRouterRef.metricsManager.getNetworkStats();
|
|
404
|
-
|
|
405
|
-
// One aggregate row per IP with real throughput data
|
|
406
|
-
if (networkStats.connectionsByIP && networkStats.connectionsByIP.size > 0) {
|
|
407
|
-
let connIndex = 0;
|
|
408
|
-
const publicIp = this.opsServerRef.dcRouterRef.options.publicIp || 'server';
|
|
353
|
+
): Promise<interfaces.data.IConnectionInfo[]> {
|
|
354
|
+
const metricsManager = this.opsServerRef.dcRouterRef.metricsManager;
|
|
355
|
+
if (!metricsManager) {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
409
358
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
// Fallback to route-based connection info if no IP data available
|
|
433
|
-
connectionInfo.forEach((info, index) => {
|
|
434
|
-
connections.push({
|
|
435
|
-
id: `conn-${index}`,
|
|
436
|
-
type: 'http',
|
|
437
|
-
source: {
|
|
438
|
-
ip: 'unknown',
|
|
439
|
-
port: 0,
|
|
440
|
-
},
|
|
441
|
-
destination: {
|
|
442
|
-
ip: this.opsServerRef.dcRouterRef.options.publicIp || 'server',
|
|
443
|
-
port: 443,
|
|
444
|
-
service: info.source,
|
|
445
|
-
},
|
|
446
|
-
startTime: info.lastActivity.getTime(),
|
|
447
|
-
bytesTransferred: 0,
|
|
448
|
-
status: 'active',
|
|
449
|
-
});
|
|
450
|
-
});
|
|
359
|
+
const snapshots = await metricsManager.getActiveConnectionSnapshots({ limit: 10000 });
|
|
360
|
+
const connections = snapshots.map((snapshot): interfaces.data.IConnectionInfo => ({
|
|
361
|
+
id: String(snapshot.id),
|
|
362
|
+
remoteAddress: snapshot.sourcePort === null
|
|
363
|
+
? snapshot.sourceIp
|
|
364
|
+
: `${snapshot.sourceIp}:${snapshot.sourcePort}`,
|
|
365
|
+
localAddress: snapshot.targetHost
|
|
366
|
+
? `${snapshot.targetHost}:${snapshot.targetPort ?? snapshot.localPort}`
|
|
367
|
+
: `${this.opsServerRef.dcRouterRef.options.publicIp || 'server'}:${snapshot.localPort}`,
|
|
368
|
+
startTime: snapshot.startedAtMs,
|
|
369
|
+
protocol: this.mapSnapshotProtocol(snapshot),
|
|
370
|
+
state: this.mapSnapshotState(snapshot.state),
|
|
371
|
+
bytesReceived: snapshot.bytesIn,
|
|
372
|
+
bytesSent: snapshot.bytesOut,
|
|
373
|
+
}));
|
|
374
|
+
|
|
375
|
+
return connections.filter((connection) => {
|
|
376
|
+
if (protocol && connection.protocol !== protocol) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
if (state && connection.state !== state) {
|
|
380
|
+
return false;
|
|
451
381
|
}
|
|
382
|
+
return true;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private mapSnapshotProtocol(
|
|
387
|
+
snapshot: plugins.smartproxy.IActiveConnectionSnapshot,
|
|
388
|
+
): interfaces.data.IConnectionInfo['protocol'] {
|
|
389
|
+
if (snapshot.localPort === 465) {
|
|
390
|
+
return 'smtps';
|
|
452
391
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (protocol) {
|
|
456
|
-
return connections.filter(conn => {
|
|
457
|
-
if (protocol === 'https' || protocol === 'http') {
|
|
458
|
-
return conn.type === 'http';
|
|
459
|
-
}
|
|
460
|
-
return conn.type === protocol.replace('s', ''); // smtp/smtps -> smtp
|
|
461
|
-
});
|
|
392
|
+
if ([25, 587, 2525].includes(snapshot.localPort)) {
|
|
393
|
+
return 'smtp';
|
|
462
394
|
}
|
|
463
|
-
|
|
464
|
-
|
|
395
|
+
|
|
396
|
+
switch (snapshot.protocol) {
|
|
397
|
+
case 'http':
|
|
398
|
+
return 'http';
|
|
399
|
+
case 'https':
|
|
400
|
+
case 'tls':
|
|
401
|
+
case 'tls-passthrough':
|
|
402
|
+
case 'tls-reencrypt':
|
|
403
|
+
case 'tls-socket-handler':
|
|
404
|
+
case 'quic':
|
|
405
|
+
return 'https';
|
|
406
|
+
default:
|
|
407
|
+
return snapshot.localPort === 80 ? 'http' : 'https';
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
private mapSnapshotState(state: string): interfaces.data.IConnectionInfo['state'] {
|
|
412
|
+
return state === 'closing' ? 'closing' : 'connected';
|
|
465
413
|
}
|
|
466
414
|
|
|
467
415
|
private async getRateLimitStatus(
|