@push.rocks/smartproxy 20.0.1 → 21.1.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 (164) hide show
  1. package/changelog.md +26 -0
  2. package/dist_ts/core/utils/proxy-protocol.d.ts +5 -17
  3. package/dist_ts/core/utils/proxy-protocol.js +13 -97
  4. package/dist_ts/core/utils/websocket-utils.d.ts +6 -7
  5. package/dist_ts/core/utils/websocket-utils.js +10 -66
  6. package/dist_ts/detection/detectors/http-detector-v2.d.ts +33 -0
  7. package/dist_ts/detection/detectors/http-detector-v2.js +87 -0
  8. package/dist_ts/detection/detectors/http-detector.d.ts +33 -0
  9. package/dist_ts/detection/detectors/http-detector.js +89 -0
  10. package/dist_ts/detection/detectors/quick-detector.d.ts +28 -0
  11. package/dist_ts/detection/detectors/quick-detector.js +131 -0
  12. package/dist_ts/detection/detectors/routing-extractor.d.ts +28 -0
  13. package/dist_ts/detection/detectors/routing-extractor.js +122 -0
  14. package/dist_ts/detection/detectors/tls-detector-v2.d.ts +33 -0
  15. package/dist_ts/detection/detectors/tls-detector-v2.js +80 -0
  16. package/dist_ts/detection/detectors/tls-detector.d.ts +33 -0
  17. package/dist_ts/detection/detectors/tls-detector.js +106 -0
  18. package/dist_ts/detection/index.d.ts +17 -0
  19. package/dist_ts/detection/index.js +22 -0
  20. package/dist_ts/detection/models/detection-types.d.ts +87 -0
  21. package/dist_ts/detection/models/detection-types.js +5 -0
  22. package/dist_ts/detection/models/interfaces.d.ts +97 -0
  23. package/dist_ts/detection/models/interfaces.js +5 -0
  24. package/dist_ts/detection/protocol-detector-v2.d.ts +46 -0
  25. package/dist_ts/detection/protocol-detector-v2.js +116 -0
  26. package/dist_ts/detection/protocol-detector.d.ts +74 -0
  27. package/dist_ts/detection/protocol-detector.js +173 -0
  28. package/dist_ts/detection/utils/buffer-utils.d.ts +61 -0
  29. package/dist_ts/detection/utils/buffer-utils.js +127 -0
  30. package/dist_ts/detection/utils/fragment-manager.d.ts +31 -0
  31. package/dist_ts/detection/utils/fragment-manager.js +53 -0
  32. package/dist_ts/detection/utils/parser-utils.d.ts +42 -0
  33. package/dist_ts/detection/utils/parser-utils.js +63 -0
  34. package/dist_ts/index.d.ts +2 -1
  35. package/dist_ts/index.js +3 -2
  36. package/dist_ts/protocols/common/fragment-handler.d.ts +73 -0
  37. package/dist_ts/protocols/common/fragment-handler.js +117 -0
  38. package/dist_ts/protocols/common/index.d.ts +7 -0
  39. package/dist_ts/protocols/common/index.js +8 -0
  40. package/dist_ts/protocols/common/types.d.ts +68 -0
  41. package/dist_ts/protocols/common/types.js +7 -0
  42. package/dist_ts/protocols/http/constants.d.ts +119 -0
  43. package/dist_ts/protocols/http/constants.js +200 -0
  44. package/dist_ts/protocols/http/index.d.ts +7 -0
  45. package/dist_ts/protocols/http/index.js +8 -0
  46. package/dist_ts/protocols/http/parser.d.ts +58 -0
  47. package/dist_ts/protocols/http/parser.js +184 -0
  48. package/dist_ts/protocols/http/types.d.ts +62 -0
  49. package/dist_ts/protocols/http/types.js +5 -0
  50. package/dist_ts/protocols/index.d.ts +11 -0
  51. package/dist_ts/protocols/index.js +12 -0
  52. package/dist_ts/protocols/proxy/index.d.ts +6 -0
  53. package/dist_ts/protocols/proxy/index.js +7 -0
  54. package/dist_ts/protocols/proxy/parser.d.ts +44 -0
  55. package/dist_ts/protocols/proxy/parser.js +153 -0
  56. package/dist_ts/protocols/proxy/types.d.ts +47 -0
  57. package/dist_ts/protocols/proxy/types.js +6 -0
  58. package/dist_ts/protocols/tls/alerts/index.d.ts +4 -0
  59. package/dist_ts/protocols/tls/alerts/index.js +5 -0
  60. package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +150 -0
  61. package/dist_ts/protocols/tls/alerts/tls-alert.js +226 -0
  62. package/dist_ts/protocols/tls/constants.d.ts +122 -0
  63. package/dist_ts/protocols/tls/constants.js +135 -0
  64. package/dist_ts/protocols/tls/index.d.ts +12 -0
  65. package/dist_ts/protocols/tls/index.js +27 -0
  66. package/dist_ts/protocols/tls/parser.d.ts +53 -0
  67. package/dist_ts/protocols/tls/parser.js +294 -0
  68. package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +100 -0
  69. package/dist_ts/protocols/tls/sni/client-hello-parser.js +463 -0
  70. package/dist_ts/protocols/tls/sni/index.d.ts +5 -0
  71. package/dist_ts/protocols/tls/sni/index.js +6 -0
  72. package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +58 -0
  73. package/dist_ts/protocols/tls/sni/sni-extraction.js +275 -0
  74. package/dist_ts/protocols/tls/types.d.ts +65 -0
  75. package/dist_ts/protocols/tls/types.js +5 -0
  76. package/dist_ts/protocols/tls/utils/index.d.ts +4 -0
  77. package/dist_ts/protocols/tls/utils/index.js +5 -0
  78. package/dist_ts/protocols/tls/utils/tls-utils.d.ts +158 -0
  79. package/dist_ts/protocols/tls/utils/tls-utils.js +187 -0
  80. package/dist_ts/protocols/websocket/constants.d.ts +55 -0
  81. package/dist_ts/protocols/websocket/constants.js +58 -0
  82. package/dist_ts/protocols/websocket/index.d.ts +7 -0
  83. package/dist_ts/protocols/websocket/index.js +8 -0
  84. package/dist_ts/protocols/websocket/types.d.ts +47 -0
  85. package/dist_ts/protocols/websocket/types.js +5 -0
  86. package/dist_ts/protocols/websocket/utils.d.ts +25 -0
  87. package/dist_ts/protocols/websocket/utils.js +103 -0
  88. package/dist_ts/proxies/http-proxy/models/http-types.d.ts +25 -27
  89. package/dist_ts/proxies/http-proxy/models/http-types.js +24 -44
  90. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -0
  91. package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
  92. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +81 -61
  93. package/dist_ts/proxies/smart-proxy/tls-manager.js +2 -1
  94. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -2
  95. package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
  96. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +112 -8
  97. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +231 -76
  98. package/dist_ts/tls/index.d.ts +5 -7
  99. package/dist_ts/tls/index.js +8 -11
  100. package/dist_ts/tls/sni/client-hello-parser.js +3 -2
  101. package/dist_ts/tls/sni/sni-handler.js +4 -4
  102. package/dist_ts/tls/utils/tls-utils.d.ts +1 -110
  103. package/dist_ts/tls/utils/tls-utils.js +4 -116
  104. package/package.json +17 -8
  105. package/readme.md +471 -2345
  106. package/readme.plan.md +0 -0
  107. package/ts/core/utils/proxy-protocol.ts +14 -131
  108. package/ts/core/utils/websocket-utils.ts +12 -60
  109. package/ts/detection/detectors/http-detector.ts +114 -0
  110. package/ts/detection/detectors/quick-detector.ts +148 -0
  111. package/ts/detection/detectors/routing-extractor.ts +147 -0
  112. package/ts/detection/detectors/tls-detector.ts +120 -0
  113. package/ts/detection/index.ts +25 -0
  114. package/ts/detection/models/detection-types.ts +102 -0
  115. package/ts/detection/models/interfaces.ts +115 -0
  116. package/ts/detection/protocol-detector.ts +230 -0
  117. package/ts/detection/utils/buffer-utils.ts +141 -0
  118. package/ts/detection/utils/fragment-manager.ts +64 -0
  119. package/ts/detection/utils/parser-utils.ts +77 -0
  120. package/ts/index.ts +3 -2
  121. package/ts/protocols/common/fragment-handler.ts +163 -0
  122. package/ts/protocols/common/index.ts +8 -0
  123. package/ts/protocols/common/types.ts +76 -0
  124. package/ts/protocols/http/constants.ts +219 -0
  125. package/ts/protocols/http/index.ts +8 -0
  126. package/ts/protocols/http/parser.ts +219 -0
  127. package/ts/protocols/http/types.ts +70 -0
  128. package/ts/protocols/index.ts +12 -0
  129. package/ts/protocols/proxy/index.ts +7 -0
  130. package/ts/protocols/proxy/parser.ts +183 -0
  131. package/ts/protocols/proxy/types.ts +53 -0
  132. package/ts/{tls → protocols/tls}/alerts/tls-alert.ts +1 -1
  133. package/ts/protocols/tls/index.ts +37 -0
  134. package/ts/protocols/tls/sni/index.ts +6 -0
  135. package/ts/{tls → protocols/tls}/utils/tls-utils.ts +1 -1
  136. package/ts/protocols/websocket/constants.ts +60 -0
  137. package/ts/protocols/websocket/index.ts +8 -0
  138. package/ts/protocols/websocket/types.ts +53 -0
  139. package/ts/protocols/websocket/utils.ts +98 -0
  140. package/ts/proxies/http-proxy/models/http-types.ts +29 -46
  141. package/ts/proxies/smart-proxy/models/interfaces.ts +7 -1
  142. package/ts/proxies/smart-proxy/models/route-types.ts +0 -1
  143. package/ts/proxies/smart-proxy/route-connection-handler.ts +91 -68
  144. package/ts/proxies/smart-proxy/tls-manager.ts +1 -0
  145. package/ts/proxies/smart-proxy/utils/index.ts +2 -13
  146. package/ts/proxies/smart-proxy/utils/route-helpers.ts +323 -86
  147. package/ts/tls/index.ts +8 -12
  148. package/ts/tls/sni/sni-handler.ts +3 -3
  149. package/ts/forwarding/config/forwarding-types.ts +0 -76
  150. package/ts/forwarding/config/index.ts +0 -26
  151. package/ts/forwarding/factory/forwarding-factory.ts +0 -189
  152. package/ts/forwarding/factory/index.ts +0 -5
  153. package/ts/forwarding/handlers/base-handler.ts +0 -155
  154. package/ts/forwarding/handlers/http-handler.ts +0 -163
  155. package/ts/forwarding/handlers/https-passthrough-handler.ts +0 -185
  156. package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +0 -312
  157. package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +0 -297
  158. package/ts/forwarding/handlers/index.ts +0 -9
  159. package/ts/forwarding/index.ts +0 -35
  160. package/ts/proxies/smart-proxy/utils/route-patterns.ts +0 -403
  161. /package/ts/{tls → protocols/tls}/alerts/index.ts +0 -0
  162. /package/ts/{tls → protocols/tls}/sni/client-hello-parser.ts +0 -0
  163. /package/ts/{tls → protocols/tls}/sni/sni-extraction.ts +0 -0
  164. /package/ts/{tls → protocols/tls}/utils/index.ts +0 -0
