@serve.zone/dcrouter 11.13.0 → 11.14.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.
Files changed (201) hide show
  1. package/dist_serve/bundle.js +2 -2
  2. package/package.json +1 -1
  3. package/readme.md +107 -3
  4. package/ts/00_commitinfo_data.ts +1 -1
  5. package/ts_web/00_commitinfo_data.ts +1 -1
  6. package/ts_web/readme.md +17 -0
  7. package/ts_web/router.ts +1 -1
  8. package/dist_ts/00_commitinfo_data.d.ts +0 -8
  9. package/dist_ts/00_commitinfo_data.js +0 -9
  10. package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
  11. package/dist_ts/cache/classes.cache.cleaner.js +0 -130
  12. package/dist_ts/cache/classes.cached.document.d.ts +0 -76
  13. package/dist_ts/cache/classes.cached.document.js +0 -100
  14. package/dist_ts/cache/classes.cachedb.d.ts +0 -60
  15. package/dist_ts/cache/classes.cachedb.js +0 -126
  16. package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
  17. package/dist_ts/cache/documents/classes.cached.email.js +0 -337
  18. package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
  19. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
  20. package/dist_ts/cache/documents/index.d.ts +0 -2
  21. package/dist_ts/cache/documents/index.js +0 -3
  22. package/dist_ts/cache/index.d.ts +0 -4
  23. package/dist_ts/cache/index.js +0 -7
  24. package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -54
  25. package/dist_ts/classes.cert-provision-scheduler.js +0 -118
  26. package/dist_ts/classes.dcrouter.d.ts +0 -386
  27. package/dist_ts/classes.dcrouter.js +0 -1682
  28. package/dist_ts/classes.storage-cert-manager.d.ts +0 -18
  29. package/dist_ts/classes.storage-cert-manager.js +0 -43
  30. package/dist_ts/config/classes.api-token-manager.d.ts +0 -46
  31. package/dist_ts/config/classes.api-token-manager.js +0 -150
  32. package/dist_ts/config/classes.route-config-manager.d.ts +0 -38
  33. package/dist_ts/config/classes.route-config-manager.js +0 -256
  34. package/dist_ts/config/index.d.ts +0 -3
  35. package/dist_ts/config/index.js +0 -5
  36. package/dist_ts/config/validator.d.ts +0 -104
  37. package/dist_ts/config/validator.js +0 -152
  38. package/dist_ts/errors/base.errors.d.ts +0 -224
  39. package/dist_ts/errors/base.errors.js +0 -320
  40. package/dist_ts/errors/error-handler.d.ts +0 -98
  41. package/dist_ts/errors/error-handler.js +0 -282
  42. package/dist_ts/errors/error.codes.d.ts +0 -115
  43. package/dist_ts/errors/error.codes.js +0 -136
  44. package/dist_ts/errors/index.d.ts +0 -54
  45. package/dist_ts/errors/index.js +0 -136
  46. package/dist_ts/errors/reputation.errors.d.ts +0 -183
  47. package/dist_ts/errors/reputation.errors.js +0 -292
  48. package/dist_ts/http3/http3-route-augmentation.d.ts +0 -50
  49. package/dist_ts/http3/http3-route-augmentation.js +0 -98
  50. package/dist_ts/http3/index.d.ts +0 -1
  51. package/dist_ts/http3/index.js +0 -2
  52. package/dist_ts/index.d.ts +0 -8
  53. package/dist_ts/index.js +0 -29
  54. package/dist_ts/logger.d.ts +0 -21
  55. package/dist_ts/logger.js +0 -81
  56. package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
  57. package/dist_ts/monitoring/classes.metricscache.js +0 -63
  58. package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -184
  59. package/dist_ts/monitoring/classes.metricsmanager.js +0 -744
  60. package/dist_ts/monitoring/index.d.ts +0 -1
  61. package/dist_ts/monitoring/index.js +0 -2
  62. package/dist_ts/opsserver/classes.opsserver.d.ts +0 -38
  63. package/dist_ts/opsserver/classes.opsserver.js +0 -87
  64. package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
  65. package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
  66. package/dist_ts/opsserver/handlers/api-token.handler.d.ts +0 -6
  67. package/dist_ts/opsserver/handlers/api-token.handler.js +0 -62
  68. package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -32
  69. package/dist_ts/opsserver/handlers/certificate.handler.js +0 -421
  70. package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
  71. package/dist_ts/opsserver/handlers/config.handler.js +0 -192
  72. package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +0 -30
  73. package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -227
  74. package/dist_ts/opsserver/handlers/index.d.ts +0 -12
  75. package/dist_ts/opsserver/handlers/index.js +0 -13
  76. package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
  77. package/dist_ts/opsserver/handlers/logs.handler.js +0 -256
  78. package/dist_ts/opsserver/handlers/radius.handler.d.ts +0 -6
  79. package/dist_ts/opsserver/handlers/radius.handler.js +0 -295
  80. package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -6
  81. package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -156
  82. package/dist_ts/opsserver/handlers/route-management.handler.d.ts +0 -14
  83. package/dist_ts/opsserver/handlers/route-management.handler.js +0 -117
  84. package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -9
  85. package/dist_ts/opsserver/handlers/security.handler.js +0 -233
  86. package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -11
  87. package/dist_ts/opsserver/handlers/stats.handler.js +0 -403
  88. package/dist_ts/opsserver/handlers/vpn.handler.d.ts +0 -6
  89. package/dist_ts/opsserver/handlers/vpn.handler.js +0 -199
  90. package/dist_ts/opsserver/helpers/guards.d.ts +0 -27
  91. package/dist_ts/opsserver/helpers/guards.js +0 -43
  92. package/dist_ts/opsserver/index.d.ts +0 -1
  93. package/dist_ts/opsserver/index.js +0 -2
  94. package/dist_ts/paths.d.ts +0 -26
  95. package/dist_ts/paths.js +0 -45
  96. package/dist_ts/plugins.d.ts +0 -81
  97. package/dist_ts/plugins.js +0 -115
  98. package/dist_ts/radius/classes.accounting.manager.d.ts +0 -231
  99. package/dist_ts/radius/classes.accounting.manager.js +0 -462
  100. package/dist_ts/radius/classes.radius.server.d.ts +0 -171
  101. package/dist_ts/radius/classes.radius.server.js +0 -386
  102. package/dist_ts/radius/classes.vlan.manager.d.ts +0 -128
  103. package/dist_ts/radius/classes.vlan.manager.js +0 -279
  104. package/dist_ts/radius/index.d.ts +0 -13
  105. package/dist_ts/radius/index.js +0 -14
  106. package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +0 -94
  107. package/dist_ts/remoteingress/classes.remoteingress-manager.js +0 -271
  108. package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +0 -59
  109. package/dist_ts/remoteingress/classes.tunnel-manager.js +0 -165
  110. package/dist_ts/remoteingress/index.d.ts +0 -2
  111. package/dist_ts/remoteingress/index.js +0 -3
  112. package/dist_ts/security/classes.contentscanner.d.ts +0 -164
  113. package/dist_ts/security/classes.contentscanner.js +0 -642
  114. package/dist_ts/security/classes.ipreputationchecker.d.ts +0 -160
  115. package/dist_ts/security/classes.ipreputationchecker.js +0 -537
  116. package/dist_ts/security/classes.securitylogger.d.ts +0 -144
  117. package/dist_ts/security/classes.securitylogger.js +0 -235
  118. package/dist_ts/security/index.d.ts +0 -3
  119. package/dist_ts/security/index.js +0 -4
  120. package/dist_ts/sms/classes.smsservice.d.ts +0 -15
  121. package/dist_ts/sms/classes.smsservice.js +0 -72
  122. package/dist_ts/sms/config/sms.config.d.ts +0 -93
  123. package/dist_ts/sms/config/sms.config.js +0 -2
  124. package/dist_ts/sms/config/sms.schema.d.ts +0 -5
  125. package/dist_ts/sms/config/sms.schema.js +0 -121
  126. package/dist_ts/sms/index.d.ts +0 -1
  127. package/dist_ts/sms/index.js +0 -2
  128. package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
  129. package/dist_ts/storage/classes.storagemanager.js +0 -348
  130. package/dist_ts/storage/index.d.ts +0 -1
  131. package/dist_ts/storage/index.js +0 -3
  132. package/dist_ts/vpn/classes.vpn-manager.d.ts +0 -113
  133. package/dist_ts/vpn/classes.vpn-manager.js +0 -297
  134. package/dist_ts/vpn/index.d.ts +0 -1
  135. package/dist_ts/vpn/index.js +0 -2
  136. package/dist_ts_apiclient/classes.apitoken.d.ts +0 -41
  137. package/dist_ts_apiclient/classes.apitoken.js +0 -115
  138. package/dist_ts_apiclient/classes.certificate.d.ts +0 -57
  139. package/dist_ts_apiclient/classes.certificate.js +0 -69
  140. package/dist_ts_apiclient/classes.config.d.ts +0 -7
  141. package/dist_ts_apiclient/classes.config.js +0 -11
  142. package/dist_ts_apiclient/classes.dcrouterapiclient.d.ts +0 -41
  143. package/dist_ts_apiclient/classes.dcrouterapiclient.js +0 -81
  144. package/dist_ts_apiclient/classes.email.d.ts +0 -30
  145. package/dist_ts_apiclient/classes.email.js +0 -52
  146. package/dist_ts_apiclient/classes.logs.d.ts +0 -21
  147. package/dist_ts_apiclient/classes.logs.js +0 -14
  148. package/dist_ts_apiclient/classes.radius.d.ts +0 -59
  149. package/dist_ts_apiclient/classes.radius.js +0 -95
  150. package/dist_ts_apiclient/classes.remoteingress.d.ts +0 -54
  151. package/dist_ts_apiclient/classes.remoteingress.js +0 -136
  152. package/dist_ts_apiclient/classes.route.d.ts +0 -42
  153. package/dist_ts_apiclient/classes.route.js +0 -154
  154. package/dist_ts_apiclient/classes.stats.d.ts +0 -47
  155. package/dist_ts_apiclient/classes.stats.js +0 -38
  156. package/dist_ts_apiclient/index.d.ts +0 -10
  157. package/dist_ts_apiclient/index.js +0 -14
  158. package/dist_ts_apiclient/plugins.d.ts +0 -3
  159. package/dist_ts_apiclient/plugins.js +0 -5
  160. package/dist_ts_web/00_commitinfo_data.d.ts +0 -8
  161. package/dist_ts_web/00_commitinfo_data.js +0 -9
  162. package/dist_ts_web/appstate.d.ts +0 -238
  163. package/dist_ts_web/appstate.js +0 -1174
  164. package/dist_ts_web/elements/index.d.ts +0 -13
  165. package/dist_ts_web/elements/index.js +0 -14
  166. package/dist_ts_web/elements/ops-dashboard.d.ts +0 -23
  167. package/dist_ts_web/elements/ops-dashboard.js +0 -323
  168. package/dist_ts_web/elements/ops-view-apitokens.d.ts +0 -13
  169. package/dist_ts_web/elements/ops-view-apitokens.js +0 -371
  170. package/dist_ts_web/elements/ops-view-certificates.d.ts +0 -22
  171. package/dist_ts_web/elements/ops-view-certificates.js +0 -528
  172. package/dist_ts_web/elements/ops-view-config.d.ts +0 -19
  173. package/dist_ts_web/elements/ops-view-config.js +0 -339
  174. package/dist_ts_web/elements/ops-view-emails.d.ts +0 -21
  175. package/dist_ts_web/elements/ops-view-emails.js +0 -165
  176. package/dist_ts_web/elements/ops-view-logs.d.ts +0 -13
  177. package/dist_ts_web/elements/ops-view-logs.js +0 -159
  178. package/dist_ts_web/elements/ops-view-network.d.ts +0 -71
  179. package/dist_ts_web/elements/ops-view-network.js +0 -764
  180. package/dist_ts_web/elements/ops-view-overview.d.ts +0 -22
  181. package/dist_ts_web/elements/ops-view-overview.js +0 -456
  182. package/dist_ts_web/elements/ops-view-remoteingress.d.ts +0 -20
  183. package/dist_ts_web/elements/ops-view-remoteingress.js +0 -494
  184. package/dist_ts_web/elements/ops-view-routes.d.ts +0 -12
  185. package/dist_ts_web/elements/ops-view-routes.js +0 -404
  186. package/dist_ts_web/elements/ops-view-security.d.ts +0 -21
  187. package/dist_ts_web/elements/ops-view-security.js +0 -574
  188. package/dist_ts_web/elements/ops-view-vpn.d.ts +0 -14
  189. package/dist_ts_web/elements/ops-view-vpn.js +0 -369
  190. package/dist_ts_web/elements/shared/css.d.ts +0 -1
  191. package/dist_ts_web/elements/shared/css.js +0 -10
  192. package/dist_ts_web/elements/shared/index.d.ts +0 -2
  193. package/dist_ts_web/elements/shared/index.js +0 -3
  194. package/dist_ts_web/elements/shared/ops-sectionheading.d.ts +0 -5
  195. package/dist_ts_web/elements/shared/ops-sectionheading.js +0 -82
  196. package/dist_ts_web/index.d.ts +0 -1
  197. package/dist_ts_web/index.js +0 -10
  198. package/dist_ts_web/plugins.d.ts +0 -6
  199. package/dist_ts_web/plugins.js +0 -11
  200. package/dist_ts_web/router.d.ts +0 -19
  201. package/dist_ts_web/router.js +0 -91
