@serve.zone/dcrouter 11.12.4 → 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 (214) hide show
  1. package/dist_serve/bundle.js +705 -548
  2. package/dist_ts_interfaces/data/index.d.ts +1 -0
  3. package/dist_ts_interfaces/data/index.js +2 -1
  4. package/dist_ts_interfaces/data/remoteingress.d.ts +10 -1
  5. package/dist_ts_interfaces/data/vpn.d.ts +43 -0
  6. package/dist_ts_interfaces/data/vpn.js +2 -0
  7. package/dist_ts_interfaces/requests/index.d.ts +1 -0
  8. package/dist_ts_interfaces/requests/index.js +2 -1
  9. package/dist_ts_interfaces/requests/vpn.d.ts +135 -0
  10. package/dist_ts_interfaces/requests/vpn.js +3 -0
  11. package/package.json +2 -1
  12. package/readme.md +107 -3
  13. package/ts/00_commitinfo_data.ts +1 -1
  14. package/ts/classes.dcrouter.ts +126 -0
  15. package/ts/config/classes.route-config-manager.ts +20 -3
  16. package/ts/opsserver/classes.opsserver.ts +2 -0
  17. package/ts/opsserver/handlers/index.ts +2 -1
  18. package/ts/opsserver/handlers/vpn.handler.ts +257 -0
  19. package/ts/plugins.ts +2 -1
  20. package/ts/vpn/classes.vpn-manager.ts +378 -0
  21. package/ts/vpn/index.ts +1 -0
  22. package/ts_web/00_commitinfo_data.ts +1 -1
  23. package/ts_web/appstate.ts +164 -0
  24. package/ts_web/elements/index.ts +1 -0
  25. package/ts_web/elements/ops-dashboard.ts +6 -0
  26. package/ts_web/elements/ops-view-vpn.ts +330 -0
  27. package/ts_web/readme.md +17 -0
  28. package/ts_web/router.ts +1 -1
  29. package/dist_ts/00_commitinfo_data.d.ts +0 -8
  30. package/dist_ts/00_commitinfo_data.js +0 -9
  31. package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
  32. package/dist_ts/cache/classes.cache.cleaner.js +0 -130
  33. package/dist_ts/cache/classes.cached.document.d.ts +0 -76
  34. package/dist_ts/cache/classes.cached.document.js +0 -100
  35. package/dist_ts/cache/classes.cachedb.d.ts +0 -60
  36. package/dist_ts/cache/classes.cachedb.js +0 -126
  37. package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
  38. package/dist_ts/cache/documents/classes.cached.email.js +0 -337
  39. package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
  40. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
  41. package/dist_ts/cache/documents/index.d.ts +0 -2
  42. package/dist_ts/cache/documents/index.js +0 -3
  43. package/dist_ts/cache/index.d.ts +0 -4
  44. package/dist_ts/cache/index.js +0 -7
  45. package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -54
  46. package/dist_ts/classes.cert-provision-scheduler.js +0 -118
  47. package/dist_ts/classes.dcrouter.d.ts +0 -356
  48. package/dist_ts/classes.dcrouter.js +0 -1592
  49. package/dist_ts/classes.storage-cert-manager.d.ts +0 -18
  50. package/dist_ts/classes.storage-cert-manager.js +0 -43
  51. package/dist_ts/config/classes.api-token-manager.d.ts +0 -46
  52. package/dist_ts/config/classes.api-token-manager.js +0 -150
  53. package/dist_ts/config/classes.route-config-manager.d.ts +0 -37
  54. package/dist_ts/config/classes.route-config-manager.js +0 -240
  55. package/dist_ts/config/index.d.ts +0 -3
  56. package/dist_ts/config/index.js +0 -5
  57. package/dist_ts/config/validator.d.ts +0 -104
  58. package/dist_ts/config/validator.js +0 -152
  59. package/dist_ts/errors/base.errors.d.ts +0 -224
  60. package/dist_ts/errors/base.errors.js +0 -320
  61. package/dist_ts/errors/error-handler.d.ts +0 -98
  62. package/dist_ts/errors/error-handler.js +0 -282
  63. package/dist_ts/errors/error.codes.d.ts +0 -115
  64. package/dist_ts/errors/error.codes.js +0 -136
  65. package/dist_ts/errors/index.d.ts +0 -54
  66. package/dist_ts/errors/index.js +0 -136
  67. package/dist_ts/errors/reputation.errors.d.ts +0 -183
  68. package/dist_ts/errors/reputation.errors.js +0 -292
  69. package/dist_ts/http3/http3-route-augmentation.d.ts +0 -50
  70. package/dist_ts/http3/http3-route-augmentation.js +0 -98
  71. package/dist_ts/http3/index.d.ts +0 -1
  72. package/dist_ts/http3/index.js +0 -2
  73. package/dist_ts/index.d.ts +0 -8
  74. package/dist_ts/index.js +0 -29
  75. package/dist_ts/logger.d.ts +0 -21
  76. package/dist_ts/logger.js +0 -81
  77. package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
  78. package/dist_ts/monitoring/classes.metricscache.js +0 -63
  79. package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -184
  80. package/dist_ts/monitoring/classes.metricsmanager.js +0 -744
  81. package/dist_ts/monitoring/index.d.ts +0 -1
  82. package/dist_ts/monitoring/index.js +0 -2
  83. package/dist_ts/opsserver/classes.opsserver.d.ts +0 -37
  84. package/dist_ts/opsserver/classes.opsserver.js +0 -85
  85. package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
  86. package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
  87. package/dist_ts/opsserver/handlers/api-token.handler.d.ts +0 -6
  88. package/dist_ts/opsserver/handlers/api-token.handler.js +0 -62
  89. package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -32
  90. package/dist_ts/opsserver/handlers/certificate.handler.js +0 -421
  91. package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
  92. package/dist_ts/opsserver/handlers/config.handler.js +0 -192
  93. package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +0 -30
  94. package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -227
  95. package/dist_ts/opsserver/handlers/index.d.ts +0 -11
  96. package/dist_ts/opsserver/handlers/index.js +0 -12
  97. package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
  98. package/dist_ts/opsserver/handlers/logs.handler.js +0 -256
  99. package/dist_ts/opsserver/handlers/radius.handler.d.ts +0 -6
  100. package/dist_ts/opsserver/handlers/radius.handler.js +0 -295
  101. package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -6
  102. package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -156
  103. package/dist_ts/opsserver/handlers/route-management.handler.d.ts +0 -14
  104. package/dist_ts/opsserver/handlers/route-management.handler.js +0 -117
  105. package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -9
  106. package/dist_ts/opsserver/handlers/security.handler.js +0 -233
  107. package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -11
  108. package/dist_ts/opsserver/handlers/stats.handler.js +0 -403
  109. package/dist_ts/opsserver/helpers/guards.d.ts +0 -27
  110. package/dist_ts/opsserver/helpers/guards.js +0 -43
  111. package/dist_ts/opsserver/index.d.ts +0 -1
  112. package/dist_ts/opsserver/index.js +0 -2
  113. package/dist_ts/paths.d.ts +0 -26
  114. package/dist_ts/paths.js +0 -45
  115. package/dist_ts/plugins.d.ts +0 -80
  116. package/dist_ts/plugins.js +0 -114
  117. package/dist_ts/radius/classes.accounting.manager.d.ts +0 -231
  118. package/dist_ts/radius/classes.accounting.manager.js +0 -462
  119. package/dist_ts/radius/classes.radius.server.d.ts +0 -171
  120. package/dist_ts/radius/classes.radius.server.js +0 -386
  121. package/dist_ts/radius/classes.vlan.manager.d.ts +0 -128
  122. package/dist_ts/radius/classes.vlan.manager.js +0 -279
  123. package/dist_ts/radius/index.d.ts +0 -13
  124. package/dist_ts/radius/index.js +0 -14
  125. package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +0 -94
  126. package/dist_ts/remoteingress/classes.remoteingress-manager.js +0 -271
  127. package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +0 -59
  128. package/dist_ts/remoteingress/classes.tunnel-manager.js +0 -165
  129. package/dist_ts/remoteingress/index.d.ts +0 -2
  130. package/dist_ts/remoteingress/index.js +0 -3
  131. package/dist_ts/security/classes.contentscanner.d.ts +0 -164
  132. package/dist_ts/security/classes.contentscanner.js +0 -642
  133. package/dist_ts/security/classes.ipreputationchecker.d.ts +0 -160
  134. package/dist_ts/security/classes.ipreputationchecker.js +0 -537
  135. package/dist_ts/security/classes.securitylogger.d.ts +0 -144
  136. package/dist_ts/security/classes.securitylogger.js +0 -235
  137. package/dist_ts/security/index.d.ts +0 -3
  138. package/dist_ts/security/index.js +0 -4
  139. package/dist_ts/sms/classes.smsservice.d.ts +0 -15
  140. package/dist_ts/sms/classes.smsservice.js +0 -72
  141. package/dist_ts/sms/config/sms.config.d.ts +0 -93
  142. package/dist_ts/sms/config/sms.config.js +0 -2
  143. package/dist_ts/sms/config/sms.schema.d.ts +0 -5
  144. package/dist_ts/sms/config/sms.schema.js +0 -121
  145. package/dist_ts/sms/index.d.ts +0 -1
  146. package/dist_ts/sms/index.js +0 -2
  147. package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
  148. package/dist_ts/storage/classes.storagemanager.js +0 -348
  149. package/dist_ts/storage/index.d.ts +0 -1
  150. package/dist_ts/storage/index.js +0 -3
  151. package/dist_ts_apiclient/classes.apitoken.d.ts +0 -41
  152. package/dist_ts_apiclient/classes.apitoken.js +0 -115
  153. package/dist_ts_apiclient/classes.certificate.d.ts +0 -57
  154. package/dist_ts_apiclient/classes.certificate.js +0 -69
  155. package/dist_ts_apiclient/classes.config.d.ts +0 -7
  156. package/dist_ts_apiclient/classes.config.js +0 -11
  157. package/dist_ts_apiclient/classes.dcrouterapiclient.d.ts +0 -41
  158. package/dist_ts_apiclient/classes.dcrouterapiclient.js +0 -81
  159. package/dist_ts_apiclient/classes.email.d.ts +0 -30
  160. package/dist_ts_apiclient/classes.email.js +0 -52
  161. package/dist_ts_apiclient/classes.logs.d.ts +0 -21
  162. package/dist_ts_apiclient/classes.logs.js +0 -14
  163. package/dist_ts_apiclient/classes.radius.d.ts +0 -59
  164. package/dist_ts_apiclient/classes.radius.js +0 -95
  165. package/dist_ts_apiclient/classes.remoteingress.d.ts +0 -54
  166. package/dist_ts_apiclient/classes.remoteingress.js +0 -136
  167. package/dist_ts_apiclient/classes.route.d.ts +0 -42
  168. package/dist_ts_apiclient/classes.route.js +0 -154
  169. package/dist_ts_apiclient/classes.stats.d.ts +0 -47
  170. package/dist_ts_apiclient/classes.stats.js +0 -38
  171. package/dist_ts_apiclient/index.d.ts +0 -10
  172. package/dist_ts_apiclient/index.js +0 -14
  173. package/dist_ts_apiclient/plugins.d.ts +0 -3
  174. package/dist_ts_apiclient/plugins.js +0 -5
  175. package/dist_ts_web/00_commitinfo_data.d.ts +0 -8
  176. package/dist_ts_web/00_commitinfo_data.js +0 -9
  177. package/dist_ts_web/appstate.d.ts +0 -216
  178. package/dist_ts_web/appstate.js +0 -1064
  179. package/dist_ts_web/elements/index.d.ts +0 -12
  180. package/dist_ts_web/elements/index.js +0 -13
  181. package/dist_ts_web/elements/ops-dashboard.d.ts +0 -23
  182. package/dist_ts_web/elements/ops-dashboard.js +0 -317
  183. package/dist_ts_web/elements/ops-view-apitokens.d.ts +0 -13
  184. package/dist_ts_web/elements/ops-view-apitokens.js +0 -371
  185. package/dist_ts_web/elements/ops-view-certificates.d.ts +0 -22
  186. package/dist_ts_web/elements/ops-view-certificates.js +0 -528
  187. package/dist_ts_web/elements/ops-view-config.d.ts +0 -19
  188. package/dist_ts_web/elements/ops-view-config.js +0 -339
  189. package/dist_ts_web/elements/ops-view-emails.d.ts +0 -21
  190. package/dist_ts_web/elements/ops-view-emails.js +0 -165
  191. package/dist_ts_web/elements/ops-view-logs.d.ts +0 -13
  192. package/dist_ts_web/elements/ops-view-logs.js +0 -159
  193. package/dist_ts_web/elements/ops-view-network.d.ts +0 -71
  194. package/dist_ts_web/elements/ops-view-network.js +0 -764
  195. package/dist_ts_web/elements/ops-view-overview.d.ts +0 -22
  196. package/dist_ts_web/elements/ops-view-overview.js +0 -456
  197. package/dist_ts_web/elements/ops-view-remoteingress.d.ts +0 -20
  198. package/dist_ts_web/elements/ops-view-remoteingress.js +0 -494
  199. package/dist_ts_web/elements/ops-view-routes.d.ts +0 -12
  200. package/dist_ts_web/elements/ops-view-routes.js +0 -404
  201. package/dist_ts_web/elements/ops-view-security.d.ts +0 -21
  202. package/dist_ts_web/elements/ops-view-security.js +0 -574
  203. package/dist_ts_web/elements/shared/css.d.ts +0 -1
  204. package/dist_ts_web/elements/shared/css.js +0 -10
  205. package/dist_ts_web/elements/shared/index.d.ts +0 -2
  206. package/dist_ts_web/elements/shared/index.js +0 -3
  207. package/dist_ts_web/elements/shared/ops-sectionheading.d.ts +0 -5
  208. package/dist_ts_web/elements/shared/ops-sectionheading.js +0 -82
  209. package/dist_ts_web/index.d.ts +0 -1
  210. package/dist_ts_web/index.js +0 -10
  211. package/dist_ts_web/plugins.d.ts +0 -6
  212. package/dist_ts_web/plugins.js +0 -11
  213. package/dist_ts_web/router.d.ts +0 -19
  214. package/dist_ts_web/router.js +0 -91
