@serve.zone/dcrouter 11.0.4 → 11.0.5
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/dist_serve/bundle.js +1 -1
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/dist_ts/00_commitinfo_data.d.ts +0 -8
- package/dist_ts/00_commitinfo_data.js +0 -9
- package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
- package/dist_ts/cache/classes.cache.cleaner.js +0 -130
- package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
- package/dist_ts/cache/documents/classes.cached.email.js +0 -337
- package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
- package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
- package/dist_ts/cache/documents/index.d.ts +0 -2
- package/dist_ts/cache/documents/index.js +0 -3
- package/dist_ts/cache/index.d.ts +0 -4
- package/dist_ts/cache/index.js +0 -7
- package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -53
- package/dist_ts/classes.cert-provision-scheduler.js +0 -110
- package/dist_ts/classes.dcrouter.d.ts +0 -337
- package/dist_ts/classes.dcrouter.js +0 -1405
- package/dist_ts/classes.storage-cert-manager.d.ts +0 -18
- package/dist_ts/classes.storage-cert-manager.js +0 -43
- package/dist_ts/config/classes.api-token-manager.d.ts +0 -46
- package/dist_ts/config/classes.api-token-manager.js +0 -150
- package/dist_ts/config/classes.route-config-manager.d.ts +0 -35
- package/dist_ts/config/classes.route-config-manager.js +0 -231
- package/dist_ts/config/index.d.ts +0 -3
- package/dist_ts/config/index.js +0 -5
- package/dist_ts/config/validator.d.ts +0 -104
- package/dist_ts/config/validator.js +0 -152
- package/dist_ts/errors/base.errors.d.ts +0 -224
- package/dist_ts/errors/base.errors.js +0 -320
- package/dist_ts/errors/error-handler.d.ts +0 -98
- package/dist_ts/errors/error-handler.js +0 -282
- package/dist_ts/errors/error.codes.d.ts +0 -115
- package/dist_ts/errors/error.codes.js +0 -136
- package/dist_ts/errors/index.d.ts +0 -54
- package/dist_ts/errors/index.js +0 -136
- package/dist_ts/errors/reputation.errors.d.ts +0 -183
- package/dist_ts/errors/reputation.errors.js +0 -292
- package/dist_ts/index.d.ts +0 -7
- package/dist_ts/index.js +0 -11
- package/dist_ts/logger.d.ts +0 -21
- package/dist_ts/logger.js +0 -81
- package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
- package/dist_ts/monitoring/classes.metricscache.js +0 -63
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -178
- package/dist_ts/monitoring/classes.metricsmanager.js +0 -642
- package/dist_ts/monitoring/index.d.ts +0 -1
- package/dist_ts/monitoring/index.js +0 -2
- package/dist_ts/opsserver/classes.opsserver.d.ts +0 -37
- package/dist_ts/opsserver/classes.opsserver.js +0 -85
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
- package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
- package/dist_ts/opsserver/handlers/api-token.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/api-token.handler.js +0 -62
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -32
- package/dist_ts/opsserver/handlers/certificate.handler.js +0 -421
- package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
- package/dist_ts/opsserver/handlers/config.handler.js +0 -192
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +0 -30
- package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -227
- package/dist_ts/opsserver/handlers/index.d.ts +0 -11
- package/dist_ts/opsserver/handlers/index.js +0 -12
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
- package/dist_ts/opsserver/handlers/logs.handler.js +0 -256
- package/dist_ts/opsserver/handlers/radius.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/radius.handler.js +0 -295
- package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -156
- package/dist_ts/opsserver/handlers/route-management.handler.d.ts +0 -14
- package/dist_ts/opsserver/handlers/route-management.handler.js +0 -117
- package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -9
- package/dist_ts/opsserver/handlers/security.handler.js +0 -231
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -11
- package/dist_ts/opsserver/handlers/stats.handler.js +0 -399
- package/dist_ts/opsserver/helpers/guards.d.ts +0 -27
- package/dist_ts/opsserver/helpers/guards.js +0 -43
- package/dist_ts/opsserver/index.d.ts +0 -1
- package/dist_ts/opsserver/index.js +0 -2
- package/dist_ts/paths.d.ts +0 -26
- package/dist_ts/paths.js +0 -45
- package/dist_ts/plugins.d.ts +0 -79
- package/dist_ts/plugins.js +0 -113
- package/dist_ts/radius/classes.accounting.manager.d.ts +0 -218
- package/dist_ts/radius/classes.accounting.manager.js +0 -417
- package/dist_ts/radius/classes.radius.server.d.ts +0 -171
- package/dist_ts/radius/classes.radius.server.js +0 -385
- package/dist_ts/radius/classes.vlan.manager.d.ts +0 -128
- package/dist_ts/radius/classes.vlan.manager.js +0 -279
- package/dist_ts/radius/index.d.ts +0 -13
- package/dist_ts/radius/index.js +0 -14
- package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +0 -82
- package/dist_ts/remoteingress/classes.remoteingress-manager.js +0 -227
- package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +0 -59
- package/dist_ts/remoteingress/classes.tunnel-manager.js +0 -165
- package/dist_ts/remoteingress/index.d.ts +0 -2
- package/dist_ts/remoteingress/index.js +0 -3
- package/dist_ts/security/classes.contentscanner.d.ts +0 -164
- package/dist_ts/security/classes.contentscanner.js +0 -642
- package/dist_ts/security/classes.ipreputationchecker.d.ts +0 -160
- package/dist_ts/security/classes.ipreputationchecker.js +0 -537
- package/dist_ts/security/classes.securitylogger.d.ts +0 -144
- package/dist_ts/security/classes.securitylogger.js +0 -233
- package/dist_ts/security/index.d.ts +0 -3
- package/dist_ts/security/index.js +0 -4
- package/dist_ts/sms/classes.smsservice.d.ts +0 -15
- package/dist_ts/sms/classes.smsservice.js +0 -72
- package/dist_ts/sms/config/sms.config.d.ts +0 -93
- package/dist_ts/sms/config/sms.config.js +0 -2
- package/dist_ts/sms/config/sms.schema.d.ts +0 -5
- package/dist_ts/sms/config/sms.schema.js +0 -121
- package/dist_ts/sms/index.d.ts +0 -1
- package/dist_ts/sms/index.js +0 -2
- package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
- package/dist_ts/storage/classes.storagemanager.js +0 -350
- package/dist_ts/storage/index.d.ts +0 -1
- package/dist_ts/storage/index.js +0 -3
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
|
-
import { logger } from '../logger.js';
|
|
3
|
-
/**
|
|
4
|
-
* Manages MAC address to VLAN mappings with support for:
|
|
5
|
-
* - Exact MAC address matching
|
|
6
|
-
* - OUI (vendor prefix) pattern matching
|
|
7
|
-
* - Wildcard patterns
|
|
8
|
-
* - Default VLAN for unknown devices
|
|
9
|
-
*/
|
|
10
|
-
export class VlanManager {
|
|
11
|
-
mappings = new Map();
|
|
12
|
-
config;
|
|
13
|
-
storageManager;
|
|
14
|
-
// Cache for normalized MAC lookups
|
|
15
|
-
normalizedMacCache = new Map();
|
|
16
|
-
constructor(config, storageManager) {
|
|
17
|
-
this.config = {
|
|
18
|
-
defaultVlan: config?.defaultVlan ?? 1,
|
|
19
|
-
allowUnknownMacs: config?.allowUnknownMacs ?? true,
|
|
20
|
-
storagePrefix: config?.storagePrefix ?? '/radius/vlan-mappings',
|
|
21
|
-
};
|
|
22
|
-
this.storageManager = storageManager;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Initialize the VLAN manager and load persisted mappings
|
|
26
|
-
*/
|
|
27
|
-
async initialize() {
|
|
28
|
-
if (this.storageManager) {
|
|
29
|
-
await this.loadMappings();
|
|
30
|
-
}
|
|
31
|
-
logger.log('info', `VlanManager initialized with ${this.mappings.size} mappings, default VLAN: ${this.config.defaultVlan}`);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Normalize a MAC address to lowercase with colons
|
|
35
|
-
* Accepts formats: 00:11:22:33:44:55, 00-11-22-33-44-55, 001122334455
|
|
36
|
-
*/
|
|
37
|
-
normalizeMac(mac) {
|
|
38
|
-
// Check cache first
|
|
39
|
-
const cached = this.normalizedMacCache.get(mac);
|
|
40
|
-
if (cached) {
|
|
41
|
-
return cached;
|
|
42
|
-
}
|
|
43
|
-
// Remove all separators and convert to lowercase
|
|
44
|
-
const cleaned = mac.toLowerCase().replace(/[-:]/g, '');
|
|
45
|
-
// Format with colons
|
|
46
|
-
const normalized = cleaned.match(/.{1,2}/g)?.join(':') || mac.toLowerCase();
|
|
47
|
-
// Cache the result
|
|
48
|
-
this.normalizedMacCache.set(mac, normalized);
|
|
49
|
-
// Prevent unbounded cache growth
|
|
50
|
-
if (this.normalizedMacCache.size > 10000) {
|
|
51
|
-
const iterator = this.normalizedMacCache.keys();
|
|
52
|
-
for (let i = 0; i < 1000; i++) {
|
|
53
|
-
this.normalizedMacCache.delete(iterator.next().value);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return normalized;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Check if a MAC address matches a pattern
|
|
60
|
-
* Supports:
|
|
61
|
-
* - Exact match: "00:11:22:33:44:55"
|
|
62
|
-
* - OUI match: "00:11:22" (matches any device with this vendor prefix)
|
|
63
|
-
* - Wildcard: "*" (matches all)
|
|
64
|
-
*/
|
|
65
|
-
macMatchesPattern(mac, pattern) {
|
|
66
|
-
const normalizedMac = this.normalizeMac(mac);
|
|
67
|
-
const normalizedPattern = this.normalizeMac(pattern);
|
|
68
|
-
// Wildcard matches all
|
|
69
|
-
if (pattern === '*') {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
// Exact match
|
|
73
|
-
if (normalizedMac === normalizedPattern) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
// OUI/prefix match (pattern is shorter than full MAC)
|
|
77
|
-
if (normalizedPattern.length < 17 && normalizedMac.startsWith(normalizedPattern)) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Add or update a MAC to VLAN mapping
|
|
84
|
-
*/
|
|
85
|
-
async addMapping(mapping) {
|
|
86
|
-
const normalizedMac = this.normalizeMac(mapping.mac);
|
|
87
|
-
const now = Date.now();
|
|
88
|
-
const existingMapping = this.mappings.get(normalizedMac);
|
|
89
|
-
const fullMapping = {
|
|
90
|
-
...mapping,
|
|
91
|
-
mac: normalizedMac,
|
|
92
|
-
createdAt: existingMapping?.createdAt || now,
|
|
93
|
-
updatedAt: now,
|
|
94
|
-
};
|
|
95
|
-
this.mappings.set(normalizedMac, fullMapping);
|
|
96
|
-
// Persist to storage
|
|
97
|
-
if (this.storageManager) {
|
|
98
|
-
await this.saveMappings();
|
|
99
|
-
}
|
|
100
|
-
logger.log('info', `VLAN mapping ${existingMapping ? 'updated' : 'added'}: ${normalizedMac} -> VLAN ${mapping.vlan}`);
|
|
101
|
-
return fullMapping;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Remove a MAC to VLAN mapping
|
|
105
|
-
*/
|
|
106
|
-
async removeMapping(mac) {
|
|
107
|
-
const normalizedMac = this.normalizeMac(mac);
|
|
108
|
-
const removed = this.mappings.delete(normalizedMac);
|
|
109
|
-
if (removed && this.storageManager) {
|
|
110
|
-
await this.saveMappings();
|
|
111
|
-
logger.log('info', `VLAN mapping removed: ${normalizedMac}`);
|
|
112
|
-
}
|
|
113
|
-
return removed;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Get a specific mapping by MAC
|
|
117
|
-
*/
|
|
118
|
-
getMapping(mac) {
|
|
119
|
-
return this.mappings.get(this.normalizeMac(mac));
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Get all mappings
|
|
123
|
-
*/
|
|
124
|
-
getAllMappings() {
|
|
125
|
-
return Array.from(this.mappings.values());
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Determine VLAN assignment for a MAC address
|
|
129
|
-
* Returns the most specific matching rule (exact > OUI > wildcard > default)
|
|
130
|
-
*/
|
|
131
|
-
assignVlan(mac) {
|
|
132
|
-
const normalizedMac = this.normalizeMac(mac);
|
|
133
|
-
// First, try exact match
|
|
134
|
-
const exactMatch = this.mappings.get(normalizedMac);
|
|
135
|
-
if (exactMatch && exactMatch.enabled) {
|
|
136
|
-
return {
|
|
137
|
-
assigned: true,
|
|
138
|
-
vlan: exactMatch.vlan,
|
|
139
|
-
matchedRule: exactMatch,
|
|
140
|
-
isDefault: false,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
// Try OUI/prefix matches (sorted by specificity - longer patterns first)
|
|
144
|
-
const patternMatches = [];
|
|
145
|
-
for (const mapping of this.mappings.values()) {
|
|
146
|
-
if (mapping.enabled && mapping.mac !== normalizedMac && this.macMatchesPattern(normalizedMac, mapping.mac)) {
|
|
147
|
-
patternMatches.push(mapping);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// Sort by pattern length (most specific first)
|
|
151
|
-
patternMatches.sort((a, b) => b.mac.length - a.mac.length);
|
|
152
|
-
if (patternMatches.length > 0) {
|
|
153
|
-
const bestMatch = patternMatches[0];
|
|
154
|
-
return {
|
|
155
|
-
assigned: true,
|
|
156
|
-
vlan: bestMatch.vlan,
|
|
157
|
-
matchedRule: bestMatch,
|
|
158
|
-
isDefault: false,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
// No match - use default VLAN if allowed
|
|
162
|
-
if (this.config.allowUnknownMacs) {
|
|
163
|
-
return {
|
|
164
|
-
assigned: true,
|
|
165
|
-
vlan: this.config.defaultVlan,
|
|
166
|
-
isDefault: true,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
// Unknown MAC and not allowed
|
|
170
|
-
return {
|
|
171
|
-
assigned: false,
|
|
172
|
-
vlan: 0,
|
|
173
|
-
isDefault: false,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Bulk import mappings
|
|
178
|
-
*/
|
|
179
|
-
async importMappings(mappings) {
|
|
180
|
-
let imported = 0;
|
|
181
|
-
for (const mapping of mappings) {
|
|
182
|
-
await this.addMapping(mapping);
|
|
183
|
-
imported++;
|
|
184
|
-
}
|
|
185
|
-
logger.log('info', `Imported ${imported} VLAN mappings`);
|
|
186
|
-
return imported;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Export all mappings
|
|
190
|
-
*/
|
|
191
|
-
exportMappings() {
|
|
192
|
-
return this.getAllMappings();
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Update configuration
|
|
196
|
-
*/
|
|
197
|
-
updateConfig(config) {
|
|
198
|
-
if (config.defaultVlan !== undefined) {
|
|
199
|
-
this.config.defaultVlan = config.defaultVlan;
|
|
200
|
-
}
|
|
201
|
-
if (config.allowUnknownMacs !== undefined) {
|
|
202
|
-
this.config.allowUnknownMacs = config.allowUnknownMacs;
|
|
203
|
-
}
|
|
204
|
-
logger.log('info', `VlanManager config updated: defaultVlan=${this.config.defaultVlan}, allowUnknown=${this.config.allowUnknownMacs}`);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Get current configuration
|
|
208
|
-
*/
|
|
209
|
-
getConfig() {
|
|
210
|
-
return { ...this.config };
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Get statistics
|
|
214
|
-
*/
|
|
215
|
-
getStats() {
|
|
216
|
-
let exactMatches = 0;
|
|
217
|
-
let ouiPatterns = 0;
|
|
218
|
-
let wildcardPatterns = 0;
|
|
219
|
-
let enabledMappings = 0;
|
|
220
|
-
for (const mapping of this.mappings.values()) {
|
|
221
|
-
if (mapping.enabled) {
|
|
222
|
-
enabledMappings++;
|
|
223
|
-
}
|
|
224
|
-
if (mapping.mac === '*') {
|
|
225
|
-
wildcardPatterns++;
|
|
226
|
-
}
|
|
227
|
-
else if (mapping.mac.length < 17) {
|
|
228
|
-
// OUI patterns are shorter than full MAC (17 chars with colons)
|
|
229
|
-
ouiPatterns++;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
exactMatches++;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return {
|
|
236
|
-
totalMappings: this.mappings.size,
|
|
237
|
-
enabledMappings,
|
|
238
|
-
exactMatches,
|
|
239
|
-
ouiPatterns,
|
|
240
|
-
wildcardPatterns,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Load mappings from storage
|
|
245
|
-
*/
|
|
246
|
-
async loadMappings() {
|
|
247
|
-
if (!this.storageManager) {
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
try {
|
|
251
|
-
const data = await this.storageManager.getJSON(this.config.storagePrefix);
|
|
252
|
-
if (data && Array.isArray(data)) {
|
|
253
|
-
for (const mapping of data) {
|
|
254
|
-
this.mappings.set(this.normalizeMac(mapping.mac), mapping);
|
|
255
|
-
}
|
|
256
|
-
logger.log('info', `Loaded ${data.length} VLAN mappings from storage`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
catch (error) {
|
|
260
|
-
logger.log('warn', `Failed to load VLAN mappings from storage: ${error.message}`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Save mappings to storage
|
|
265
|
-
*/
|
|
266
|
-
async saveMappings() {
|
|
267
|
-
if (!this.storageManager) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
const mappings = Array.from(this.mappings.values());
|
|
272
|
-
await this.storageManager.setJSON(this.config.storagePrefix, mappings);
|
|
273
|
-
}
|
|
274
|
-
catch (error) {
|
|
275
|
-
logger.log('error', `Failed to save VLAN mappings to storage: ${error.message}`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy52bGFuLm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9yYWRpdXMvY2xhc3Nlcy52bGFuLm1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQStDdEM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDZCxRQUFRLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDbkQsTUFBTSxDQUErQjtJQUNyQyxjQUFjLENBQWtCO0lBRXhDLG1DQUFtQztJQUMzQixrQkFBa0IsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUU1RCxZQUFZLE1BQTJCLEVBQUUsY0FBK0I7UUFDdEUsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLFdBQVcsRUFBRSxNQUFNLEVBQUUsV0FBVyxJQUFJLENBQUM7WUFDckMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixJQUFJLElBQUk7WUFDbEQsYUFBYSxFQUFFLE1BQU0sRUFBRSxhQUFhLElBQUksdUJBQXVCO1NBQ2hFLENBQUM7UUFDRixJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsVUFBVTtRQUNkLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzVCLENBQUM7UUFDRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxnQ0FBZ0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLDRCQUE0QixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDOUgsQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQVksQ0FBQyxHQUFXO1FBQ3RCLG9CQUFvQjtR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
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RADIUS module for DcRouter
|
|
3
|
-
*
|
|
4
|
-
* Provides:
|
|
5
|
-
* - MAC Authentication Bypass (MAB) for network device authentication
|
|
6
|
-
* - VLAN assignment based on MAC addresses
|
|
7
|
-
* - OUI (vendor prefix) pattern matching for device categorization
|
|
8
|
-
* - RADIUS accounting for session tracking and billing
|
|
9
|
-
* - Integration with StorageManager for persistence
|
|
10
|
-
*/
|
|
11
|
-
export * from './classes.radius.server.js';
|
|
12
|
-
export * from './classes.vlan.manager.js';
|
|
13
|
-
export * from './classes.accounting.manager.js';
|
package/dist_ts/radius/index.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RADIUS module for DcRouter
|
|
3
|
-
*
|
|
4
|
-
* Provides:
|
|
5
|
-
* - MAC Authentication Bypass (MAB) for network device authentication
|
|
6
|
-
* - VLAN assignment based on MAC addresses
|
|
7
|
-
* - OUI (vendor prefix) pattern matching for device categorization
|
|
8
|
-
* - RADIUS accounting for session tracking and billing
|
|
9
|
-
* - Integration with StorageManager for persistence
|
|
10
|
-
*/
|
|
11
|
-
export * from './classes.radius.server.js';
|
|
12
|
-
export * from './classes.vlan.manager.js';
|
|
13
|
-
export * from './classes.accounting.manager.js';
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9yYWRpdXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBRUgsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsaUNBQWlDLENBQUMifQ==
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import type { StorageManager } from '../storage/classes.storagemanager.js';
|
|
2
|
-
import type { IRemoteIngress, IDcRouterRouteConfig } from '../../dist_ts_interfaces/data/remoteingress.js';
|
|
3
|
-
/**
|
|
4
|
-
* Manages CRUD for remote ingress edge registrations.
|
|
5
|
-
* Persists edge configs via StorageManager and provides
|
|
6
|
-
* the allowed edges list for the Rust hub.
|
|
7
|
-
*/
|
|
8
|
-
export declare class RemoteIngressManager {
|
|
9
|
-
private storageManager;
|
|
10
|
-
private edges;
|
|
11
|
-
private routes;
|
|
12
|
-
constructor(storageManager: StorageManager);
|
|
13
|
-
/**
|
|
14
|
-
* Load all edge registrations from storage into memory.
|
|
15
|
-
*/
|
|
16
|
-
initialize(): Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* Store the current route configs for port derivation.
|
|
19
|
-
*/
|
|
20
|
-
setRoutes(routes: IDcRouterRouteConfig[]): void;
|
|
21
|
-
/**
|
|
22
|
-
* Derive listen ports for an edge from routes tagged with remoteIngress.enabled.
|
|
23
|
-
* When a route specifies edgeFilter, only edges whose id or tags match get that route's ports.
|
|
24
|
-
* When edgeFilter is absent, the route applies to all edges.
|
|
25
|
-
*/
|
|
26
|
-
derivePortsForEdge(edgeId: string, edgeTags?: string[]): number[];
|
|
27
|
-
/**
|
|
28
|
-
* Get the effective listen ports for an edge.
|
|
29
|
-
* Manual ports are always included. Auto-derived ports are added (union) when autoDerivePorts is true.
|
|
30
|
-
*/
|
|
31
|
-
getEffectiveListenPorts(edge: IRemoteIngress): number[];
|
|
32
|
-
/**
|
|
33
|
-
* Get manual and derived port breakdown for an edge (used in API responses).
|
|
34
|
-
* Derived ports exclude any ports already present in the manual list.
|
|
35
|
-
*/
|
|
36
|
-
getPortBreakdown(edge: IRemoteIngress): {
|
|
37
|
-
manual: number[];
|
|
38
|
-
derived: number[];
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Create a new edge registration.
|
|
42
|
-
*/
|
|
43
|
-
createEdge(name: string, listenPorts?: number[], tags?: string[], autoDerivePorts?: boolean): Promise<IRemoteIngress>;
|
|
44
|
-
/**
|
|
45
|
-
* Get an edge by ID.
|
|
46
|
-
*/
|
|
47
|
-
getEdge(id: string): IRemoteIngress | undefined;
|
|
48
|
-
/**
|
|
49
|
-
* Get all edge registrations.
|
|
50
|
-
*/
|
|
51
|
-
getAllEdges(): IRemoteIngress[];
|
|
52
|
-
/**
|
|
53
|
-
* Update an edge registration.
|
|
54
|
-
*/
|
|
55
|
-
updateEdge(id: string, updates: {
|
|
56
|
-
name?: string;
|
|
57
|
-
listenPorts?: number[];
|
|
58
|
-
autoDerivePorts?: boolean;
|
|
59
|
-
enabled?: boolean;
|
|
60
|
-
tags?: string[];
|
|
61
|
-
}): Promise<IRemoteIngress | null>;
|
|
62
|
-
/**
|
|
63
|
-
* Delete an edge registration.
|
|
64
|
-
*/
|
|
65
|
-
deleteEdge(id: string): Promise<boolean>;
|
|
66
|
-
/**
|
|
67
|
-
* Regenerate the secret for an edge.
|
|
68
|
-
*/
|
|
69
|
-
regenerateSecret(id: string): Promise<string | null>;
|
|
70
|
-
/**
|
|
71
|
-
* Verify an edge's secret using constant-time comparison.
|
|
72
|
-
*/
|
|
73
|
-
verifySecret(id: string, secret: string): boolean;
|
|
74
|
-
/**
|
|
75
|
-
* Get the list of allowed edges (enabled only) for the Rust hub.
|
|
76
|
-
*/
|
|
77
|
-
getAllowedEdges(): Array<{
|
|
78
|
-
id: string;
|
|
79
|
-
secret: string;
|
|
80
|
-
listenPorts: number[];
|
|
81
|
-
}>;
|
|
82
|
-
}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
|
-
const STORAGE_PREFIX = '/remote-ingress/';
|
|
3
|
-
/**
|
|
4
|
-
* Flatten a port range (number | number[] | Array<{from, to}>) to a sorted unique number array.
|
|
5
|
-
*/
|
|
6
|
-
function extractPorts(portRange) {
|
|
7
|
-
const ports = new Set();
|
|
8
|
-
if (typeof portRange === 'number') {
|
|
9
|
-
ports.add(portRange);
|
|
10
|
-
}
|
|
11
|
-
else if (Array.isArray(portRange)) {
|
|
12
|
-
for (const entry of portRange) {
|
|
13
|
-
if (typeof entry === 'number') {
|
|
14
|
-
ports.add(entry);
|
|
15
|
-
}
|
|
16
|
-
else if (typeof entry === 'object' && 'from' in entry && 'to' in entry) {
|
|
17
|
-
for (let p = entry.from; p <= entry.to; p++) {
|
|
18
|
-
ports.add(p);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return [...ports].sort((a, b) => a - b);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Manages CRUD for remote ingress edge registrations.
|
|
27
|
-
* Persists edge configs via StorageManager and provides
|
|
28
|
-
* the allowed edges list for the Rust hub.
|
|
29
|
-
*/
|
|
30
|
-
export class RemoteIngressManager {
|
|
31
|
-
storageManager;
|
|
32
|
-
edges = new Map();
|
|
33
|
-
routes = [];
|
|
34
|
-
constructor(storageManager) {
|
|
35
|
-
this.storageManager = storageManager;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Load all edge registrations from storage into memory.
|
|
39
|
-
*/
|
|
40
|
-
async initialize() {
|
|
41
|
-
const keys = await this.storageManager.list(STORAGE_PREFIX);
|
|
42
|
-
for (const key of keys) {
|
|
43
|
-
const edge = await this.storageManager.getJSON(key);
|
|
44
|
-
if (edge) {
|
|
45
|
-
// Migration: old edges without autoDerivePorts default to true
|
|
46
|
-
if (edge.autoDerivePorts === undefined) {
|
|
47
|
-
edge.autoDerivePorts = true;
|
|
48
|
-
await this.storageManager.setJSON(key, edge);
|
|
49
|
-
}
|
|
50
|
-
this.edges.set(edge.id, edge);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Store the current route configs for port derivation.
|
|
56
|
-
*/
|
|
57
|
-
setRoutes(routes) {
|
|
58
|
-
this.routes = routes;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Derive listen ports for an edge from routes tagged with remoteIngress.enabled.
|
|
62
|
-
* When a route specifies edgeFilter, only edges whose id or tags match get that route's ports.
|
|
63
|
-
* When edgeFilter is absent, the route applies to all edges.
|
|
64
|
-
*/
|
|
65
|
-
derivePortsForEdge(edgeId, edgeTags) {
|
|
66
|
-
const ports = new Set();
|
|
67
|
-
for (const route of this.routes) {
|
|
68
|
-
if (!route.remoteIngress?.enabled)
|
|
69
|
-
continue;
|
|
70
|
-
// Apply edge filter if present
|
|
71
|
-
const filter = route.remoteIngress.edgeFilter;
|
|
72
|
-
if (filter && filter.length > 0) {
|
|
73
|
-
const idMatch = filter.includes(edgeId);
|
|
74
|
-
const tagMatch = edgeTags?.some((tag) => filter.includes(tag)) ?? false;
|
|
75
|
-
if (!idMatch && !tagMatch)
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
// Extract ports from the route match
|
|
79
|
-
if (route.match?.ports) {
|
|
80
|
-
for (const p of extractPorts(route.match.ports)) {
|
|
81
|
-
ports.add(p);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return [...ports].sort((a, b) => a - b);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Get the effective listen ports for an edge.
|
|
89
|
-
* Manual ports are always included. Auto-derived ports are added (union) when autoDerivePorts is true.
|
|
90
|
-
*/
|
|
91
|
-
getEffectiveListenPorts(edge) {
|
|
92
|
-
const manualPorts = edge.listenPorts || [];
|
|
93
|
-
const shouldDerive = edge.autoDerivePorts !== false;
|
|
94
|
-
if (!shouldDerive)
|
|
95
|
-
return [...manualPorts].sort((a, b) => a - b);
|
|
96
|
-
const derivedPorts = this.derivePortsForEdge(edge.id, edge.tags);
|
|
97
|
-
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Get manual and derived port breakdown for an edge (used in API responses).
|
|
101
|
-
* Derived ports exclude any ports already present in the manual list.
|
|
102
|
-
*/
|
|
103
|
-
getPortBreakdown(edge) {
|
|
104
|
-
const manual = edge.listenPorts || [];
|
|
105
|
-
const shouldDerive = edge.autoDerivePorts !== false;
|
|
106
|
-
if (!shouldDerive)
|
|
107
|
-
return { manual, derived: [] };
|
|
108
|
-
const manualSet = new Set(manual);
|
|
109
|
-
const allDerived = this.derivePortsForEdge(edge.id, edge.tags);
|
|
110
|
-
const derived = allDerived.filter((p) => !manualSet.has(p));
|
|
111
|
-
return { manual, derived };
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Create a new edge registration.
|
|
115
|
-
*/
|
|
116
|
-
async createEdge(name, listenPorts = [], tags, autoDerivePorts = true) {
|
|
117
|
-
const id = plugins.uuid.v4();
|
|
118
|
-
const secret = plugins.crypto.randomBytes(32).toString('hex');
|
|
119
|
-
const now = Date.now();
|
|
120
|
-
const edge = {
|
|
121
|
-
id,
|
|
122
|
-
name,
|
|
123
|
-
secret,
|
|
124
|
-
listenPorts,
|
|
125
|
-
enabled: true,
|
|
126
|
-
autoDerivePorts,
|
|
127
|
-
tags: tags || [],
|
|
128
|
-
createdAt: now,
|
|
129
|
-
updatedAt: now,
|
|
130
|
-
};
|
|
131
|
-
await this.storageManager.setJSON(`${STORAGE_PREFIX}${id}`, edge);
|
|
132
|
-
this.edges.set(id, edge);
|
|
133
|
-
return edge;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Get an edge by ID.
|
|
137
|
-
*/
|
|
138
|
-
getEdge(id) {
|
|
139
|
-
return this.edges.get(id);
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Get all edge registrations.
|
|
143
|
-
*/
|
|
144
|
-
getAllEdges() {
|
|
145
|
-
return Array.from(this.edges.values());
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Update an edge registration.
|
|
149
|
-
*/
|
|
150
|
-
async updateEdge(id, updates) {
|
|
151
|
-
const edge = this.edges.get(id);
|
|
152
|
-
if (!edge) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
if (updates.name !== undefined)
|
|
156
|
-
edge.name = updates.name;
|
|
157
|
-
if (updates.listenPorts !== undefined)
|
|
158
|
-
edge.listenPorts = updates.listenPorts;
|
|
159
|
-
if (updates.autoDerivePorts !== undefined)
|
|
160
|
-
edge.autoDerivePorts = updates.autoDerivePorts;
|
|
161
|
-
if (updates.enabled !== undefined)
|
|
162
|
-
edge.enabled = updates.enabled;
|
|
163
|
-
if (updates.tags !== undefined)
|
|
164
|
-
edge.tags = updates.tags;
|
|
165
|
-
edge.updatedAt = Date.now();
|
|
166
|
-
await this.storageManager.setJSON(`${STORAGE_PREFIX}${id}`, edge);
|
|
167
|
-
this.edges.set(id, edge);
|
|
168
|
-
return edge;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Delete an edge registration.
|
|
172
|
-
*/
|
|
173
|
-
async deleteEdge(id) {
|
|
174
|
-
if (!this.edges.has(id)) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
await this.storageManager.delete(`${STORAGE_PREFIX}${id}`);
|
|
178
|
-
this.edges.delete(id);
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Regenerate the secret for an edge.
|
|
183
|
-
*/
|
|
184
|
-
async regenerateSecret(id) {
|
|
185
|
-
const edge = this.edges.get(id);
|
|
186
|
-
if (!edge) {
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
edge.secret = plugins.crypto.randomBytes(32).toString('hex');
|
|
190
|
-
edge.updatedAt = Date.now();
|
|
191
|
-
await this.storageManager.setJSON(`${STORAGE_PREFIX}${id}`, edge);
|
|
192
|
-
this.edges.set(id, edge);
|
|
193
|
-
return edge.secret;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Verify an edge's secret using constant-time comparison.
|
|
197
|
-
*/
|
|
198
|
-
verifySecret(id, secret) {
|
|
199
|
-
const edge = this.edges.get(id);
|
|
200
|
-
if (!edge) {
|
|
201
|
-
return false;
|
|
202
|
-
}
|
|
203
|
-
const expected = Buffer.from(edge.secret);
|
|
204
|
-
const provided = Buffer.from(secret);
|
|
205
|
-
if (expected.length !== provided.length) {
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
return plugins.crypto.timingSafeEqual(expected, provided);
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Get the list of allowed edges (enabled only) for the Rust hub.
|
|
212
|
-
*/
|
|
213
|
-
getAllowedEdges() {
|
|
214
|
-
const result = [];
|
|
215
|
-
for (const edge of this.edges.values()) {
|
|
216
|
-
if (edge.enabled) {
|
|
217
|
-
result.push({
|
|
218
|
-
id: edge.id,
|
|
219
|
-
secret: edge.secret,
|
|
220
|
-
listenPorts: this.getEffectiveListenPorts(edge),
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return result;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yZW1vdGVpbmdyZXNzLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9yZW1vdGVpbmdyZXNzL2NsYXNzZXMucmVtb3RlaW5ncmVzcy1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBSXpDLE1BQU0sY0FBYyxHQUFHLGtCQUFrQixDQUFDO0FBRTFDOztHQUVHO0FBQ0gsU0FBUyxZQUFZLENBQUMsU0FBa0U7SUFDdEYsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNoQyxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ2xDLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkIsQ0FBQztTQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3BDLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDOUIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuQixDQUFDO2lCQUFNLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLE1BQU0sSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN6RSxLQUFLLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQkFDNUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENB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
|