@@ -1,386 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- import { logger } from '../logger.js';
3
- import { VlanManager } from './classes.vlan.manager.js';
4
- import { AccountingManager } from './classes.accounting.manager.js';
5
- /**
6
- * RADIUS Server wrapper that provides:
7
- * - MAC Authentication Bypass (MAB) for network devices
8
- * - VLAN assignment based on MAC address
9
- * - Accounting for session tracking and billing
10
- * - Integration with SmartProxy routing
11
- */
12
- export class RadiusServer {
13
- radiusServer;
14
- vlanManager;
15
- accountingManager;
16
- config;
17
- storageManager;
18
- clientSecrets = new Map();
19
- running = false;
20
- // Statistics
21
- stats = {
22
- authRequests: 0,
23
- authAccepts: 0,
24
- authRejects: 0,
25
- accountingRequests: 0,
26
- startTime: 0,
27
- };
28
- constructor(config, storageManager) {
29
- this.config = {
30
- authPort: config.authPort ?? 1812,
31
- acctPort: config.acctPort ?? 1813,
32
- bindAddress: config.bindAddress ?? '0.0.0.0',
33
- ...config,
34
- };
35
- this.storageManager = storageManager;
36
- // Initialize VLAN manager
37
- this.vlanManager = new VlanManager(config.vlanAssignment, storageManager);
38
- // Initialize accounting manager
39
- this.accountingManager = new AccountingManager(config.accounting, storageManager);
40
- }
41
- /**
42
- * Start the RADIUS server
43
- */
44
- async start() {
45
- if (this.running) {
46
- logger.log('warn', 'RADIUS server is already running');
47
- return;
48
- }
49
- logger.log('info', `Starting RADIUS server on ${this.config.bindAddress}:${this.config.authPort} (auth) and ${this.config.acctPort} (acct)`);
50
- // Initialize managers
51
- await this.vlanManager.initialize();
52
- await this.accountingManager.initialize();
53
- // Import static VLAN mappings if provided
54
- if (this.config.vlanAssignment?.mappings) {
55
- await this.vlanManager.importMappings(this.config.vlanAssignment.mappings);
56
- }
57
- // Build client secrets map
58
- this.buildClientSecretsMap();
59
- // Create the RADIUS server
60
- this.radiusServer = new plugins.smartradius.RadiusServer({
61
- authPort: this.config.authPort,
62
- acctPort: this.config.acctPort,
63
- bindAddress: this.config.bindAddress,
64
- defaultSecret: this.getDefaultSecret(),
65
- authenticationHandler: this.handleAuthentication.bind(this),
66
- accountingHandler: this.handleAccounting.bind(this),
67
- });
68
- // Configure per-client secrets
69
- for (const [ip, secret] of this.clientSecrets) {
70
- this.radiusServer.setClientSecret(ip, secret);
71
- }
72
- // Start the server
73
- await this.radiusServer.start();
74
- this.running = true;
75
- this.stats.startTime = Date.now();
76
- logger.log('info', `RADIUS server started with ${this.config.clients.length} configured clients`);
77
- }
78
- /**
79
- * Stop the RADIUS server
80
- */
81
- async stop() {
82
- if (!this.running) {
83
- return;
84
- }
85
- logger.log('info', 'Stopping RADIUS server...');
86
- if (this.radiusServer) {
87
- await this.radiusServer.stop();
88
- this.radiusServer = undefined;
89
- }
90
- this.accountingManager.stop();
91
- this.running = false;
92
- logger.log('info', 'RADIUS server stopped');
93
- }
94
- /**
95
- * Handle authentication request
96
- */
97
- async handleAuthentication(request) {
98
- this.stats.authRequests++;
99
- const authData = {
100
- username: request.attributes?.UserName || '',
101
- password: request.attributes?.UserPassword,
102
- nasIpAddress: request.attributes?.NasIpAddress || request.source?.address || '',
103
- nasPort: request.attributes?.NasPort,
104
- nasPortType: request.attributes?.NasPortType,
105
- nasIdentifier: request.attributes?.NasIdentifier,
106
- calledStationId: request.attributes?.CalledStationId,
107
- callingStationId: request.attributes?.CallingStationId,
108
- serviceType: request.attributes?.ServiceType,
109
- };
110
- logger.log('debug', `RADIUS Auth Request: user=${authData.username}, NAS=${authData.nasIpAddress}`);
111
- // Perform MAC Authentication Bypass (MAB)
112
- // In MAB, the username is typically the MAC address
113
- const result = await this.performMabAuthentication(authData);
114
- if (result.success) {
115
- this.stats.authAccepts++;
116
- logger.log('info', `RADIUS Auth Accept: user=${authData.username}, VLAN=${result.vlanId}`);
117
- // Build response with VLAN attributes
118
- const response = {
119
- code: plugins.smartradius.ERadiusCode.AccessAccept,
120
- replyMessage: result.replyMessage,
121
- };
122
- // Add VLAN attributes if assigned
123
- if (result.vlanId !== undefined) {
124
- response.tunnelType = 13; // VLAN
125
- response.tunnelMediumType = 6; // IEEE 802
126
- response.tunnelPrivateGroupId = String(result.vlanId);
127
- }
128
- // Add session timeout if specified
129
- if (result.sessionTimeout) {
130
- response.sessionTimeout = result.sessionTimeout;
131
- }
132
- // Add idle timeout if specified
133
- if (result.idleTimeout) {
134
- response.idleTimeout = result.idleTimeout;
135
- }
136
- // Add framed IP if specified
137
- if (result.framedIpAddress) {
138
- response.framedIpAddress = result.framedIpAddress;
139
- }
140
- return response;
141
- }
142
- else {
143
- this.stats.authRejects++;
144
- logger.log('warn', `RADIUS Auth Reject: user=${authData.username}, reason=${result.rejectReason}`);
145
- return {
146
- code: plugins.smartradius.ERadiusCode.AccessReject,
147
- replyMessage: result.rejectReason || 'Access Denied',
148
- };
149
- }
150
- }
151
- /**
152
- * Handle accounting request
153
- */
154
- async handleAccounting(request) {
155
- this.stats.accountingRequests++;
156
- if (!this.config.accounting?.enabled) {
157
- // Still respond even if not tracking
158
- return { code: plugins.smartradius.ERadiusCode.AccountingResponse };
159
- }
160
- const statusType = request.attributes?.AcctStatusType;
161
- const sessionId = request.attributes?.AcctSessionId || '';
162
- const accountingData = {
163
- sessionId,
164
- username: request.attributes?.UserName || '',
165
- macAddress: request.attributes?.CallingStationId,
166
- nasIpAddress: request.attributes?.NasIpAddress || request.source?.address || '',
167
- nasPort: request.attributes?.NasPort,
168
- nasPortType: request.attributes?.NasPortType,
169
- nasIdentifier: request.attributes?.NasIdentifier,
170
- calledStationId: request.attributes?.CalledStationId,
171
- callingStationId: request.attributes?.CallingStationId,
172
- inputOctets: request.attributes?.AcctInputOctets,
173
- outputOctets: request.attributes?.AcctOutputOctets,
174
- inputPackets: request.attributes?.AcctInputPackets,
175
- outputPackets: request.attributes?.AcctOutputPackets,
176
- sessionTime: request.attributes?.AcctSessionTime,
177
- terminateCause: request.attributes?.AcctTerminateCause,
178
- serviceType: request.attributes?.ServiceType,
179
- };
180
- try {
181
- switch (statusType) {
182
- case plugins.smartradius.EAcctStatusType.Start:
183
- logger.log('debug', `RADIUS Acct Start: session=${sessionId}, user=${accountingData.username}`);
184
- await this.accountingManager.handleAccountingStart(accountingData);
185
- break;
186
- case plugins.smartradius.EAcctStatusType.Stop:
187
- logger.log('debug', `RADIUS Acct Stop: session=${sessionId}`);
188
- await this.accountingManager.handleAccountingStop(accountingData);
189
- break;
190
- case plugins.smartradius.EAcctStatusType.InterimUpdate:
191
- logger.log('debug', `RADIUS Acct Interim: session=${sessionId}`);
192
- await this.accountingManager.handleAccountingUpdate(accountingData);
193
- break;
194
- default:
195
- logger.log('debug', `RADIUS Acct Unknown status type: ${statusType}`);
196
- }
197
- }
198
- catch (error) {
199
- logger.log('error', `RADIUS accounting error: ${error.message}`);
200
- }
201
- return { code: plugins.smartradius.ERadiusCode.AccountingResponse };
202
- }
203
- /**
204
- * Perform MAC Authentication Bypass
205
- */
206
- async performMabAuthentication(data) {
207
- // Extract MAC address from username or CallingStationId
208
- const macAddress = this.extractMacAddress(data);
209
- if (!macAddress) {
210
- return {
211
- success: false,
212
- rejectReason: 'No MAC address found',
213
- };
214
- }
215
- // Look up VLAN assignment
216
- const vlanResult = this.vlanManager.assignVlan(macAddress);
217
- if (!vlanResult.assigned) {
218
- return {
219
- success: false,
220
- rejectReason: 'Unknown MAC address',
221
- };
222
- }
223
- // Build successful result
224
- const result = {
225
- success: true,
226
- vlanId: vlanResult.vlan,
227
- replyMessage: vlanResult.isDefault
228
- ? `Assigned to default VLAN ${vlanResult.vlan}`
229
- : `Assigned to VLAN ${vlanResult.vlan}`,
230
- };
231
- // Apply any additional settings from the matched rule
232
- if (vlanResult.matchedRule) {
233
- // Future: Add session timeout, idle timeout, etc. from rule
234
- }
235
- return result;
236
- }
237
- /**
238
- * Extract MAC address from authentication data
239
- */
240
- extractMacAddress(data) {
241
- // Try CallingStationId first (most common for MAB)
242
- if (data.callingStationId) {
243
- return this.normalizeMac(data.callingStationId);
244
- }
245
- // Try username (often MAC address in MAB)
246
- if (data.username && this.looksLikeMac(data.username)) {
247
- return this.normalizeMac(data.username);
248
- }
249
- return null;
250
- }
251
- /**
252
- * Check if a string looks like a MAC address
253
- */
254
- looksLikeMac(value) {
255
- // Remove common separators and check length
256
- const cleaned = value.replace(/[-:. ]/g, '');
257
- return /^[0-9a-fA-F]{12}$/.test(cleaned);
258
- }
259
- /**
260
- * Normalize MAC address format
261
- */
262
- normalizeMac(mac) {
263
- return this.vlanManager.normalizeMac(mac);
264
- }
265
- /**
266
- * Build client secrets map from configuration
267
- */
268
- buildClientSecretsMap() {
269
- this.clientSecrets.clear();
270
- for (const client of this.config.clients) {
271
- if (!client.enabled) {
272
- continue;
273
- }
274
- // Handle CIDR ranges
275
- if (client.ipRange.includes('/')) {
276
- // For CIDR ranges, we'll use the network address as key
277
- // In practice, smartradius may handle this differently
278
- const [network] = client.ipRange.split('/');
279
- this.clientSecrets.set(network, client.secret);
280
- }
281
- else {
282
- this.clientSecrets.set(client.ipRange, client.secret);
283
- }
284
- }
285
- }
286
- /**
287
- * Get default secret for unknown clients
288
- */
289
- getDefaultSecret() {
290
- // Use first enabled client's secret as default, or a random one
291
- for (const client of this.config.clients) {
292
- if (client.enabled) {
293
- return client.secret;
294
- }
295
- }
296
- return plugins.crypto.randomBytes(16).toString('hex');
297
- }
298
- /**
299
- * Add a RADIUS client
300
- */
301
- async addClient(client) {
302
- // Check if client already exists
303
- const existingIndex = this.config.clients.findIndex(c => c.name === client.name);
304
- if (existingIndex >= 0) {
305
- this.config.clients[existingIndex] = client;
306
- }
307
- else {
308
- this.config.clients.push(client);
309
- }
310
- // Update client secrets if running
311
- if (this.running && this.radiusServer && client.enabled) {
312
- if (client.ipRange.includes('/')) {
313
- const [network] = client.ipRange.split('/');
314
- this.radiusServer.setClientSecret(network, client.secret);
315
- this.clientSecrets.set(network, client.secret);
316
- }
317
- else {
318
- this.radiusServer.setClientSecret(client.ipRange, client.secret);
319
- this.clientSecrets.set(client.ipRange, client.secret);
320
- }
321
- }
322
- logger.log('info', `RADIUS client ${client.enabled ? 'added' : 'disabled'}: ${client.name} (${client.ipRange})`);
323
- }
324
- /**
325
- * Remove a RADIUS client
326
- */
327
- removeClient(name) {
328
- const index = this.config.clients.findIndex(c => c.name === name);
329
- if (index >= 0) {
330
- const client = this.config.clients[index];
331
- this.config.clients.splice(index, 1);
332
- // Remove from secrets map
333
- if (client.ipRange.includes('/')) {
334
- const [network] = client.ipRange.split('/');
335
- this.clientSecrets.delete(network);
336
- }
337
- else {
338
- this.clientSecrets.delete(client.ipRange);
339
- }
340
- logger.log('info', `RADIUS client removed: ${name}`);
341
- return true;
342
- }
343
- return false;
344
- }
345
- /**
346
- * Get configured clients
347
- */
348
- getClients() {
349
- return [...this.config.clients];
350
- }
351
- /**
352
- * Get VLAN manager for direct access to VLAN operations
353
- */
354
- getVlanManager() {
355
- return this.vlanManager;
356
- }
357
- /**
358
- * Get accounting manager for direct access to accounting operations
359
- */
360
- getAccountingManager() {
361
- return this.accountingManager;
362
- }
363
- /**
364
- * Get server statistics
365
- */
366
- getStats() {
367
- return {
368
- running: this.running,
369
- uptime: this.running ? Date.now() - this.stats.startTime : 0,
370
- authRequests: this.stats.authRequests,
371
- authAccepts: this.stats.authAccepts,
372
- authRejects: this.stats.authRejects,
373
- accountingRequests: this.stats.accountingRequests,
374
- activeSessions: this.accountingManager.getStats().activeSessions,
375
- vlanMappings: this.vlanManager.getStats().totalMappings,
376
- clients: this.config.clients.filter(c => c.enabled).length,
377
- };
378
- }
379
- /**
380
- * Check if server is running
381
- */
382
- isRunning() {
383
- return this.running;
384
- }
385
- }
386
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yYWRpdXMuc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcmFkaXVzL2NsYXNzZXMucmFkaXVzLnNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxXQUFXLEVBQWlELE1BQU0sMkJBQTJCLENBQUM7QUFDdkcsT0FBTyxFQUFFLGlCQUFpQixFQUEwRCxNQUFNLGlDQUFpQyxDQUFDO0FBOEU1SDs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUNmLFlBQVksQ0FBb0M7SUFDaEQsV0FBVyxDQUFjO0lBQ3pCLGlCQUFpQixDQUFvQjtJQUNyQyxNQUFNLENBQXNCO0lBQzVCLGNBQWMsQ0FBa0I7SUFDaEMsYUFBYSxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQy9DLE9BQU8sR0FBWSxLQUFLLENBQUM7SUFFakMsYUFBYTtJQUNMLEtBQUssR0FBRztRQUNkLFlBQVksRUFBRSxDQUFDO1FBQ2YsV0FBVyxFQUFFLENBQUM7UUFDZCxXQUFXLEVBQUUsQ0FBQztRQUNkLGtCQUFrQixFQUFFLENBQUM7UUFDckIsU0FBUyxFQUFFLENBQUM7S0FDYixDQUFDO0lBRUYsWUFBWSxNQUEyQixFQUFFLGNBQStCO1FBQ3RFLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJO1lBQ2pDLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxJQUFJLElBQUk7WUFDakMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLElBQUksU0FBUztZQUM1QyxHQUFHLE1BQU07U0FDVixDQUFDO1FBQ0YsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFFckMsMEJBQTBCO1FBQzFCLElBQUksQ0FBQyxX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
@@ -1,128 +0,0 @@
1
- import type { StorageManager } from '../storage/index.js';
2
- /**
3
- * MAC address to VLAN mapping
4
- */
5
- export interface IMacVlanMapping {
6
- /** MAC address (full) or OUI pattern (e.g., "00:11:22" for vendor prefix) */
7
- mac: string;
8
- /** VLAN ID to assign */
9
- vlan: number;
10
- /** Optional description */
11
- description?: string;
12
- /** Whether this mapping is enabled */
13
- enabled: boolean;
14
- /** Creation timestamp */
15
- createdAt: number;
16
- /** Last update timestamp */
17
- updatedAt: number;
18
- }
19
- /**
20
- * VLAN assignment result
21
- */
22
- export interface IVlanAssignmentResult {
23
- /** Whether a VLAN was successfully assigned */
24
- assigned: boolean;
25
- /** The assigned VLAN ID (or default if not matched) */
26
- vlan: number;
27
- /** The matching rule (if any) */
28
- matchedRule?: IMacVlanMapping;
29
- /** Whether default VLAN was used */
30
- isDefault: boolean;
31
- }
32
- /**
33
- * VlanManager configuration
34
- */
35
- export interface IVlanManagerConfig {
36
- /** Default VLAN for unknown MACs */
37
- defaultVlan?: number;
38
- /** Whether to allow unknown MACs (assign default VLAN) or reject */
39
- allowUnknownMacs?: boolean;
40
- /** Storage key prefix for persistence */
41
- storagePrefix?: string;
42
- }
43
- /**
44
- * Manages MAC address to VLAN mappings with support for:
45
- * - Exact MAC address matching
46
- * - OUI (vendor prefix) pattern matching
47
- * - Wildcard patterns
48
- * - Default VLAN for unknown devices
49
- */
50
- export declare class VlanManager {
51
- private mappings;
52
- private config;
53
- private storageManager?;
54
- private normalizedMacCache;
55
- constructor(config?: IVlanManagerConfig, storageManager?: StorageManager);
56
- /**
57
- * Initialize the VLAN manager and load persisted mappings
58
- */
59
- initialize(): Promise<void>;
60
- /**
61
- * Normalize a MAC address to lowercase with colons
62
- * Accepts formats: 00:11:22:33:44:55, 00-11-22-33-44-55, 001122334455
63
- */
64
- normalizeMac(mac: string): string;
65
- /**
66
- * Check if a MAC address matches a pattern
67
- * Supports:
68
- * - Exact match: "00:11:22:33:44:55"
69
- * - OUI match: "00:11:22" (matches any device with this vendor prefix)
70
- * - Wildcard: "*" (matches all)
71
- */
72
- macMatchesPattern(mac: string, pattern: string): boolean;
73
- /**
74
- * Add or update a MAC to VLAN mapping
75
- */
76
- addMapping(mapping: Omit<IMacVlanMapping, 'createdAt' | 'updatedAt'>): Promise<IMacVlanMapping>;
77
- /**
78
- * Remove a MAC to VLAN mapping
79
- */
80
- removeMapping(mac: string): Promise<boolean>;
81
- /**
82
- * Get a specific mapping by MAC
83
- */
84
- getMapping(mac: string): IMacVlanMapping | undefined;
85
- /**
86
- * Get all mappings
87
- */
88
- getAllMappings(): IMacVlanMapping[];
89
- /**
90
- * Determine VLAN assignment for a MAC address
91
- * Returns the most specific matching rule (exact > OUI > wildcard > default)
92
- */
93
- assignVlan(mac: string): IVlanAssignmentResult;
94
- /**
95
- * Bulk import mappings
96
- */
97
- importMappings(mappings: Array<Omit<IMacVlanMapping, 'createdAt' | 'updatedAt'>>): Promise<number>;
98
- /**
99
- * Export all mappings
100
- */
101
- exportMappings(): IMacVlanMapping[];
102
- /**
103
- * Update configuration
104
- */
105
- updateConfig(config: Partial<IVlanManagerConfig>): void;
106
- /**
107
- * Get current configuration
108
- */
109
- getConfig(): Required<IVlanManagerConfig>;
110
- /**
111
- * Get statistics
112
- */
113
- getStats(): {
114
- totalMappings: number;
115
- enabledMappings: number;
116
- exactMatches: number;
117
- ouiPatterns: number;
118
- wildcardPatterns: number;
119
- };
120
- /**
121
- * Load mappings from storage
122
- */
123
- private loadMappings;
124
- /**
125
- * Save mappings to storage
126
- */
127
- private saveMappings;
128
- }