@push.rocks/smartproxy 19.6.13 → 19.6.15

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 (32) hide show
  1. package/dist_ts/core/utils/log-deduplicator.d.ts +39 -0
  2. package/dist_ts/core/utils/log-deduplicator.js +297 -0
  3. package/dist_ts/core/utils/shared-security-manager.d.ts +2 -1
  4. package/dist_ts/core/utils/shared-security-manager.js +22 -2
  5. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +1 -0
  6. package/dist_ts/proxies/http-proxy/http-proxy.js +94 -9
  7. package/dist_ts/proxies/http-proxy/models/types.d.ts +2 -0
  8. package/dist_ts/proxies/http-proxy/models/types.js +1 -1
  9. package/dist_ts/proxies/http-proxy/security-manager.d.ts +42 -1
  10. package/dist_ts/proxies/http-proxy/security-manager.js +121 -2
  11. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +14 -0
  12. package/dist_ts/proxies/smart-proxy/connection-manager.js +86 -32
  13. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +5 -1
  14. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +1 -0
  15. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +25 -9
  16. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +9 -0
  17. package/dist_ts/proxies/smart-proxy/security-manager.js +63 -1
  18. package/dist_ts/proxies/smart-proxy/smart-proxy.js +4 -1
  19. package/package.json +1 -1
  20. package/readme.hints.md +113 -1
  21. package/readme.plan.md +34 -353
  22. package/ts/core/utils/log-deduplicator.ts +361 -0
  23. package/ts/core/utils/shared-security-manager.ts +24 -1
  24. package/ts/proxies/http-proxy/http-proxy.ts +129 -9
  25. package/ts/proxies/http-proxy/models/types.ts +4 -0
  26. package/ts/proxies/http-proxy/security-manager.ts +136 -1
  27. package/ts/proxies/smart-proxy/connection-manager.ts +113 -36
  28. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +5 -0
  29. package/ts/proxies/smart-proxy/models/interfaces.ts +1 -0
  30. package/ts/proxies/smart-proxy/route-connection-handler.ts +52 -15
  31. package/ts/proxies/smart-proxy/security-manager.ts +76 -1
  32. package/ts/proxies/smart-proxy/smart-proxy.ts +4 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Log deduplication utility to reduce log spam for repetitive events
