@push.rocks/smartproxy 21.1.1 → 21.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "21.1.1",
3
+ "version": "21.1.2",
4
4
  "private": false,
5
5
  "description": "A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.",
6
6
  "main": "dist_ts/index.js",
@@ -5,7 +5,7 @@
5
5
  // TLS detector doesn't need plugins imports
6
6
  import type { IProtocolDetector } from '../models/interfaces.js';
7
7
  import type { IDetectionResult, IDetectionOptions, IConnectionInfo } from '../models/detection-types.js';
8
- import { readUInt16BE, BufferAccumulator } from '../utils/buffer-utils.js';
8
+ import { readUInt16BE } from '../utils/buffer-utils.js';
9
9
  import { tlsVersionToString } from '../utils/parser-utils.js';
10
10
 
11
11
  // Import from protocols
@@ -24,17 +24,6 @@ export class TlsDetector implements IProtocolDetector {
24
24
  */
25
25
  private static readonly MIN_TLS_HEADER_SIZE = 5;
26
26
 
27
- /**
28
- * Fragment tracking for incomplete handshakes
29
- */
30
- private static fragmentedBuffers = new Map<string, BufferAccumulator>();
31
-
32
- /**
33
- * Create connection ID from context
34
- */
35
- private createConnectionId(context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number }): string {
36
- return `${context.sourceIp || 'unknown'}:${context.sourcePort || 0}->${context.destIp || 'unknown'}:${context.destPort || 0}`;
37
- }
38
27
 
39
28
  /**
40
29
  * Detect TLS protocol from buffer
@@ -224,29 +213,11 @@ export class TlsDetector implements IProtocolDetector {
224
213
  */
225
214
  detectWithContext(
226
215
  buffer: Buffer,
227
- context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
216
+ _context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
228
217
  options?: IDetectionOptions
229
218
  ): IDetectionResult | null {
230
- const connectionId = this.createConnectionId(context);
231
-
232
- // Get or create buffer accumulator for this connection
233
- let accumulator = TlsDetector.fragmentedBuffers.get(connectionId);
234
- if (!accumulator) {
235
- accumulator = new BufferAccumulator();
236
- TlsDetector.fragmentedBuffers.set(connectionId, accumulator);
237
- }
238
-
239
- // Add new data
240
- accumulator.append(buffer);
241
-
242
- // Try detection on accumulated data
243
- const result = this.detect(accumulator.getBuffer(), options);
244
-
245
- // If detection is complete or we have too much data, clean up
246
- if (result?.isComplete || accumulator.length() > 65536) {
247
- TlsDetector.fragmentedBuffers.delete(connectionId);
248
- }
249
-
250
- return result;
219
+ // This method is deprecated - TLS detection should use the fragment manager
220
+ // from the parent detector system, not maintain its own fragments
221
+ return this.detect(buffer, options);
251
222
  }
252
223
  }
@@ -120,10 +120,28 @@ export class ProtocolDetector {
120
120
  };
121
121
  }
122
122
 
123
+ const connectionId = DetectionFragmentManager.createConnectionId(context);
124
+
123
125
  // First peek to determine protocol type
124
126
  if (this.tlsDetector.canHandle(buffer)) {
125
- const result = this.tlsDetector.detectWithContext(buffer, context, options);
127
+ // Handle TLS with fragment accumulation
128
+ const handler = this.fragmentManager.getHandler('tls');
129
+ const fragmentResult = handler.addFragment(connectionId, buffer);
130
+
131
+ if (fragmentResult.error) {
132
+ handler.complete(connectionId);
133
+ return {
134
+ protocol: 'unknown',
135
+ connectionInfo: { protocol: 'unknown' },
136
+ isComplete: true
137
+ };
138
+ }
139
+
140
+ const result = this.tlsDetector.detect(fragmentResult.buffer!, options);
126
141
  if (result) {
142
+ if (result.isComplete) {
143
+ handler.complete(connectionId);
144
+ }
127
145
  return result;
128
146
  }
129
147
  }
