@push.rocks/smartproxy 21.0.0 → 21.1.1

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 (146) hide show
  1. package/changelog.md +18 -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 +55 -0
  17. package/dist_ts/detection/detectors/tls-detector.js +206 -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 -0
  35. package/dist_ts/index.js +3 -1
  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/route-connection-handler.js +81 -61
  92. package/dist_ts/proxies/smart-proxy/tls-manager.js +2 -1
  93. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +2 -0
  94. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +61 -52
  95. package/dist_ts/tls/index.d.ts +5 -7
  96. package/dist_ts/tls/index.js +8 -11
  97. package/dist_ts/tls/sni/client-hello-parser.js +3 -2
  98. package/dist_ts/tls/sni/sni-handler.js +4 -4
  99. package/dist_ts/tls/utils/tls-utils.d.ts +1 -110
  100. package/dist_ts/tls/utils/tls-utils.js +4 -116
  101. package/package.json +1 -1
  102. package/readme.plan.md +0 -0
  103. package/ts/core/utils/proxy-protocol.ts +14 -131
  104. package/ts/core/utils/websocket-utils.ts +12 -60
  105. package/ts/detection/detectors/http-detector.ts +114 -0
  106. package/ts/detection/detectors/quick-detector.ts +148 -0
  107. package/ts/detection/detectors/routing-extractor.ts +147 -0
  108. package/ts/detection/detectors/tls-detector.ts +252 -0
  109. package/ts/detection/index.ts +25 -0
  110. package/ts/detection/models/detection-types.ts +102 -0
  111. package/ts/detection/models/interfaces.ts +115 -0
  112. package/ts/detection/protocol-detector.ts +230 -0
  113. package/ts/detection/utils/buffer-utils.ts +141 -0
  114. package/ts/detection/utils/fragment-manager.ts +64 -0
  115. package/ts/detection/utils/parser-utils.ts +77 -0
  116. package/ts/index.ts +3 -1
  117. package/ts/protocols/common/fragment-handler.ts +163 -0
  118. package/ts/protocols/common/index.ts +8 -0
  119. package/ts/protocols/common/types.ts +76 -0
  120. package/ts/protocols/http/constants.ts +219 -0
  121. package/ts/protocols/http/index.ts +8 -0
  122. package/ts/protocols/http/parser.ts +219 -0
  123. package/ts/protocols/http/types.ts +70 -0
  124. package/ts/protocols/index.ts +12 -0
  125. package/ts/protocols/proxy/index.ts +7 -0
  126. package/ts/protocols/proxy/parser.ts +183 -0
  127. package/ts/protocols/proxy/types.ts +53 -0
  128. package/ts/{tls → protocols/tls}/alerts/tls-alert.ts +1 -1
  129. package/ts/protocols/tls/index.ts +37 -0
  130. package/ts/protocols/tls/sni/index.ts +6 -0
  131. package/ts/{tls → protocols/tls}/utils/tls-utils.ts +1 -1
  132. package/ts/protocols/websocket/constants.ts +60 -0
  133. package/ts/protocols/websocket/index.ts +8 -0
  134. package/ts/protocols/websocket/types.ts +53 -0
  135. package/ts/protocols/websocket/utils.ts +98 -0
  136. package/ts/proxies/http-proxy/models/http-types.ts +29 -46
  137. package/ts/proxies/smart-proxy/models/interfaces.ts +7 -0
  138. package/ts/proxies/smart-proxy/route-connection-handler.ts +91 -68
  139. package/ts/proxies/smart-proxy/tls-manager.ts +1 -0
  140. package/ts/proxies/smart-proxy/utils/route-helpers.ts +72 -56
  141. package/ts/tls/index.ts +8 -12
  142. package/ts/tls/sni/sni-handler.ts +3 -3
  143. /package/ts/{tls → protocols/tls}/alerts/index.ts +0 -0
  144. /package/ts/{tls → protocols/tls}/sni/client-hello-parser.ts +0 -0
  145. /package/ts/{tls → protocols/tls}/sni/sni-extraction.ts +0 -0
  146. /package/ts/{tls → protocols/tls}/utils/index.ts +0 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Quick Protocol Detector