@@ -1,462 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- import { logger } from '../logger.js';
3
- /**
4
- * Manages RADIUS accounting data including:
5
- * - Session tracking (start/stop/interim)
6
- * - Data usage tracking (bytes in/out)
7
- * - Session history and retention
8
- * - Billing reports and summaries
9
- */
10
- export class AccountingManager {
11
- activeSessions = new Map();
12
- config;
13
- storageManager;
14
- staleSessionSweepTimer;
15
- // Counters for statistics
16
- stats = {
17
- totalSessionsStarted: 0,
18
- totalSessionsStopped: 0,
19
- totalInputBytes: 0,
20
- totalOutputBytes: 0,
21
- interimUpdatesReceived: 0,
22
- };
23
- constructor(config, storageManager) {
24
- this.config = {
25
- storagePrefix: config?.storagePrefix ?? '/radius/accounting',
26
- retentionDays: config?.retentionDays ?? 30,
27
- detailedLogging: config?.detailedLogging ?? false,
28
- maxActiveSessions: config?.maxActiveSessions ?? 10000,
29
- staleSessionTimeoutHours: config?.staleSessionTimeoutHours ?? 24,
30
- };
31
- this.storageManager = storageManager;
32
- }
33
- /**
34
- * Initialize the accounting manager
35
- */
36
- async initialize() {
37
- if (this.storageManager) {
38
- await this.loadActiveSessions();
39
- }
40
- // Start periodic sweep to evict stale sessions (every 15 minutes)
41
- this.staleSessionSweepTimer = setInterval(() => {
42
- this.sweepStaleSessions();
43
- }, 15 * 60 * 1000);
44
- // Allow the process to exit even if the timer is pending
45
- if (this.staleSessionSweepTimer.unref) {
46
- this.staleSessionSweepTimer.unref();
47
- }
48
- logger.log('info', `AccountingManager initialized with ${this.activeSessions.size} active sessions`);
49
- }
50
- /**
51
- * Stop the accounting manager and clean up timers
52
- */
53
- stop() {
54
- if (this.staleSessionSweepTimer) {
55
- clearInterval(this.staleSessionSweepTimer);
56
- this.staleSessionSweepTimer = undefined;
57
- }
58
- }
59
- /**
60
- * Sweep stale active sessions that have not received any update
61
- * within the configured timeout. These are orphaned sessions where
62
- * the Stop packet was never received.
63
- */
64
- sweepStaleSessions() {
65
- const timeoutMs = this.config.staleSessionTimeoutHours * 60 * 60 * 1000;
66
- const cutoff = Date.now() - timeoutMs;
67
- let swept = 0;
68
- for (const [sessionId, session] of this.activeSessions) {
69
- if (session.lastUpdateTime < cutoff) {
70
- session.status = 'terminated';
71
- session.terminateCause = 'StaleSessionTimeout';
72
- session.endTime = Date.now();
73
- session.sessionTime = Math.floor((session.endTime - session.startTime) / 1000);
74
- if (this.storageManager) {
75
- this.archiveSession(session).catch(() => { });
76
- }
77
- this.activeSessions.delete(sessionId);
78
- swept++;
79
- }
80
- }
81
- if (swept > 0) {
82
- logger.log('info', `Swept ${swept} stale RADIUS sessions (no update for ${this.config.staleSessionTimeoutHours}h)`);
83
- }
84
- }
85
- /**
86
- * Handle accounting start request
87
- */
88
- async handleAccountingStart(data) {
89
- const now = Date.now();
90
- const session = {
91
- sessionId: data.sessionId,
92
- username: data.username,
93
- macAddress: data.macAddress,
94
- nasIpAddress: data.nasIpAddress,
95
- nasPort: data.nasPort,
96
- nasPortType: data.nasPortType,
97
- nasIdentifier: data.nasIdentifier,
98
- vlanId: data.vlanId,
99
- framedIpAddress: data.framedIpAddress,
100
- calledStationId: data.calledStationId,
101
- callingStationId: data.callingStationId,
102
- serviceType: data.serviceType,
103
- startTime: now,
104
- endTime: 0,
105
- lastUpdateTime: now,
106
- status: 'active',
107
- inputOctets: 0,
108
- outputOctets: 0,
109
- inputPackets: 0,
110
- outputPackets: 0,
111
- sessionTime: 0,
112
- };
113
- // Check if we're at capacity
114
- if (this.activeSessions.size >= this.config.maxActiveSessions) {
115
- // Remove oldest session
116
- const oldest = this.findOldestSession();
117
- if (oldest) {
118
- await this.evictSession(oldest);
119
- }
120
- }
121
- this.activeSessions.set(data.sessionId, session);
122
- this.stats.totalSessionsStarted++;
123
- if (this.config.detailedLogging) {
124
- logger.log('info', `Accounting Start: session=${data.sessionId}, user=${data.username}, NAS=${data.nasIpAddress}`);
125
- }
126
- // Persist session
127
- if (this.storageManager) {
128
- await this.persistSession(session);
129
- }
130
- }
131
- /**
132
- * Handle accounting interim update request
133
- */
134
- async handleAccountingUpdate(data) {
135
- const session = this.activeSessions.get(data.sessionId);
136
- if (!session) {
137
- logger.log('warn', `Interim update for unknown session: ${data.sessionId}`);
138
- return;
139
- }
140
- // Update session metrics
141
- if (data.inputOctets !== undefined) {
142
- session.inputOctets = data.inputOctets;
143
- }
144
- if (data.outputOctets !== undefined) {
145
- session.outputOctets = data.outputOctets;
146
- }
147
- if (data.inputPackets !== undefined) {
148
- session.inputPackets = data.inputPackets;
149
- }
150
- if (data.outputPackets !== undefined) {
151
- session.outputPackets = data.outputPackets;
152
- }
153
- if (data.sessionTime !== undefined) {
154
- session.sessionTime = data.sessionTime;
155
- }
156
- session.lastUpdateTime = Date.now();
157
- this.stats.interimUpdatesReceived++;
158
- if (this.config.detailedLogging) {
159
- logger.log('debug', `Accounting Interim: session=${data.sessionId}, in=${data.inputOctets}, out=${data.outputOctets}`);
160
- }
161
- // Update persisted session
162
- if (this.storageManager) {
163
- await this.persistSession(session);
164
- }
165
- }
166
- /**
167
- * Handle accounting stop request
168
- */
169
- async handleAccountingStop(data) {
170
- const session = this.activeSessions.get(data.sessionId);
171
- if (!session) {
172
- logger.log('warn', `Stop for unknown session: ${data.sessionId}`);
173
- return;
174
- }
175
- // Update final metrics
176
- if (data.inputOctets !== undefined) {
177
- session.inputOctets = data.inputOctets;
178
- }
179
- if (data.outputOctets !== undefined) {
180
- session.outputOctets = data.outputOctets;
181
- }
182
- if (data.inputPackets !== undefined) {
183
- session.inputPackets = data.inputPackets;
184
- }
185
- if (data.outputPackets !== undefined) {
186
- session.outputPackets = data.outputPackets;
187
- }
188
- if (data.sessionTime !== undefined) {
189
- session.sessionTime = data.sessionTime;
190
- }
191
- session.endTime = Date.now();
192
- session.lastUpdateTime = session.endTime;
193
- session.status = 'stopped';
194
- session.terminateCause = data.terminateCause;
195
- // Update global stats
196
- this.stats.totalSessionsStopped++;
197
- this.stats.totalInputBytes += session.inputOctets;
198
- this.stats.totalOutputBytes += session.outputOctets;
199
- if (this.config.detailedLogging) {
200
- logger.log('info', `Accounting Stop: session=${data.sessionId}, duration=${session.sessionTime}s, in=${session.inputOctets}, out=${session.outputOctets}`);
201
- }
202
- // Archive the session
203
- if (this.storageManager) {
204
- await this.archiveSession(session);
205
- }
206
- // Remove from active sessions
207
- this.activeSessions.delete(data.sessionId);
208
- }
209
- /**
210
- * Get an active session by ID
211
- */
212
- getSession(sessionId) {
213
- return this.activeSessions.get(sessionId);
214
- }
215
- /**
216
- * Get all active sessions
217
- */
218
- getActiveSessions() {
219
- return Array.from(this.activeSessions.values());
220
- }
221
- /**
222
- * Get active sessions by username
223
- */
224
- getSessionsByUsername(username) {
225
- return Array.from(this.activeSessions.values()).filter(s => s.username === username);
226
- }
227
- /**
228
- * Get active sessions by NAS IP
229
- */
230
- getSessionsByNas(nasIpAddress) {
231
- return Array.from(this.activeSessions.values()).filter(s => s.nasIpAddress === nasIpAddress);
232
- }
233
- /**
234
- * Get active sessions by VLAN
235
- */
236
- getSessionsByVlan(vlanId) {
237
- return Array.from(this.activeSessions.values()).filter(s => s.vlanId === vlanId);
238
- }
239
- /**
240
- * Get accounting summary for a time period
241
- */
242
- async getSummary(startTime, endTime) {
243
- // Get archived sessions for the time period
244
- const archivedSessions = await this.getArchivedSessions(startTime, endTime);
245
- // Combine with active sessions that started within the period
246
- const activeSessions = Array.from(this.activeSessions.values()).filter(s => s.startTime >= startTime && s.startTime <= endTime);
247
- const allSessions = [...archivedSessions, ...activeSessions];
248
- // Calculate summary
249
- let totalInputBytes = 0;
250
- let totalOutputBytes = 0;
251
- let totalSessionTime = 0;
252
- const uniqueUsers = new Set();
253
- const sessionsByVlan = {};
254
- const userTraffic = {};
255
- for (const session of allSessions) {
256
- totalInputBytes += session.inputOctets;
257
- totalOutputBytes += session.outputOctets;
258
- totalSessionTime += session.sessionTime;
259
- uniqueUsers.add(session.username);
260
- if (session.vlanId !== undefined) {
261
- sessionsByVlan[session.vlanId] = (sessionsByVlan[session.vlanId] || 0) + 1;
262
- }
263
- const userBytes = session.inputOctets + session.outputOctets;
264
- userTraffic[session.username] = (userTraffic[session.username] || 0) + userBytes;
265
- }
266
- // Top users by traffic
267
- const topUsersByTraffic = Object.entries(userTraffic)
268
- .sort((a, b) => b[1] - a[1])
269
- .slice(0, 10)
270
- .map(([username, totalBytes]) => ({ username, totalBytes }));
271
- return {
272
- periodStart: startTime,
273
- periodEnd: endTime,
274
- totalSessions: allSessions.length,
275
- activeSessions: activeSessions.length,
276
- totalInputBytes,
277
- totalOutputBytes,
278
- totalSessionTime,
279
- averageSessionDuration: allSessions.length > 0 ? totalSessionTime / allSessions.length : 0,
280
- uniqueUsers: uniqueUsers.size,
281
- sessionsByVlan,
282
- topUsersByTraffic,
283
- };
284
- }
285
- /**
286
- * Get statistics
287
- */
288
- getStats() {
289
- return {
290
- activeSessions: this.activeSessions.size,
291
- ...this.stats,
292
- };
293
- }
294
- /**
295
- * Disconnect a session (admin action)
296
- */
297
- async disconnectSession(sessionId, reason = 'AdminReset') {
298
- const session = this.activeSessions.get(sessionId);
299
- if (!session) {
300
- return false;
301
- }
302
- await this.handleAccountingStop({
303
- sessionId,
304
- terminateCause: reason,
305
- sessionTime: Math.floor((Date.now() - session.startTime) / 1000),
306
- });
307
- return true;
308
- }
309
- /**
310
- * Clean up old archived sessions based on retention policy
311
- */
312
- async cleanupOldSessions() {
313
- if (!this.storageManager) {
314
- return 0;
315
- }
316
- const cutoffTime = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1000;
317
- let deletedCount = 0;
318
- try {
319
- const keys = await this.storageManager.list(`${this.config.storagePrefix}/archive/`);
320
- for (const key of keys) {
321
- try {
322
- const session = await this.storageManager.getJSON(key);
323
- if (session && session.endTime > 0 && session.endTime < cutoffTime) {
324
- await this.storageManager.delete(key);
325
- deletedCount++;
326
- }
327
- }
328
- catch (error) {
329
- // Ignore individual errors
330
- }
331
- }
332
- if (deletedCount > 0) {
333
- logger.log('info', `Cleaned up ${deletedCount} old accounting sessions`);
334
- }
335
- }
336
- catch (error) {
337
- logger.log('error', `Failed to cleanup old sessions: ${error.message}`);
338
- }
339
- return deletedCount;
340
- }
341
- /**
342
- * Find the oldest active session
343
- */
344
- findOldestSession() {
345
- let oldestTime = Infinity;
346
- let oldestSessionId = null;
347
- for (const [sessionId, session] of this.activeSessions) {
348
- if (session.lastUpdateTime < oldestTime) {
349
- oldestTime = session.lastUpdateTime;
350
- oldestSessionId = sessionId;
351
- }
352
- }
353
- return oldestSessionId;
354
- }
355
- /**
356
- * Evict a session from memory
357
- */
358
- async evictSession(sessionId) {
359
- const session = this.activeSessions.get(sessionId);
360
- if (session) {
361
- session.status = 'terminated';
362
- session.terminateCause = 'SessionEvicted';
363
- session.endTime = Date.now();
364
- if (this.storageManager) {
365
- await this.archiveSession(session);
366
- }
367
- this.activeSessions.delete(sessionId);
368
- logger.log('warn', `Evicted session ${sessionId} due to capacity limit`);
369
- }
370
- }
371
- /**
372
- * Load active sessions from storage
373
- */
374
- async loadActiveSessions() {
375
- if (!this.storageManager) {
376
- return;
377
- }
378
- try {
379
- const keys = await this.storageManager.list(`${this.config.storagePrefix}/active/`);
380
- for (const key of keys) {
381
- try {
382
- const session = await this.storageManager.getJSON(key);
383
- if (session && session.status === 'active') {
384
- this.activeSessions.set(session.sessionId, session);
385
- }
386
- }
387
- catch (error) {
388
- // Ignore individual errors
389
- }
390
- }
391
- }
392
- catch (error) {
393
- logger.log('warn', `Failed to load active sessions: ${error.message}`);
394
- }
395
- }
396
- /**
397
- * Persist a session to storage
398
- */
399
- async persistSession(session) {
400
- if (!this.storageManager) {
401
- return;
402
- }
403
- const key = `${this.config.storagePrefix}/active/${session.sessionId}.json`;
404
- try {
405
- await this.storageManager.setJSON(key, session);
406
- }
407
- catch (error) {
408
- logger.log('error', `Failed to persist session ${session.sessionId}: ${error.message}`);
409
- }
410
- }
411
- /**
412
- * Archive a completed session
413
- */
414
- async archiveSession(session) {
415
- if (!this.storageManager) {
416
- return;
417
- }
418
- try {
419
- // Remove from active
420
- const activeKey = `${this.config.storagePrefix}/active/${session.sessionId}.json`;
421
- await this.storageManager.delete(activeKey);
422
- // Add to archive with date-based path
423
- const date = new Date(session.endTime);
424
- const archiveKey = `${this.config.storagePrefix}/archive/${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')}/${session.sessionId}.json`;
425
- await this.storageManager.setJSON(archiveKey, session);
426
- }
427
- catch (error) {
428
- logger.log('error', `Failed to archive session ${session.sessionId}: ${error.message}`);
429
- }
430
- }
431
- /**
432
- * Get archived sessions for a time period
433
- */
434
- async getArchivedSessions(startTime, endTime) {
435
- if (!this.storageManager) {
436
- return [];
437
- }
438
- const sessions = [];
439
- try {
440
- const keys = await this.storageManager.list(`${this.config.storagePrefix}/archive/`);
441
- for (const key of keys) {
442
- try {
443
- const session = await this.storageManager.getJSON(key);
444
- if (session &&
445
- session.endTime > 0 &&
446
- session.startTime <= endTime &&
447
- session.endTime >= startTime) {
448
- sessions.push(session);
449
- }
450
- }
451
- catch (error) {
452
- // Ignore individual errors
453
- }
454
- }
455
- }
456
- catch (error) {
457
- logger.log('warn', `Failed to get archived sessions: ${error.message}`);
458
- }
459
- return sessions;
460
- }
461
- }
462
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hY2NvdW50aW5nLm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9yYWRpdXMvY2xhc3Nlcy5hY2NvdW50aW5nLm1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQWlHdEM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUNwQixjQUFjLEdBQW9DLElBQUksR0FBRyxFQUFFLENBQUM7SUFDNUQsTUFBTSxDQUFxQztJQUMzQyxjQUFjLENBQWtCO0lBQ2hDLHNCQUFzQixDQUFrQztJQUVoRSwwQkFBMEI7SUFDbEIsS0FBSyxHQUFHO1FBQ2Qsb0JBQW9CLEVBQUUsQ0FBQztRQUN2QixvQkFBb0IsRUFBRSxDQUFDO1FBQ3ZCLGVBQWUsRUFBRSxDQUFDO1FBQ2xCLGdCQUFnQixFQUFFLENBQUM7UUFDbkIsc0JBQXNCLEVBQUUsQ0FBQztLQUMxQixDQUFDO0lBRUYsWUFBWSxNQUFpQyxFQUFFLGNBQStCO1FBQzVFLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixhQUFhLEVBQUUsTUFBTSxFQUFFLGFBQWEsSUFBSSxvQkFBb0I7WUFDNUQsYUFBYSxFQUFFLE1BQU0sRUFBRSxhQUFhLElBQUksRUFBRTtZQUMxQyxlQUFlLEVBQUUsTUFBTSxFQUFFLGVBQWUsSUFBSSxLQUFLO1lBQ2pELGlCQUFpQixFQUFFLE1BQU0sRUFBRSxpQkFBaUIsSUFBSSxLQUFLO1lBQ3JELHdCQUF3QixFQUFFLE1BQU0sRUFBRSx3QkFBd0IsSUFBSSxFQUFFO1NBQ2pFLENBQUM7UUFDRixJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsVUFBVTtRQUNkLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFD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
@@ -1,171 +0,0 @@
1
- import type { StorageManager } from '../storage/index.js';
2
- import { VlanManager, type IMacVlanMapping, type IVlanManagerConfig } from './classes.vlan.manager.js';
3
- import { AccountingManager, type IAccountingManagerConfig } from './classes.accounting.manager.js';
4
- /**
5
- * RADIUS client (NAS) configuration
6
- */
7
- export interface IRadiusClient {
8
- /** Client name for identification */
9
- name: string;
10
- /** IP address or CIDR range */
11
- ipRange: string;
12
- /** Shared secret for this client */
13
- secret: string;
14
- /** Optional description */
15
- description?: string;
16
- /** Whether this client is enabled */
17
- enabled: boolean;
18
- }
19
- /**
20
- * RADIUS server configuration
21
- */
22
- export interface IRadiusServerConfig {
23
- /** Authentication port (default: 1812) */
24
- authPort?: number;
25
- /** Accounting port (default: 1813) */
26
- acctPort?: number;
27
- /** Bind address (default: 0.0.0.0) */
28
- bindAddress?: string;
29
- /** NAS clients configuration */
30
- clients: IRadiusClient[];
31
- /** VLAN assignment configuration */
32
- vlanAssignment?: IVlanManagerConfig & {
33
- /** Static MAC to VLAN mappings */
34
- mappings?: Array<Omit<IMacVlanMapping, 'createdAt' | 'updatedAt'>>;
35
- };
36
- /** Accounting configuration */
37
- accounting?: IAccountingManagerConfig & {
38
- /** Whether accounting is enabled */
39
- enabled: boolean;
40
- };
41
- }
42
- /**
43
- * RADIUS authentication result
44
- */
45
- export interface IRadiusAuthResult {
46
- /** Whether authentication was successful */
47
- success: boolean;
48
- /** Reject reason (if not successful) */
49
- rejectReason?: string;
50
- /** Reply message to send to client */
51
- replyMessage?: string;
52
- /** Session timeout in seconds */
53
- sessionTimeout?: number;
54
- /** Idle timeout in seconds */
55
- idleTimeout?: number;
56
- /** VLAN to assign */
57
- vlanId?: number;
58
- /** Framed IP address to assign */
59
- framedIpAddress?: string;
60
- }
61
- /**
62
- * Authentication request data from RADIUS
63
- */
64
- export interface IAuthRequestData {
65
- username: string;
66
- password?: string;
67
- nasIpAddress: string;
68
- nasPort?: number;
69
- nasPortType?: string;
70
- nasIdentifier?: string;
71
- calledStationId?: string;
72
- callingStationId?: string;
73
- serviceType?: string;
74
- framedMtu?: number;
75
- }
76
- /**
77
- * RADIUS Server wrapper that provides:
78
- * - MAC Authentication Bypass (MAB) for network devices
79
- * - VLAN assignment based on MAC address
80
- * - Accounting for session tracking and billing
81
- * - Integration with SmartProxy routing
82
- */
83
- export declare class RadiusServer {
84
- private radiusServer?;
85
- private vlanManager;
86
- private accountingManager;
87
- private config;
88
- private storageManager?;
89
- private clientSecrets;
90
- private running;
91
- private stats;
92
- constructor(config: IRadiusServerConfig, storageManager?: StorageManager);
93
- /**
94
- * Start the RADIUS server
95
- */
96
- start(): Promise<void>;
97
- /**
98
- * Stop the RADIUS server
99
- */
100
- stop(): Promise<void>;
101
- /**
102
- * Handle authentication request
103
- */
104
- private handleAuthentication;
105
- /**
106
- * Handle accounting request
107
- */
108
- private handleAccounting;
109
- /**
110
- * Perform MAC Authentication Bypass
111
- */
112
- private performMabAuthentication;
113
- /**
114
- * Extract MAC address from authentication data
115
- */
116
- private extractMacAddress;
117
- /**
118
- * Check if a string looks like a MAC address
119
- */
120
- private looksLikeMac;
121
- /**
122
- * Normalize MAC address format
123
- */
124
- private normalizeMac;
125
- /**
126
- * Build client secrets map from configuration
127
- */
128
- private buildClientSecretsMap;
129
- /**
130
- * Get default secret for unknown clients
131
- */
132
- private getDefaultSecret;
133
- /**
134
- * Add a RADIUS client
135
- */
136
- addClient(client: IRadiusClient): Promise<void>;
137
- /**
138
- * Remove a RADIUS client
139
- */
140
- removeClient(name: string): boolean;
141
- /**
142
- * Get configured clients
143
- */
144
- getClients(): IRadiusClient[];
145
- /**
146
- * Get VLAN manager for direct access to VLAN operations
147
- */
148
- getVlanManager(): VlanManager;
149
- /**
150
- * Get accounting manager for direct access to accounting operations
151
- */
152
- getAccountingManager(): AccountingManager;
153
- /**
154
- * Get server statistics
155
- */
156
- getStats(): {
157
- running: boolean;
158
- uptime: number;
159
- authRequests: number;
160
- authAccepts: number;
161
- authRejects: number;
162
- accountingRequests: number;
163
- activeSessions: number;
164
- vlanMappings: number;
165
- clients: number;
166
- };
167
- /**
168
- * Check if server is running
169
- */
170
- isRunning(): boolean;
171
- }