@@ -10,6 +10,7 @@ import { WrappedSocket } from '../../core/models/wrapped-socket.js';
10
10
  import { getUnderlyingSocket } from '../../core/models/socket-types.js';
11
11
  import { ProxyProtocolParser } from '../../core/utils/proxy-protocol.js';
12
12
  import type { SmartProxy } from './smart-proxy.js';
13
+ import { ProtocolDetector } from '../../detection/index.js';
13
14
 
14
15
  /**
15
16
  * Handles new connection processing and setup logic with support for route-based configuration
@@ -301,11 +302,27 @@ export class RouteConnectionHandler {
301
302
  });
302
303
 
303
304
  // Handler for processing initial data (after potential PROXY protocol)
304
- const processInitialData = (chunk: Buffer) => {
305
+ const processInitialData = async (chunk: Buffer) => {
306
+ // Use ProtocolDetector to identify protocol
307
+ const connectionId = ProtocolDetector.createConnectionId({
308
+ sourceIp: record.remoteIP,
309
+ sourcePort: socket.remotePort,
310
+ destIp: socket.localAddress,
311
+ destPort: socket.localPort,
312
+ socketId: record.id
313
+ });
314
+
315
+ const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
316
+ chunk,
317
+ connectionId,
318
+ { extractFullHeaders: false } // Only extract essential info for routing
319
+ );
320
+
305
321
  // Block non-TLS connections on port 443
306
- if (!this.smartProxy.tlsManager.isTlsHandshake(chunk) && localPort === 443) {
307
- logger.log('warn', `Non-TLS connection ${connectionId} detected on port 443. Terminating connection - only TLS traffic is allowed on standard HTTPS port.`, {
308
- connectionId,
322
+ if (localPort === 443 && detectionResult.protocol !== 'tls') {
323
+ logger.log('warn', `Non-TLS connection ${record.id} detected on port 443. Terminating connection - only TLS traffic is allowed on standard HTTPS port.`, {
324
+ connectionId: record.id,
325
+ detectedProtocol: detectionResult.protocol,
309
326
  message: 'Terminating connection - only TLS traffic is allowed on standard HTTPS port.',
310
327
  component: 'route-handler'
311
328
  });
@@ -318,71 +335,78 @@ export class RouteConnectionHandler {
318
335
  return;
319
336
  }
320
337
 
321
- // Check if this looks like a TLS handshake
338
+ // Extract domain and protocol info
322
339
  let serverName = '';
323
- if (this.smartProxy.tlsManager.isTlsHandshake(chunk)) {
340
+ if (detectionResult.protocol === 'tls') {
324
341
  record.isTLS = true;
342
+ serverName = detectionResult.connectionInfo.domain || '';
343
+
344
+ // Lock the connection to the negotiated SNI
345
+ record.lockedDomain = serverName;
325
346
 
326
- // Check for ClientHello to extract SNI
327
- if (this.smartProxy.tlsManager.isClientHello(chunk)) {
328
- // Create connection info for SNI extraction
329
- const connInfo = {
330
- sourceIp: record.remoteIP,
331
- sourcePort: socket.remotePort || 0,
332
- destIp: socket.localAddress || '',
333
- destPort: socket.localPort || 0,
334
- };
335
-
336
- // Extract SNI
337
- serverName = this.smartProxy.tlsManager.extractSNI(chunk, connInfo) || '';
338
-
339
- // Lock the connection to the negotiated SNI
340
- record.lockedDomain = serverName;
341
-
342
- // Check if we should reject connections without SNI
343
- if (!serverName && this.smartProxy.settings.allowSessionTicket === false) {
344
- logger.log('warn', `No SNI detected in TLS ClientHello for connection ${connectionId}; sending TLS alert`, {
345
- connectionId,
346
- component: 'route-handler'
347
- });
348
- if (record.incomingTerminationReason === null) {
349
- record.incomingTerminationReason = 'session_ticket_blocked_no_sni';
350
- this.smartProxy.connectionManager.incrementTerminationStat(
351
- 'incoming',
352
- 'session_ticket_blocked_no_sni'
353
- );
354
- }
355
- const alert = Buffer.from([0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x70]);
356
- try {
357
- // Count the alert bytes being sent
358
- record.bytesSent += alert.length;
359
- if (this.smartProxy.metricsCollector) {
360
- this.smartProxy.metricsCollector.recordBytes(record.id, 0, alert.length);
361
- }
362
-
363
- socket.cork();
364
- socket.write(alert);
365
- socket.uncork();
366
- socket.end();
367
- } catch {
368
- socket.end();
347
+ // Check if we should reject connections without SNI
348
+ if (!serverName && this.smartProxy.settings.allowSessionTicket === false) {
349
+ logger.log('warn', `No SNI detected in TLS ClientHello for connection ${record.id}; sending TLS alert`, {
350
+ connectionId: record.id,
351
+ component: 'route-handler'
352
+ });
353
+ if (record.incomingTerminationReason === null) {
354
+ record.incomingTerminationReason = 'session_ticket_blocked_no_sni';
355
+ this.smartProxy.connectionManager.incrementTerminationStat(
356
+ 'incoming',
357
+ 'session_ticket_blocked_no_sni'
358
+ );
359
+ }
360
+ const alert = Buffer.from([0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x70]);
361
+ try {
362
+ // Count the alert bytes being sent
363
+ record.bytesSent += alert.length;
364
+ if (this.smartProxy.metricsCollector) {
365
+ this.smartProxy.metricsCollector.recordBytes(record.id, 0, alert.length);
369
366
  }
370
- this.smartProxy.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni');
371
- return;
367
+
368
+ socket.cork();
369
+ socket.write(alert);
370
+ socket.uncork();
371
+ socket.end();
372
+ } catch {
373
+ socket.end();
372
374
  }
375
+ this.smartProxy.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni');
376
+ return;
377
+ }
373
378
 
374
- if (this.smartProxy.settings.enableDetailedLogging) {
375
- logger.log('info', `TLS connection with SNI`, {
376
- connectionId,
377
- serverName: serverName || '(empty)',
378
- component: 'route-handler'
379
- });
380
- }
379
+ if (this.smartProxy.settings.enableDetailedLogging) {
380
+ logger.log('info', `TLS connection with SNI`, {
381
+ connectionId: record.id,
382
+ serverName: serverName || '(empty)',
383
+ component: 'route-handler'
384
+ });
385
+ }
386
+ } else if (detectionResult.protocol === 'http') {
387
+ // For HTTP, extract domain from Host header
388
+ serverName = detectionResult.connectionInfo.domain || '';
389
+
390
+ // Store HTTP-specific info for later use
391
+ record.httpInfo = {
392
+ method: detectionResult.connectionInfo.method,
393
+ path: detectionResult.connectionInfo.path,
394
+ headers: detectionResult.connectionInfo.headers
395
+ };
396
+
397
+ if (this.smartProxy.settings.enableDetailedLogging) {
398
+ logger.log('info', `HTTP connection detected`, {
399
+ connectionId: record.id,
400
+ domain: serverName || '(no host header)',
401
+ method: detectionResult.connectionInfo.method,
402
+ path: detectionResult.connectionInfo.path,
403
+ component: 'route-handler'
404
+ });
381
405
  }
382
406
  }
383
407
 
384
408
  // Find the appropriate route for this connection
385
- this.routeConnection(socket, record, serverName, chunk);
409
+ this.routeConnection(socket, record, serverName, chunk, detectionResult);
386
410
  };
387
411
 
388
412
  // First data handler to capture initial TLS handshake or PROXY protocol
@@ -454,7 +478,8 @@ export class RouteConnectionHandler {
454
478
  socket: plugins.net.Socket | WrappedSocket,
455
479
  record: IConnectionRecord,
456
480
  serverName: string,
457
- initialChunk?: Buffer
481
+ initialChunk?: Buffer,
482
+ detectionResult?: any // Using any temporarily to avoid circular dependency issues
458
483
  ): void {
459
484
  const connectionId = record.id;
460
485
  const localPort = record.localPort;
@@ -635,7 +660,7 @@ export class RouteConnectionHandler {
635
660
  // Handle the route based on its action type
636
661
  switch (route.action.type) {
637
662
  case 'forward':
638
- return this.handleForwardAction(socket, record, route, initialChunk);
663
+ return this.handleForwardAction(socket, record, route, initialChunk, detectionResult);
639
664
 
640
665
  case 'socket-handler':
641
666
  logger.log('info', `Handling socket-handler action for route ${route.name}`, {
@@ -738,7 +763,8 @@ export class RouteConnectionHandler {
738
763
  socket: plugins.net.Socket | WrappedSocket,
739
764
  record: IConnectionRecord,
740
765
  route: IRouteConfig,
741
- initialChunk?: Buffer
766
+ initialChunk?: Buffer,
767
+ detectionResult?: any // Using any temporarily to avoid circular dependency issues
742
768
  ): void {
743
769
  const connectionId = record.id;
744
770
  const action = route.action as IRouteAction;
@@ -819,14 +845,11 @@ export class RouteConnectionHandler {
819
845
  // Create context for target selection
820
846
  const targetSelectionContext = {
821
847
  port: record.localPort,
822
- path: undefined, // Will be populated from HTTP headers if available
823
- headers: undefined, // Will be populated from HTTP headers if available
824
- method: undefined // Will be populated from HTTP headers if available
848
+ path: record.httpInfo?.path,
849
+ headers: record.httpInfo?.headers,
850
+ method: record.httpInfo?.method
825
851
  };
826
852
 
827
- // TODO: Extract path, headers, and method from initialChunk if it's HTTP
828
- // For now, we'll select based on port only
829
-
830
853
  const selectedTarget = this.selectTarget(action.targets, targetSelectionContext);
831
854
  if (!selectedTarget) {
832
855
  logger.log('error', `No matching target found for connection ${connectionId}`, {
@@ -1,5 +1,6 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import { SniHandler } from '../../tls/sni/sni-handler.js';
3
+ import { ProtocolDetector, TlsDetector } from '../../detection/index.js';
3
4
  import type { SmartProxy } from './smart-proxy.js';
4
5
 
5
6
  /**
@@ -14,23 +14,12 @@ export * from './route-validators.js';
14
14
  // Export route utilities for route operations
15
15
  export * from './route-utils.js';
16
16
 
17
- // Export route patterns with renamed exports to avoid conflicts
18
- import {
19
- createWebSocketRoute as createWebSocketPatternRoute,
20
- createLoadBalancerRoute as createLoadBalancerPatternRoute,
21
- createApiGatewayRoute,
22
- addRateLimiting,
23
- addBasicAuth,
24
- addJwtAuth
25
- } from './route-patterns.js';
26
-
17
+ // Export additional functions from route-helpers that weren't already exported
27
18
  export {
28
- createWebSocketPatternRoute,
29
- createLoadBalancerPatternRoute,
30
19
  createApiGatewayRoute,
31
20
  addRateLimiting,
32
21
  addBasicAuth,
33
22
  addJwtAuth
34
- };
23
+ } from './route-helpers.js';
35
24
 
36
25
  // Migration utilities have been removed as they are no longer needed