3
+ */
4
+ export declare class LogDeduplicator {
5
+ private globalFlushTimer?;
6
+ private aggregatedEvents;
7
+ private flushInterval;
8
+ private maxBatchSize;
9
+ private rapidEventThreshold;
10
+ private lastRapidCheck;
11
+ constructor(flushInterval?: number);
12
+ /**
13
+ * Log a deduplicated event
14
+ * @param key - Aggregation key (e.g., 'connection-rejected', 'cleanup-batch')
15
+ * @param level - Log level
16
+ * @param message - Log message template
17
+ * @param data - Additional data
18
+ * @param dedupeKey - Deduplication key within the aggregation (e.g., IP address, reason)
19
+ */
20
+ log(key: string, level: 'info' | 'warn' | 'error' | 'debug', message: string, data?: any, dedupeKey?: string): void;
21
+ /**
22
+ * Flush aggregated events for a specific key
23
+ */
24
+ flush(key: string): void;
25
+ /**
26
+ * Flush all pending events
27
+ */
28
+ flushAll(): void;
29
+ private flushConnectionRejections;
30
+ private flushConnectionCleanups;
31
+ private flushConnectionTerminations;
32
+ private flushIPRejections;
33
+ private flushGeneric;
34
+ /**
35
+ * Cleanup and stop deduplication
36
+ */
37
+ cleanup(): void;
38
+ }
39
+ export declare const connectionLogDeduplicator: LogDeduplicator;
@@ -0,0 +1,297 @@
1
+ import { logger } from './logger.js';
2
+ /**
3
+ * Log deduplication utility to reduce log spam for repetitive events
4
+ */
5
+ export class LogDeduplicator {
6
+ constructor(flushInterval) {
7
+ this.aggregatedEvents = new Map();
8
+ this.flushInterval = 5000; // 5 seconds
9
+ this.maxBatchSize = 100;
10
+ this.rapidEventThreshold = 50; // Flush early if this many events in 1 second
11
+ this.lastRapidCheck = Date.now();
12
+ if (flushInterval) {
13
+ this.flushInterval = flushInterval;
14
+ }
15
+ // Set up global periodic flush to ensure logs are emitted regularly
16
+ this.globalFlushTimer = setInterval(() => {
17
+ this.flushAll();
18
+ }, this.flushInterval * 2); // Flush everything every 2x the normal interval
19
+ if (this.globalFlushTimer.unref) {
20
+ this.globalFlushTimer.unref();
21
+ }
22
+ }
23
+ /**
24
+ * Log a deduplicated event
25
+ * @param key - Aggregation key (e.g., 'connection-rejected', 'cleanup-batch')
26
+ * @param level - Log level
27
+ * @param message - Log message template
28
+ * @param data - Additional data
29
+ * @param dedupeKey - Deduplication key within the aggregation (e.g., IP address, reason)
30
+ */
31
+ log(key, level, message, data, dedupeKey) {
32
+ const eventKey = dedupeKey || message;
33
+ const now = Date.now();
34
+ if (!this.aggregatedEvents.has(key)) {
35
+ this.aggregatedEvents.set(key, {
36
+ key,
37
+ events: new Map(),
38
+ flushTimer: undefined
39
+ });
40
+ }
41
+ const aggregated = this.aggregatedEvents.get(key);
42
+ if (aggregated.events.has(eventKey)) {
43
+ const event = aggregated.events.get(eventKey);
44
+ event.count++;
45
+ event.lastSeen = now;
46
+ if (data) {
47
+ event.data = { ...event.data, ...data };
48
+ }
49
+ }
50
+ else {
51
+ aggregated.events.set(eventKey, {
52
+ level,
53
+ message,
54
+ data,
55
+ count: 1,
56
+ firstSeen: now,
57
+ lastSeen: now
58
+ });
59
+ }
60
+ // Check for rapid events (many events in short time)
61
+ const totalEvents = Array.from(aggregated.events.values()).reduce((sum, e) => sum + e.count, 0);
62
+ // If we're getting flooded with events, flush more frequently
63
+ if (now - this.lastRapidCheck < 1000 && totalEvents >= this.rapidEventThreshold) {
64
+ this.flush(key);
65
+ this.lastRapidCheck = now;
66
+ }
67
+ else if (aggregated.events.size >= this.maxBatchSize) {
68
+ // Check if we should flush due to size
69
+ this.flush(key);
70
+ }
71
+ else if (!aggregated.flushTimer) {
72
+ // Schedule flush
73
+ aggregated.flushTimer = setTimeout(() => {
74
+ this.flush(key);
75
+ }, this.flushInterval);
76
+ if (aggregated.flushTimer.unref) {
77
+ aggregated.flushTimer.unref();
78
+ }
79
+ }
80
+ // Update rapid check time
81
+ if (now - this.lastRapidCheck >= 1000) {
82
+ this.lastRapidCheck = now;
83
+ }
84
+ }
85
+ /**
86
+ * Flush aggregated events for a specific key
87
+ */
88
+ flush(key) {
89
+ const aggregated = this.aggregatedEvents.get(key);
90
+ if (!aggregated || aggregated.events.size === 0) {
91
+ return;
92
+ }
93
+ if (aggregated.flushTimer) {
94
+ clearTimeout(aggregated.flushTimer);
95
+ aggregated.flushTimer = undefined;
96
+ }
97
+ // Emit aggregated log based on the key
98
+ switch (key) {
99
+ case 'connection-rejected':
100
+ this.flushConnectionRejections(aggregated);
101
+ break;
102
+ case 'connection-cleanup':
103
+ this.flushConnectionCleanups(aggregated);
104
+ break;
105
+ case 'connection-terminated':
106
+ this.flushConnectionTerminations(aggregated);
107
+ break;
108
+ case 'ip-rejected':
109
+ this.flushIPRejections(aggregated);
110
+ break;
111
+ default:
112
+ this.flushGeneric(aggregated);
113
+ }
114
+ // Clear events
115
+ aggregated.events.clear();
116
+ }
117
+ /**
118
+ * Flush all pending events
119
+ */
120
+ flushAll() {
121
+ for (const key of this.aggregatedEvents.keys()) {
122
+ this.flush(key);
123
+ }
124
+ }
125
+ flushConnectionRejections(aggregated) {
126
+ const totalCount = Array.from(aggregated.events.values()).reduce((sum, e) => sum + e.count, 0);
127
+ const byReason = new Map();
128
+ for (const [, event] of aggregated.events) {
129
+ const reason = event.data?.reason || 'unknown';
130
+ byReason.set(reason, (byReason.get(reason) || 0) + event.count);
131
+ }
132
+ const reasonSummary = Array.from(byReason.entries())
133
+ .sort((a, b) => b[1] - a[1])
134
+ .map(([reason, count]) => `${reason}: ${count}`)
135
+ .join(', ');
136
+ const duration = Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen));
137
+ logger.log('warn', `[SUMMARY] Rejected ${totalCount} connections in ${Math.round(duration / 1000)}s`, {
138
+ reasons: reasonSummary,
139
+ uniqueIPs: aggregated.events.size,
140
+ component: 'connection-dedup'
141
+ });
142
+ }
143
+ flushConnectionCleanups(aggregated) {
144
+ const totalCount = Array.from(aggregated.events.values()).reduce((sum, e) => sum + e.count, 0);
145
+ const byReason = new Map();
146
+ for (const [, event] of aggregated.events) {
147
+ const reason = event.data?.reason || 'normal';
148
+ byReason.set(reason, (byReason.get(reason) || 0) + event.count);
149
+ }
150
+ const reasonSummary = Array.from(byReason.entries())
151
+ .sort((a, b) => b[1] - a[1])
152
+ .slice(0, 5) // Top 5 reasons
153
+ .map(([reason, count]) => `${reason}: ${count}`)
154
+ .join(', ');
155
+ logger.log('info', `Cleaned up ${totalCount} connections`, {
156
+ reasons: reasonSummary,
157
+ duration: Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen)),
158
+ component: 'connection-dedup'
159
+ });
160
+ }
161
+ flushConnectionTerminations(aggregated) {
162
+ const totalCount = Array.from(aggregated.events.values()).reduce((sum, e) => sum + e.count, 0);
163
+ const byReason = new Map();
164
+ const byIP = new Map();
165
+ let lastActiveCount = 0;
166
+ for (const [, event] of aggregated.events) {
167
+ const reason = event.data?.reason || 'unknown';
168
+ const ip = event.data?.remoteIP || 'unknown';
169
+ byReason.set(reason, (byReason.get(reason) || 0) + event.count);
170
+ // Track by IP
171
+ if (ip !== 'unknown') {
172
+ byIP.set(ip, (byIP.get(ip) || 0) + event.count);
173
+ }
174
+ // Track the last active connection count
175
+ if (event.data?.activeConnections !== undefined) {
176
+ lastActiveCount = event.data.activeConnections;
177
+ }
178
+ }
179
+ const reasonSummary = Array.from(byReason.entries())
180
+ .sort((a, b) => b[1] - a[1])
181
+ .slice(0, 5) // Top 5 reasons
182
+ .map(([reason, count]) => `${reason}: ${count}`)
183
+ .join(', ');
184
+ // Show top IPs if there are many different ones
185
+ let ipInfo = '';
186
+ if (byIP.size > 3) {
187
+ const topIPs = Array.from(byIP.entries())
188
+ .sort((a, b) => b[1] - a[1])
189
+ .slice(0, 3)
190
+ .map(([ip, count]) => `${ip} (${count})`)
191
+ .join(', ');
192
+ ipInfo = `, from ${byIP.size} IPs (top: ${topIPs})`;
193
+ }
194
+ else if (byIP.size > 0) {
195
+ ipInfo = `, IPs: ${Array.from(byIP.keys()).join(', ')}`;
196
+ }
197
+ const duration = Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen));
198
+ // Special handling for localhost connections (HttpProxy)
199
+ const localhostCount = byIP.get('::ffff:127.0.0.1') || 0;
200
+ if (localhostCount > 0 && byIP.size === 1) {
201
+ // All connections are from localhost (HttpProxy)
202
+ logger.log('info', `[SUMMARY] ${totalCount} HttpProxy connections terminated in ${Math.round(duration / 1000)}s`, {
203
+ reasons: reasonSummary,
204
+ activeConnections: lastActiveCount,
205
+ component: 'connection-dedup'
206
+ });
207
+ }
208
+ else {
209
+ logger.log('info', `[SUMMARY] ${totalCount} connections terminated in ${Math.round(duration / 1000)}s`, {
210
+ reasons: reasonSummary,
211
+ activeConnections: lastActiveCount,
212
+ uniqueReasons: byReason.size,
213
+ ...(ipInfo ? { ips: ipInfo } : {}),
214
+ component: 'connection-dedup'
215
+ });
216
+ }
217
+ }
218
+ flushIPRejections(aggregated) {
219
+ const byIP = new Map();
220
+ for (const [ip, event] of aggregated.events) {
221
+ if (!byIP.has(ip)) {
222
+ byIP.set(ip, { count: 0, reasons: new Set() });
223
+ }
224
+ const ipData = byIP.get(ip);
225
+ ipData.count += event.count;
226
+ if (event.data?.reason) {
227
+ ipData.reasons.add(event.data.reason);
228
+ }
229
+ }
230
+ // Log top offenders
231
+ const topOffenders = Array.from(byIP.entries())
232
+ .sort((a, b) => b[1].count - a[1].count)
233
+ .slice(0, 10)
234
+ .map(([ip, data]) => `${ip} (${data.count}x, ${Array.from(data.reasons).join('/')})`)
235
+ .join(', ');
236
+ const totalRejections = Array.from(byIP.values()).reduce((sum, data) => sum + data.count, 0);
237
+ const duration = Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen));
238
+ logger.log('warn', `[SUMMARY] Rejected ${totalRejections} connections from ${byIP.size} IPs in ${Math.round(duration / 1000)}s`, {
239
+ topOffenders,
240
+ component: 'ip-dedup'
241
+ });
242
+ }
243
+ flushGeneric(aggregated) {
244
+ const totalCount = Array.from(aggregated.events.values()).reduce((sum, e) => sum + e.count, 0);
245
+ const level = aggregated.events.values().next().value?.level || 'info';
246
+ // Special handling for IP cleanup events
247
+ if (aggregated.key === 'ip-cleanup') {
248
+ const totalCleaned = Array.from(aggregated.events.values()).reduce((sum, e) => {
249
+ return sum + (e.data?.cleanedIPs || 0) + (e.data?.cleanedRateLimits || 0);
250
+ }, 0);
251
+ if (totalCleaned > 0) {
252
+ logger.log(level, `IP tracking cleanup: removed ${totalCleaned} entries across ${totalCount} cleanup cycles`, {
253
+ duration: Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen)),
254
+ component: 'log-dedup'
255
+ });
256
+ }
257
+ }
258
+ else {
259
+ logger.log(level, `${aggregated.key}: ${totalCount} events`, {
260
+ uniqueEvents: aggregated.events.size,
261
+ duration: Date.now() - Math.min(...Array.from(aggregated.events.values()).map(e => e.firstSeen)),
262
+ component: 'log-dedup'
263
+ });
264
+ }
265
+ }
266
+ /**
267
+ * Cleanup and stop deduplication
268
+ */
269
+ cleanup() {
270
+ this.flushAll();
271
+ if (this.globalFlushTimer) {
272
+ clearInterval(this.globalFlushTimer);
273
+ this.globalFlushTimer = undefined;
274
+ }
275
+ for (const aggregated of this.aggregatedEvents.values()) {
276
+ if (aggregated.flushTimer) {
277
+ clearTimeout(aggregated.flushTimer);
278
+ }
279
+ }
280
+ this.aggregatedEvents.clear();
281
+ }
282
+ }
283
+ // Global instance for connection-related log deduplication
284
+ export const connectionLogDeduplicator = new LogDeduplicator(5000); // 5 second batches
285
+ // Ensure logs are flushed on process exit
286
+ process.on('beforeExit', () => {
287
+ connectionLogDeduplicator.flushAll();
288
+ });
289
+ process.on('SIGINT', () => {
290
+ connectionLogDeduplicator.cleanup();
291
+ process.exit(0);
292
+ });
293
+ process.on('SIGTERM', () => {
294
+ connectionLogDeduplicator.cleanup();
295
+ process.exit(0);
296
+ });
297
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nLWRlZHVwbGljYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2NvcmUvdXRpbHMvbG9nLWRlZHVwbGljYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBaUJyQzs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBUTFCLFlBQVksYUFBc0I7UUFOMUIscUJBQWdCLEdBQWtDLElBQUksR0FBRyxFQUFFLENBQUM7UUFDNUQsa0JBQWEsR0FBVyxJQUFJLENBQUMsQ0FBQyxZQUFZO1FBQzFDLGlCQUFZLEdBQVcsR0FBRyxDQUFDO1FBQzNCLHdCQUFtQixHQUFXLEVBQUUsQ0FBQyxDQUFDLDhDQUE4QztRQUNoRixtQkFBYyxHQUFXLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUcxQyxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ3JDLENBQUM7UUFFRCxvRUFBb0U7UUFDcEUsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDdkMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLENBQUMsRUFBRSxJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0RBQWdEO1FBRTVFLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSSxHQUFHLENBQ1IsR0FBVyxFQUNYLEtBQTBDLEVBQzFDLE9BQWUsRUFDZixJQUFVLEVBQ1YsU0FBa0I7UUFFbEIsTUFBTSxRQUFRLEdBQUcsU0FBUyxJQUFJLE9BQU8sQ0FBQztRQUN0QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENB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TSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvRixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztRQUUzQyxLQUFLLE1BQU0sQ0FBQyxFQUFFLEtBQUssQ0FBQyxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMxQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQU0sSUFBSSxTQUFTLENBQUM7WUFDL0MsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDakQsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxNQUFNLEtBQUssS0FBSyxFQUFFLENBQUM7YUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUN4RyxNQUFNLENBQUMsR0FB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
@@ -66,9 +66,10 @@ export declare class SharedSecurityManager {
66
66
  *
67
67
  * @param route - The route to check
68
68
  * @param context - The request context
69
+ * @param routeConnectionCount - Current connection count for this route (optional)
69
70
  * @returns Whether access is allowed
70
71
  */
71
- isAllowed(route: IRouteConfig, context: IRouteContext): boolean;
72
+ isAllowed(route: IRouteConfig, context: IRouteContext, routeConnectionCount?: number): boolean;
72
73
  /**
73
74
  * Check if a client IP is allowed for a route
74
75
  *
@@ -101,9 +101,10 @@ export class SharedSecurityManager {
101
101
  *
102
102
  * @param route - The route to check
103
103
  * @param context - The request context
104
+ * @param routeConnectionCount - Current connection count for this route (optional)
104
105
  * @returns Whether access is allowed
105
106
  */
106
- isAllowed(route, context) {
107
+ isAllowed(route, context, routeConnectionCount) {
107
108
  if (!route.security) {
108
109
  return true; // No security restrictions
109
110
  }
@@ -112,6 +113,13 @@ export class SharedSecurityManager {
112
113
  this.logger?.debug?.(`IP ${context.clientIp} is blocked for route ${route.name || 'unnamed'}`);
113
114
  return false;
114
115
  }
116
+ // --- Route-level connection limit ---
117
+ if (route.security.maxConnections !== undefined && routeConnectionCount !== undefined) {
118
+ if (routeConnectionCount >= route.security.maxConnections) {
119
+ this.logger?.debug?.(`Route connection limit (${route.security.maxConnections}) exceeded for route ${route.name || 'unnamed'}`);
120
+ return false;
121
+ }
122
+ }
115
123
  // --- Rate limiting ---
116
124
  if (route.security.rateLimit?.enabled && !this.isWithinRateLimit(route, context)) {
117
125
  this.logger?.debug?.(`Rate limit exceeded for route ${route.name || 'unnamed'}`);
@@ -225,6 +233,18 @@ export class SharedSecurityManager {
225
233
  cleanupCaches() {
226
234
  // Clean up rate limits
227
235
  cleanupExpiredRateLimits(this.rateLimits, this.logger);
236
+ // Clean up IP connection tracking
237
+ let cleanedIPs = 0;
238
+ for (const [ip, info] of this.connectionsByIP.entries()) {
239
+ // Remove IPs with no active connections and no recent timestamps
240
+ if (info.connections.size === 0 && info.timestamps.length === 0) {
241
+ this.connectionsByIP.delete(ip);
242
+ cleanedIPs++;
243
+ }
244
+ }
245
+ if (cleanedIPs > 0 && this.logger?.debug) {
246
+ this.logger.debug(`Cleaned up ${cleanedIPs} IPs with no active connections`);
247
+ }
228
248
  // IP filter cache doesn't need cleanup (tied to routes)
229
249
  }
230
250
  /**
@@ -249,4 +269,4 @@ export class SharedSecurityManager {
249
269
  this.ipFilterCache.clear();
250
270
  }
251
271
  }
252
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLXNlY3VyaXR5LW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL3NoYXJlZC1zZWN1cml0eS1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFRNUMsT0FBTyxFQUNMLGNBQWMsRUFDZCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLGVBQWUsRUFDZixnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNyQixNQUFNLHFCQUFxQixDQUFDO0FBRTdCOzs7R0FHRztBQUNILE1BQU0sT0FBTyxxQkFBcUI7SUFpQmhDOzs7OztPQUtHO0lBQ0gsWUFBWSxPQUtYLEVBQVUsTUFBd0I7UUFBeEIsV0FBTSxHQUFOLE1BQU0sQ0FBa0I7UUEzQm5DLHlCQUF5QjtRQUNqQixvQkFBZSxHQUFtQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRXBFLCtCQUErQjtRQUN2QixlQUFVLEdBQTZDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFekUsOERBQThEO1FBQ3RELGtCQUFhLEdBQXNDLElBQUksR0FBRyxFQUFFLENBQUM7UUFNckUseUJBQXlCO1FBQ2pCLG9CQUFlLEdBQTBCLElBQUksQ0FBQztRQWNwRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixJQUFJLEdBQUcsQ0FBQztRQUM5RCxJQUFJLENBQUMsNEJBQTRCLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixJQUFJLEdBQUcsQ0FBQztRQUVoRiw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUk7WUFDdEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxHQUFHO1lBQ2pCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtZQUNsQixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7U0FDckIsQ0FBQztRQUVGLGdDQUFnQztRQUNoQyxNQUFN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
272
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLXNlY3VyaXR5LW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL3NoYXJlZC1zZWN1cml0eS1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFRNUMsT0FBTyxFQUNMLGNBQWMsRUFDZCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLGVBQWUsRUFDZixnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNyQixNQUFNLHFCQUFxQixDQUFDO0FBRTdCOzs7R0FHRztBQUNILE1BQU0sT0FBTyxxQkFBcUI7SUFpQmhDOzs7OztPQUtHO0lBQ0gsWUFBWSxPQUtYLEVBQVUsTUFBd0I7UUFBeEIsV0FBTSxHQUFOLE1BQU0sQ0FBa0I7UUEzQm5DLHlCQUF5QjtRQUNqQixvQkFBZSxHQUFtQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRXBFLCtCQUErQjtRQUN2QixlQUFVLEdBQTZDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFekUsOERBQThEO1FBQ3RELGtCQUFhLEdBQXNDLElBQUksR0FBRyxFQUFFLENBQUM7UUFNckUseUJBQXlCO1FBQ2pCLG9CQUFlLEdBQTBCLElBQUksQ0FBQztRQWNwRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixJQUFJLEdBQUcsQ0FBQztRQUM5RCxJQUFJLENBQUMsNEJBQTRCLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixJQUFJLEdBQUcsQ0FBQztRQUVoRiw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUk7WUFDdEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxHQUFHO1lBQ2pCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtZQUNsQixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7U0FDckIsQ0FBQztRQUVGLGdDQUFnQztRQUNoQyxNQUFN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
@@ -19,6 +19,7 @@ export declare class HttpProxy implements IMetricsTracker {
19
19
  private router;
20
20
  private routeManager;
21
21
  private functionCache;
22
+ private securityManager;
22
23
  socketMap: plugins.lik.ObjectMap<plugins.net.Socket>;
23
24
  activeContexts: Set<string>;
24
25
  connectedClients: number;