3
+ *
4
+ * Lightweight protocol identification based on minimal bytes
5
+ * No parsing, just identification
6
+ */
7
+
8
+ import type { IProtocolDetector, IProtocolDetectionResult } from '../../protocols/common/types.js';
9
+ import { TlsRecordType } from '../../protocols/tls/index.js';
10
+ import { HttpParser } from '../../protocols/http/index.js';
11
+
12
+ /**
13
+ * Quick protocol detector for fast identification
14
+ */
15
+ export class QuickProtocolDetector implements IProtocolDetector {
16
+ /**
17
+ * Check if this detector can handle the data
18
+ */
19
+ canHandle(data: Buffer): boolean {
20
+ return data.length >= 1;
21
+ }
22
+
23
+ /**
24
+ * Perform quick detection based on first few bytes
25
+ */
26
+ quickDetect(data: Buffer): IProtocolDetectionResult {
27
+ if (data.length === 0) {
28
+ return {
29
+ protocol: 'unknown',
30
+ confidence: 0,
31
+ requiresMoreData: true
32
+ };
33
+ }
34
+
35
+ // Check for TLS
36
+ const tlsResult = this.checkTls(data);
37
+ if (tlsResult.confidence > 80) {
38
+ return tlsResult;
39
+ }
40
+
41
+ // Check for HTTP
42
+ const httpResult = this.checkHttp(data);
43
+ if (httpResult.confidence > 80) {
44
+ return httpResult;
45
+ }
46
+
47
+ // Need more data or unknown
48
+ return {
49
+ protocol: 'unknown',
50
+ confidence: 0,
51
+ requiresMoreData: data.length < 20
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Check if data looks like TLS
57
+ */
58
+ private checkTls(data: Buffer): IProtocolDetectionResult {
59
+ if (data.length < 3) {
60
+ return {
61
+ protocol: 'tls',
62
+ confidence: 0,
63
+ requiresMoreData: true
64
+ };
65
+ }
66
+
67
+ const firstByte = data[0];
68
+ const secondByte = data[1];
69
+
70
+ // Check for valid TLS record type
71
+ const validRecordTypes = [
72
+ TlsRecordType.CHANGE_CIPHER_SPEC,
73
+ TlsRecordType.ALERT,
74
+ TlsRecordType.HANDSHAKE,
75
+ TlsRecordType.APPLICATION_DATA,
76
+ TlsRecordType.HEARTBEAT
77
+ ];
78
+
79
+ if (!validRecordTypes.includes(firstByte)) {
80
+ return {
81
+ protocol: 'tls',
82
+ confidence: 0
83
+ };
84
+ }
85
+
86
+ // Check TLS version byte (0x03 for all TLS/SSL versions)
87
+ if (secondByte !== 0x03) {
88
+ return {
89
+ protocol: 'tls',
90
+ confidence: 0
91
+ };
92
+ }
93
+
94
+ // High confidence it's TLS
95
+ return {
96
+ protocol: 'tls',
97
+ confidence: 95,
98
+ metadata: {
99
+ recordType: firstByte
100
+ }
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Check if data looks like HTTP
106
+ */
107
+ private checkHttp(data: Buffer): IProtocolDetectionResult {
108
+ if (data.length < 3) {
109
+ return {
110
+ protocol: 'http',
111
+ confidence: 0,
112
+ requiresMoreData: true
113
+ };
114
+ }
115
+
116
+ // Quick check for HTTP methods
117
+ const start = data.subarray(0, Math.min(10, data.length)).toString('ascii');
118
+
119
+ // Check common HTTP methods
120
+ const httpMethods = ['GET ', 'POST ', 'PUT ', 'DELETE ', 'HEAD ', 'OPTIONS', 'PATCH ', 'CONNECT', 'TRACE '];
121
+ for (const method of httpMethods) {
122
+ if (start.startsWith(method)) {
123
+ return {
124
+ protocol: 'http',
125
+ confidence: 95,
126
+ metadata: {
127
+ method: method.trim()
128
+ }
129
+ };
130
+ }
131
+ }
132
+
133
+ // Check if it might be HTTP but need more data
134
+ if (HttpParser.isPrintableAscii(data, Math.min(20, data.length))) {
135
+ // Could be HTTP, but not sure
136
+ return {
137
+ protocol: 'http',
138
+ confidence: 30,
139
+ requiresMoreData: data.length < 20
140
+ };
141
+ }
142
+
143
+ return {
144
+ protocol: 'http',
145
+ confidence: 0
146
+ };
147
+ }
148
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Routing Information Extractor
3
+ *
4
+ * Extracts minimal routing information from protocols
5
+ * without full parsing
6
+ */
7
+
8
+ import type { IRoutingInfo, IConnectionContext, TProtocolType } from '../../protocols/common/types.js';
9
+ import { SniExtraction } from '../../protocols/tls/sni/sni-extraction.js';
10
+ import { HttpParser } from '../../protocols/http/index.js';
11
+
12
+ /**
13
+ * Extracts routing information from protocol data
14
+ */
15
+ export class RoutingExtractor {
16
+ /**
17
+ * Extract routing info based on protocol type
18
+ */
19
+ static extract(
20
+ data: Buffer,
21
+ protocol: TProtocolType,
22
+ context?: IConnectionContext
23
+ ): IRoutingInfo | null {
24
+ switch (protocol) {
25
+ case 'tls':
26
+ case 'https':
27
+ return this.extractTlsRouting(data, context);
28
+
29
+ case 'http':
30
+ return this.extractHttpRouting(data);
31
+
32
+ default:
33
+ return null;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Extract routing from TLS ClientHello (SNI)
39
+ */
40
+ private static extractTlsRouting(
41
+ data: Buffer,
42
+ context?: IConnectionContext
43
+ ): IRoutingInfo | null {
44
+ try {
45
+ // Quick SNI extraction without full parsing
46
+ const sni = SniExtraction.extractSNI(data);
47
+
48
+ if (sni) {
49
+ return {
50
+ domain: sni,
51
+ protocol: 'tls',
52
+ port: 443 // Default HTTPS port
53
+ };
54
+ }
55
+
56
+ return null;
57
+ } catch (error) {
58
+ // Extraction failed, return null
59
+ return null;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Extract routing from HTTP headers (Host header)
65
+ */
66
+ private static extractHttpRouting(data: Buffer): IRoutingInfo | null {
67
+ try {
68
+ // Look for first line
69
+ const firstLineEnd = data.indexOf('\n');
70
+ if (firstLineEnd === -1) {
71
+ return null;
72
+ }
73
+
74
+ // Parse request line
75
+ const firstLine = data.subarray(0, firstLineEnd).toString('ascii').trim();
76
+ const requestLine = HttpParser.parseRequestLine(firstLine);
77
+
78
+ if (!requestLine) {
79
+ return null;
80
+ }
81
+
82
+ // Look for Host header
83
+ let pos = firstLineEnd + 1;
84
+ const maxSearch = Math.min(data.length, 4096); // Don't search too far
85
+
86
+ while (pos < maxSearch) {
87
+ const lineEnd = data.indexOf('\n', pos);
88
+ if (lineEnd === -1) break;
89
+
90
+ const line = data.subarray(pos, lineEnd).toString('ascii').trim();
91
+
92
+ // Empty line means end of headers
93
+ if (line.length === 0) break;
94
+
95
+ // Check for Host header
96
+ if (line.toLowerCase().startsWith('host:')) {
97
+ const hostValue = line.substring(5).trim();
98
+ const domain = HttpParser.extractDomainFromHost(hostValue);
99
+
100
+ return {
101
+ domain,
102
+ path: requestLine.path,
103
+ protocol: 'http',
104
+ port: 80 // Default HTTP port
105
+ };
106
+ }
107
+
108
+ pos = lineEnd + 1;
109
+ }
110
+
111
+ // No Host header found, but we have the path
112
+ return {
113
+ path: requestLine.path,
114
+ protocol: 'http',
115
+ port: 80
116
+ };
117
+ } catch (error) {
118
+ // Extraction failed
119
+ return null;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Try to extract domain from any protocol
125
+ */
126
+ static extractDomain(data: Buffer, hint?: TProtocolType): string | null {
127
+ // If we have a hint, use it
128
+ if (hint) {
129
+ const routing = this.extract(data, hint);
130
+ return routing?.domain || null;
131
+ }
132
+
133
+ // Try TLS first (more specific)
134
+ const tlsRouting = this.extractTlsRouting(data);
135
+ if (tlsRouting?.domain) {
136
+ return tlsRouting.domain;
137
+ }
138
+
139
+ // Try HTTP
140
+ const httpRouting = this.extractHttpRouting(data);
141
+ if (httpRouting?.domain) {
142
+ return httpRouting.domain;
143
+ }
144
+
145
+ return null;
146
+ }
147
+ }
@@ -0,0 +1,252 @@
1
+ /**
2
+ * TLS protocol detector
3
+ */
4
+
5
+ // TLS detector doesn't need plugins imports
6
+ import type { IProtocolDetector } from '../models/interfaces.js';
7
+ import type { IDetectionResult, IDetectionOptions, IConnectionInfo } from '../models/detection-types.js';
8
+ import { readUInt16BE, BufferAccumulator } from '../utils/buffer-utils.js';
9
+ import { tlsVersionToString } from '../utils/parser-utils.js';
10
+
11
+ // Import from protocols
12
+ import { TlsRecordType, TlsHandshakeType, TlsExtensionType } from '../../protocols/tls/index.js';
13
+
14
+ // Import TLS utilities for SNI extraction from protocols
15
+ import { SniExtraction } from '../../protocols/tls/sni/sni-extraction.js';
16
+ import { ClientHelloParser } from '../../protocols/tls/sni/client-hello-parser.js';
17
+
18
+ /**
19
+ * TLS detector implementation
20
+ */
21
+ export class TlsDetector implements IProtocolDetector {
22
+ /**
23
+ * Minimum bytes needed to identify TLS (record header)
24
+ */
25
+ private static readonly MIN_TLS_HEADER_SIZE = 5;
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
+
39
+ /**
40
+ * Detect TLS protocol from buffer
41
+ */
42
+ detect(buffer: Buffer, options?: IDetectionOptions): IDetectionResult | null {
43
+ // Check if buffer is too small
44
+ if (buffer.length < TlsDetector.MIN_TLS_HEADER_SIZE) {
45
+ return null;
46
+ }
47
+
48
+ // Check if this is a TLS record
49
+ if (!this.isTlsRecord(buffer)) {
50
+ return null;
51
+ }
52
+
53
+ // Extract basic TLS info
54
+ const recordType = buffer[0];
55
+ const tlsMajor = buffer[1];
56
+ const tlsMinor = buffer[2];
57
+ const recordLength = readUInt16BE(buffer, 3);
58
+
59
+ // Initialize connection info
60
+ const connectionInfo: IConnectionInfo = {
61
+ protocol: 'tls',
62
+ tlsVersion: tlsVersionToString(tlsMajor, tlsMinor) || undefined
63
+ };
64
+
65
+ // If it's a handshake, try to extract more info
66
+ if (recordType === TlsRecordType.HANDSHAKE && buffer.length >= 6) {
67
+ const handshakeType = buffer[5];
68
+
69
+ // For ClientHello, extract SNI and other info
70
+ if (handshakeType === TlsHandshakeType.CLIENT_HELLO) {
71
+ // Check if we have the complete handshake
72
+ const totalRecordLength = recordLength + 5; // Including TLS header
73
+ if (buffer.length >= totalRecordLength) {
74
+ // Extract SNI using existing logic
75
+ const sni = SniExtraction.extractSNI(buffer);
76
+ if (sni) {
77
+ connectionInfo.domain = sni;
78
+ connectionInfo.sni = sni;
79
+ }
80
+
81
+ // Parse ClientHello for additional info
82
+ const parseResult = ClientHelloParser.parseClientHello(buffer);
83
+ if (parseResult.isValid) {
84
+ // Extract ALPN if present
85
+ const alpnExtension = parseResult.extensions.find(
86
+ ext => ext.type === TlsExtensionType.APPLICATION_LAYER_PROTOCOL_NEGOTIATION
87
+ );
88
+
89
+ if (alpnExtension) {
90
+ connectionInfo.alpn = this.parseAlpnExtension(alpnExtension.data);
91
+ }
92
+
93
+ // Store cipher suites if needed
94
+ if (parseResult.cipherSuites && options?.extractFullHeaders) {
95
+ connectionInfo.cipherSuites = this.parseCipherSuites(parseResult.cipherSuites);
96
+ }
97
+ }
98
+
99
+ // Return complete result
100
+ return {
101
+ protocol: 'tls',
102
+ connectionInfo,
103
+ remainingBuffer: buffer.length > totalRecordLength
104
+ ? buffer.subarray(totalRecordLength)
105
+ : undefined,
106
+ isComplete: true
107
+ };
108
+ } else {
109
+ // Incomplete handshake
110
+ return {
111
+ protocol: 'tls',
112
+ connectionInfo,
113
+ isComplete: false,
114
+ bytesNeeded: totalRecordLength
115
+ };
116
+ }
117
+ }
118
+ }
119
+
120
+ // For other TLS record types, just return basic info
121
+ return {
122
+ protocol: 'tls',
123
+ connectionInfo,
124
+ isComplete: true,
125
+ remainingBuffer: buffer.length > recordLength + 5
126
+ ? buffer.subarray(recordLength + 5)
127
+ : undefined
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Check if buffer can be handled by this detector
133
+ */
134
+ canHandle(buffer: Buffer): boolean {
135
+ return buffer.length >= TlsDetector.MIN_TLS_HEADER_SIZE &&
136
+ this.isTlsRecord(buffer);
137
+ }
138
+
139
+ /**
140
+ * Get minimum bytes needed for detection
141
+ */
142
+ getMinimumBytes(): number {
143
+ return TlsDetector.MIN_TLS_HEADER_SIZE;
144
+ }
145
+
146
+ /**
147
+ * Check if buffer contains a valid TLS record
148
+ */
149
+ private isTlsRecord(buffer: Buffer): boolean {
150
+ const recordType = buffer[0];
151
+
152
+ // Check for valid record type
153
+ const validTypes = [
154
+ TlsRecordType.CHANGE_CIPHER_SPEC,
155
+ TlsRecordType.ALERT,
156
+ TlsRecordType.HANDSHAKE,
157
+ TlsRecordType.APPLICATION_DATA,
158
+ TlsRecordType.HEARTBEAT
159
+ ];
160
+
161
+ if (!validTypes.includes(recordType)) {
162
+ return false;
163
+ }
164
+
165
+ // Check TLS version bytes (should be 0x03 0x0X)
166
+ if (buffer[1] !== 0x03) {
167
+ return false;
168
+ }
169
+
170
+ // Check record length is reasonable
171
+ const recordLength = readUInt16BE(buffer, 3);
172
+ if (recordLength > 16384) { // Max TLS record size
173
+ return false;
174
+ }
175
+
176
+ return true;
177
+ }
178
+
179
+ /**
180
+ * Parse ALPN extension data
181
+ */
182
+ private parseAlpnExtension(data: Buffer): string[] {
183
+ const protocols: string[] = [];
184
+
185
+ if (data.length < 2) {
186
+ return protocols;
187
+ }
188
+
189
+ const listLength = readUInt16BE(data, 0);
190
+ let offset = 2;
191
+
192
+ while (offset < Math.min(2 + listLength, data.length)) {
193
+ const protoLength = data[offset];
194
+ offset++;
195
+
196
+ if (offset + protoLength <= data.length) {
197
+ const protocol = data.subarray(offset, offset + protoLength).toString('ascii');
198
+ protocols.push(protocol);
199
+ offset += protoLength;
200
+ } else {
201
+ break;
202
+ }
203
+ }
204
+
205
+ return protocols;
206
+ }
207
+
208
+ /**
209
+ * Parse cipher suites
210
+ */
211
+ private parseCipherSuites(cipherData: Buffer): number[] {
212
+ const suites: number[] = [];
213
+
214
+ for (let i = 0; i < cipherData.length - 1; i += 2) {
215
+ const suite = readUInt16BE(cipherData, i);
216
+ suites.push(suite);
217
+ }
218
+
219
+ return suites;
220
+ }
221
+
222
+ /**
223
+ * Detect with context for fragmented data
224
+ */
225
+ detectWithContext(
226
+ buffer: Buffer,
227
+ context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
228
+ options?: IDetectionOptions
229
+ ): 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;
251
+ }
252
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Centralized Protocol Detection Module
3
+ *
4
+ * This module provides unified protocol detection capabilities for
5
+ * both TLS and HTTP protocols, extracting connection information
6
+ * without consuming the data stream.
7
+ */
8
+
9
+ // Main detector
10
+ export * from './protocol-detector.js';
11
+
12
+ // Models
13
+ export * from './models/detection-types.js';
14
+ export * from './models/interfaces.js';
15
+
16
+ // Individual detectors
17
+ export * from './detectors/tls-detector.js';
18
+ export * from './detectors/http-detector.js';
19
+ export * from './detectors/quick-detector.js';
20
+ export * from './detectors/routing-extractor.js';
21
+
22
+ // Utilities
23
+ export * from './utils/buffer-utils.js';
24
+ export * from './utils/parser-utils.js';
25
+ export * from './utils/fragment-manager.js';
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Type definitions for protocol detection
3
+ */
4
+
5
+ /**
6
+ * Supported protocol types that can be detected
7
+ */
8
+ export type TProtocolType = 'tls' | 'http' | 'unknown';
9
+
10
+ /**
11
+ * HTTP method types
12
+ */
13
+ export type THttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
14
+
15
+ /**
16
+ * TLS version identifiers
17
+ */
18
+ export type TTlsVersion = 'SSLv3' | 'TLSv1.0' | 'TLSv1.1' | 'TLSv1.2' | 'TLSv1.3';
19
+
20
+ /**
21
+ * Connection information extracted from protocol detection
22
+ */
23
+ export interface IConnectionInfo {
24
+ /**
25
+ * The detected protocol type
26
+ */
27
+ protocol: TProtocolType;
28
+
29
+ /**
30
+ * Domain/hostname extracted from the connection
31
+ * - For TLS: from SNI extension
32
+ * - For HTTP: from Host header
33
+ */
34
+ domain?: string;
35
+
36
+ /**
37
+ * HTTP-specific fields
38
+ */
39
+ method?: THttpMethod;
40
+ path?: string;
41
+ httpVersion?: string;
42
+ headers?: Record<string, string>;
43
+
44
+ /**
45
+ * TLS-specific fields
46
+ */
47
+ tlsVersion?: TTlsVersion;
48
+ sni?: string;
49
+ alpn?: string[];
50
+ cipherSuites?: number[];
51
+ }
52
+
53
+ /**
54
+ * Result of protocol detection
55
+ */
56
+ export interface IDetectionResult {
57
+ /**
58
+ * The detected protocol type
59
+ */
60
+ protocol: TProtocolType;
61
+
62
+ /**
63
+ * Extracted connection information
64
+ */
65
+ connectionInfo: IConnectionInfo;
66
+
67
+ /**
68
+ * Any remaining buffer data after detection headers
69
+ * This can be used to continue processing the stream
70
+ */
71
+ remainingBuffer?: Buffer;
72
+
73
+ /**
74
+ * Whether the detection is complete or needs more data
75
+ */
76
+ isComplete: boolean;
77
+
78
+ /**
79
+ * Minimum bytes needed for complete detection (if incomplete)
80
+ */
81
+ bytesNeeded?: number;
82
+ }
83
+
84
+ /**
85
+ * Options for protocol detection
86
+ */
87
+ export interface IDetectionOptions {
88
+ /**
89
+ * Maximum bytes to buffer for detection (default: 8192)
90
+ */
91
+ maxBufferSize?: number;
92
+
93
+ /**
94
+ * Timeout for detection in milliseconds (default: 5000)
95
+ */
96
+ timeout?: number;
97
+
98
+ /**
99
+ * Whether to extract full headers or just essential info
100
+ */
101
+ extractFullHeaders?: boolean;
102
+ }