@@ -173,13 +191,25 @@ export class ProtocolDetector {
173
191
  /**
174
192
  * Clean up old connection tracking entries
175
193
  *
176
- * @param maxAge Maximum age in milliseconds (default: 30 seconds)
194
+ * @param _maxAge Maximum age in milliseconds (default: 30 seconds)
177
195
  */
178
- static cleanupConnections(maxAge: number = 30000): void {
196
+ static cleanupConnections(_maxAge: number = 30000): void {
179
197
  // Cleanup is now handled internally by the fragment manager
180
198
  this.getInstance().fragmentManager.cleanup();
181
199
  }
182
200
 
201
+ /**
202
+ * Clean up fragments for a specific connection
203
+ */
204
+ static cleanupConnection(context: IConnectionContext): void {
205
+ const instance = this.getInstance();
206
+ const connectionId = DetectionFragmentManager.createConnectionId(context);
207
+
208
+ // Clean up both TLS and HTTP fragments for this connection
209
+ instance.fragmentManager.getHandler('tls').complete(connectionId);
210
+ instance.fragmentManager.getHandler('http').complete(connectionId);
211
+ }
212
+
183
213
  /**
184
214
  * Extract domain from connection info
185
215
  */
@@ -5,6 +5,7 @@ import { connectionLogDeduplicator } from '../../core/utils/log-deduplicator.js'
5
5
  import { LifecycleComponent } from '../../core/utils/lifecycle-component.js';
6
6
  import { cleanupSocket } from '../../core/utils/socket-utils.js';
7
7
  import { WrappedSocket } from '../../core/models/wrapped-socket.js';
8
+ import { ProtocolDetector } from '../../detection/index.js';
8
9
  import type { SmartProxy } from './smart-proxy.js';
9
10
 
10
11
  /**
@@ -323,6 +324,18 @@ export class ConnectionManager extends LifecycleComponent {
323
324
  this.smartProxy.metricsCollector.removeConnection(record.id);
324
325
  }
325
326
 
327
+ // Clean up protocol detection fragments
328
+ const context = ProtocolDetector.createConnectionContext({
329
+ sourceIp: record.remoteIP,
330
+ sourcePort: record.incoming?.remotePort || 0,
331
+ destIp: record.incoming?.localAddress || '',
332
+ destPort: record.localPort,
333
+ socketId: record.id
334
+ });
335
+
336
+ // Clean up any pending detection fragments for this connection
337
+ ProtocolDetector.cleanupConnection(context);
338
+
326
339
  if (record.cleanupTimer) {
327
340
  clearTimeout(record.cleanupTimer);
328
341
  record.cleanupTimer = undefined;
@@ -303,18 +303,18 @@ export class RouteConnectionHandler {
303
303
 
304
304
  // Handler for processing initial data (after potential PROXY protocol)
305
305
  const processInitialData = async (chunk: Buffer) => {
306
- // Use ProtocolDetector to identify protocol
307
- const connectionId = ProtocolDetector.createConnectionId({
306
+ // Create connection context for protocol detection
307
+ const context = ProtocolDetector.createConnectionContext({
308
308
  sourceIp: record.remoteIP,
309
- sourcePort: socket.remotePort,
310
- destIp: socket.localAddress,
311
- destPort: socket.localPort,
309
+ sourcePort: socket.remotePort || 0,
310
+ destIp: socket.localAddress || '',
311
+ destPort: socket.localPort || 0,
312
312
  socketId: record.id
313
313
  });
314
314
 
315
- const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
315
+ const detectionResult = await ProtocolDetector.detectWithContext(
316
316
  chunk,
317
- connectionId,
317
+ context,
318
318
  { extractFullHeaders: false } // Only extract essential info for routing
319
319
  );
320
320