@push.rocks/smartproxy 21.0.0 → 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 (146) hide show
  1. package/changelog.md +9 -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 -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 +17 -8
  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 +120 -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,70 @@
1
+ /**
2
+ * HTTP Protocol Type Definitions
3
+ */
4
+
5
+ import type { THttpMethod, THttpVersion, HttpStatus } from './constants.js';
6
+
7
+ /**
8
+ * HTTP request line structure
9
+ */
10
+ export interface IHttpRequestLine {
11
+ method: THttpMethod;
12
+ path: string;
13
+ version: THttpVersion;
14
+ }
15
+
16
+ /**
17
+ * HTTP response line structure
18
+ */
19
+ export interface IHttpResponseLine {
20
+ version: THttpVersion;
21
+ status: HttpStatus;
22
+ statusText: string;
23
+ }
24
+
25
+ /**
26
+ * HTTP header structure
27
+ */
28
+ export interface IHttpHeader {
29
+ name: string;
30
+ value: string;
31
+ }
32
+
33
+ /**
34
+ * HTTP message structure (base for request and response)
35
+ */
36
+ export interface IHttpMessage {
37
+ headers: Record<string, string>;
38
+ body?: Buffer;
39
+ }
40
+
41
+ /**
42
+ * HTTP request structure
43
+ */
44
+ export interface IHttpRequest extends IHttpMessage {
45
+ method: THttpMethod;
46
+ path: string;
47
+ version: THttpVersion;
48
+ query?: Record<string, string>;
49
+ }
50
+
51
+ /**
52
+ * HTTP response structure
53
+ */
54
+ export interface IHttpResponse extends IHttpMessage {
55
+ status: HttpStatus;
56
+ statusText: string;
57
+ version: THttpVersion;
58
+ }
59
+
60
+ /**
61
+ * Parsed URL structure
62
+ */
63
+ export interface IParsedUrl {
64
+ protocol?: string;
65
+ hostname?: string;
66
+ port?: number;
67
+ path?: string;
68
+ query?: string;
69
+ fragment?: string;
70
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Protocol-specific modules for smartproxy
3
+ *
4
+ * This directory contains generic protocol knowledge separated from
5
+ * smartproxy-specific implementation details.
6
+ */
7
+
8
+ export * as common from './common/index.js';
9
+ export * as tls from './tls/index.js';
10
+ export * as http from './http/index.js';
11
+ export * as proxy from './proxy/index.js';
12
+ export * as websocket from './websocket/index.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * PROXY Protocol Module
3
+ * HAProxy PROXY protocol implementation
4
+ */
5
+
6
+ export * from './types.js';
7
+ export * from './parser.js';
@@ -0,0 +1,183 @@
1
+ /**
2
+ * PROXY Protocol Parser
3
+ * Implementation of HAProxy PROXY protocol v1 (text format)
4
+ * Spec: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
5
+ */
6
+
7
+ import type { IProxyInfo, IProxyParseResult, TProxyProtocol } from './types.js';
8
+
9
+ /**
10
+ * PROXY protocol parser
11
+ */
12
+ export class ProxyProtocolParser {
13
+ static readonly PROXY_V1_SIGNATURE = 'PROXY ';
14
+ static readonly MAX_HEADER_LENGTH = 107; // Max length for v1 header
15
+ static readonly HEADER_TERMINATOR = '\r\n';
16
+
17
+ /**
18
+ * Parse PROXY protocol v1 header from buffer
19
+ * Returns proxy info and remaining data after header
20
+ */
21
+ static parse(data: Buffer): IProxyParseResult {
22
+ // Check if buffer starts with PROXY signature
23
+ if (!data.toString('ascii', 0, 6).startsWith(this.PROXY_V1_SIGNATURE)) {
24
+ return {
25
+ proxyInfo: null,
26
+ remainingData: data
27
+ };
28
+ }
29
+
30
+ // Find header terminator
31
+ const headerEndIndex = data.indexOf(this.HEADER_TERMINATOR);
32
+ if (headerEndIndex === -1) {
33
+ // Header incomplete, need more data
34
+ if (data.length > this.MAX_HEADER_LENGTH) {
35
+ // Header too long, invalid
36
+ throw new Error('PROXY protocol header exceeds maximum length');
37
+ }
38
+ return {
39
+ proxyInfo: null,
40
+ remainingData: data
41
+ };
42
+ }
43
+
44
+ // Extract header line
45
+ const headerLine = data.toString('ascii', 0, headerEndIndex);
46
+ const remainingData = data.slice(headerEndIndex + 2); // Skip \r\n
47
+
48
+ // Parse header
49
+ const parts = headerLine.split(' ');
50
+
51
+ if (parts.length < 2) {
52
+ throw new Error(`Invalid PROXY protocol header format: ${headerLine}`);
53
+ }
54
+
55
+ const [signature, protocol] = parts;
56
+
57
+ // Validate protocol
58
+ if (!['TCP4', 'TCP6', 'UNKNOWN'].includes(protocol)) {
59
+ throw new Error(`Invalid PROXY protocol: ${protocol}`);
60
+ }
61
+
62
+ // For UNKNOWN protocol, ignore addresses
63
+ if (protocol === 'UNKNOWN') {
64
+ return {
65
+ proxyInfo: {
66
+ protocol: 'UNKNOWN',
67
+ sourceIP: '',
68
+ sourcePort: 0,
69
+ destinationIP: '',
70
+ destinationPort: 0
71
+ },
72
+ remainingData
73
+ };
74
+ }
75
+
76
+ // For TCP4/TCP6, we need all 6 parts
77
+ if (parts.length !== 6) {
78
+ throw new Error(`Invalid PROXY protocol header format: ${headerLine}`);
79
+ }
80
+
81
+ const [, , srcIP, dstIP, srcPort, dstPort] = parts;
82
+
83
+ // Validate and parse ports
84
+ const sourcePort = parseInt(srcPort, 10);
85
+ const destinationPort = parseInt(dstPort, 10);
86
+
87
+ if (isNaN(sourcePort) || sourcePort < 0 || sourcePort > 65535) {
88
+ throw new Error(`Invalid source port: ${srcPort}`);
89
+ }
90
+
91
+ if (isNaN(destinationPort) || destinationPort < 0 || destinationPort > 65535) {
92
+ throw new Error(`Invalid destination port: ${dstPort}`);
93
+ }
94
+
95
+ // Validate IP addresses
96
+ const protocolType = protocol as TProxyProtocol;
97
+ if (!this.isValidIP(srcIP, protocolType)) {
98
+ throw new Error(`Invalid source IP for ${protocol}: ${srcIP}`);
99
+ }
100
+
101
+ if (!this.isValidIP(dstIP, protocolType)) {
102
+ throw new Error(`Invalid destination IP for ${protocol}: ${dstIP}`);
103
+ }
104
+
105
+ return {
106
+ proxyInfo: {
107
+ protocol: protocolType,
108
+ sourceIP: srcIP,
109
+ sourcePort,
110
+ destinationIP: dstIP,
111
+ destinationPort
112
+ },
113
+ remainingData
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Generate PROXY protocol v1 header
119
+ */
120
+ static generate(info: IProxyInfo): Buffer {
121
+ if (info.protocol === 'UNKNOWN') {
122
+ return Buffer.from(`PROXY UNKNOWN\r\n`, 'ascii');
123
+ }
124
+
125
+ const header = `PROXY ${info.protocol} ${info.sourceIP} ${info.destinationIP} ${info.sourcePort} ${info.destinationPort}\r\n`;
126
+
127
+ if (header.length > this.MAX_HEADER_LENGTH) {
128
+ throw new Error('Generated PROXY protocol header exceeds maximum length');
129
+ }
130
+
131
+ return Buffer.from(header, 'ascii');
132
+ }
133
+
134
+ /**
135
+ * Validate IP address format
136
+ */
137
+ static isValidIP(ip: string, protocol: TProxyProtocol): boolean {
138
+ if (protocol === 'TCP4') {
139
+ return this.isIPv4(ip);
140
+ } else if (protocol === 'TCP6') {
141
+ return this.isIPv6(ip);
142
+ }
143
+ return false;
144
+ }
145
+
146
+ /**
147
+ * Check if string is valid IPv4
148
+ */
149
+ static isIPv4(ip: string): boolean {
150
+ const parts = ip.split('.');
151
+ if (parts.length !== 4) return false;
152
+
153
+ for (const part of parts) {
154
+ const num = parseInt(part, 10);
155
+ if (isNaN(num) || num < 0 || num > 255 || part !== num.toString()) {
156
+ return false;
157
+ }
158
+ }
159
+ return true;
160
+ }
161
+
162
+ /**
163
+ * Check if string is valid IPv6
164
+ */
165
+ static isIPv6(ip: string): boolean {
166
+ // Basic IPv6 validation
167
+ const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
168
+ return ipv6Regex.test(ip);
169
+ }
170
+
171
+ /**
172
+ * Create a connection ID string for tracking
173
+ */
174
+ static createConnectionId(connectionInfo: {
175
+ sourceIp?: string;
176
+ sourcePort?: number;
177
+ destIp?: string;
178
+ destPort?: number;
179
+ }): string {
180
+ const { sourceIp, sourcePort, destIp, destPort } = connectionInfo;
181
+ return `${sourceIp}:${sourcePort}-${destIp}:${destPort}`;
182
+ }
183
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * PROXY Protocol Type Definitions
3
+ * Based on HAProxy PROXY protocol specification
4
+ */
5
+
6
+ /**
7
+ * PROXY protocol version
8
+ */
9
+ export type TProxyProtocolVersion = 'v1' | 'v2';
10
+
11
+ /**
12
+ * Connection protocol type
13
+ */
14
+ export type TProxyProtocol = 'TCP4' | 'TCP6' | 'UNKNOWN';
15
+
16
+ /**
17
+ * Interface representing parsed PROXY protocol information
18
+ */
19
+ export interface IProxyInfo {
20
+ protocol: TProxyProtocol;
21
+ sourceIP: string;
22
+ sourcePort: number;
23
+ destinationIP: string;
24
+ destinationPort: number;
25
+ }
26
+
27
+ /**
28
+ * Interface for parse result including remaining data
29
+ */
30
+ export interface IProxyParseResult {
31
+ proxyInfo: IProxyInfo | null;
32
+ remainingData: Buffer;
33
+ }
34
+
35
+ /**
36
+ * PROXY protocol v2 header format
37
+ */
38
+ export interface IProxyV2Header {
39
+ signature: Buffer;
40
+ versionCommand: number;
41
+ family: number;
42
+ length: number;
43
+ }
44
+
45
+ /**
46
+ * Connection information for PROXY protocol
47
+ */
48
+ export interface IProxyConnectionInfo {
49
+ sourceIp?: string;
50
+ sourcePort?: number;
51
+ destIp?: string;
52
+ destPort?: number;
53
+ }
@@ -1,4 +1,4 @@
1
- import * as plugins from '../../plugins.js';
1
+ import * as plugins from '../../../plugins.js';
2
2
  import { TlsAlertLevel, TlsAlertDescription, TlsVersion } from '../utils/tls-utils.js';
3
3
 
4
4
  /**
@@ -0,0 +1,37 @@
1
+ /**
2
+ * TLS Protocol Module
3
+ * Contains generic TLS protocol knowledge including parsers, constants, and utilities
4
+ */
5
+
6
+ // Export all sub-modules
7
+ export * from './alerts/index.js';
8
+ export * from './sni/index.js';
9
+ export * from './utils/index.js';
10
+
11
+ // Re-export main utilities and types for convenience
12
+ export {
13
+ TlsUtils,
14
+ TlsRecordType,
15
+ TlsHandshakeType,
16
+ TlsExtensionType,
17
+ TlsAlertLevel,
18
+ TlsAlertDescription,
19
+ TlsVersion
20
+ } from './utils/tls-utils.js';
21
+ export { TlsAlert } from './alerts/tls-alert.js';
22
+ export { ClientHelloParser } from './sni/client-hello-parser.js';
23
+ export { SniExtraction } from './sni/sni-extraction.js';
24
+
25
+ // Export tlsVersionToString helper
26
+ export function tlsVersionToString(major: number, minor: number): string | null {
27
+ if (major === 0x03) {
28
+ switch (minor) {
29
+ case 0x00: return 'SSLv3';
30
+ case 0x01: return 'TLSv1.0';
31
+ case 0x02: return 'TLSv1.1';
32
+ case 0x03: return 'TLSv1.2';
33
+ case 0x04: return 'TLSv1.3';
34
+ }
35
+ }
36
+ return null;
37
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * TLS SNI (Server Name Indication) protocol utilities
3
+ */
4
+
5
+ export * from './client-hello-parser.js';
6
+ export * from './sni-extraction.js';
@@ -1,4 +1,4 @@
1
- import * as plugins from '../../plugins.js';
1
+ import * as plugins from '../../../plugins.js';
2
2
 
3
3
  /**
4
4
  * TLS record types as defined in various RFCs
@@ -0,0 +1,60 @@
1
+ /**
2
+ * WebSocket Protocol Constants
3
+ * Based on RFC 6455
4
+ */
5
+
6
+ /**
7
+ * WebSocket opcode types
8
+ */
9
+ export enum WebSocketOpcode {
10
+ CONTINUATION = 0x0,
11
+ TEXT = 0x1,
12
+ BINARY = 0x2,
13
+ CLOSE = 0x8,
14
+ PING = 0x9,
15
+ PONG = 0xa,
16
+ }
17
+
18
+ /**
19
+ * WebSocket close codes
20
+ */
21
+ export enum WebSocketCloseCode {
22
+ NORMAL_CLOSURE = 1000,
23
+ GOING_AWAY = 1001,
24
+ PROTOCOL_ERROR = 1002,
25
+ UNSUPPORTED_DATA = 1003,
26
+ NO_STATUS_RECEIVED = 1005,
27
+ ABNORMAL_CLOSURE = 1006,
28
+ INVALID_FRAME_PAYLOAD_DATA = 1007,
29
+ POLICY_VIOLATION = 1008,
30
+ MESSAGE_TOO_BIG = 1009,
31
+ MISSING_EXTENSION = 1010,
32
+ INTERNAL_ERROR = 1011,
33
+ SERVICE_RESTART = 1012,
34
+ TRY_AGAIN_LATER = 1013,
35
+ BAD_GATEWAY = 1014,
36
+ TLS_HANDSHAKE = 1015,
37
+ }
38
+
39
+ /**
40
+ * WebSocket protocol version
41
+ */
42
+ export const WEBSOCKET_VERSION = 13;
43
+
44
+ /**
45
+ * WebSocket magic string for handshake
46
+ */
47
+ export const WEBSOCKET_MAGIC_STRING = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
48
+
49
+ /**
50
+ * WebSocket headers
51
+ */
52
+ export const WEBSOCKET_HEADERS = {
53
+ UPGRADE: 'upgrade',
54
+ CONNECTION: 'connection',
55
+ SEC_WEBSOCKET_KEY: 'sec-websocket-key',
56
+ SEC_WEBSOCKET_VERSION: 'sec-websocket-version',
57
+ SEC_WEBSOCKET_ACCEPT: 'sec-websocket-accept',
58
+ SEC_WEBSOCKET_PROTOCOL: 'sec-websocket-protocol',
59
+ SEC_WEBSOCKET_EXTENSIONS: 'sec-websocket-extensions',
60
+ } as const;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * WebSocket Protocol Module
3
+ * WebSocket protocol utilities and constants
4
+ */
5
+
6
+ export * from './constants.js';
7
+ export * from './types.js';
8
+ export * from './utils.js';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * WebSocket Protocol Type Definitions
3
+ */
4
+
5
+ import type { WebSocketOpcode, WebSocketCloseCode } from './constants.js';
6
+
7
+ /**
8
+ * WebSocket frame header
9
+ */
10
+ export interface IWebSocketFrameHeader {
11
+ fin: boolean;
12
+ rsv1: boolean;
13
+ rsv2: boolean;
14
+ rsv3: boolean;
15
+ opcode: WebSocketOpcode;
16
+ masked: boolean;
17
+ payloadLength: number;
18
+ maskingKey?: Buffer;
19
+ }
20
+
21
+ /**
22
+ * WebSocket frame
23
+ */
24
+ export interface IWebSocketFrame {
25
+ header: IWebSocketFrameHeader;
26
+ payload: Buffer;
27
+ }
28
+
29
+ /**
30
+ * WebSocket close frame payload
31
+ */
32
+ export interface IWebSocketClosePayload {
33
+ code: WebSocketCloseCode;
34
+ reason?: string;
35
+ }
36
+
37
+ /**
38
+ * WebSocket handshake request headers
39
+ */
40
+ export interface IWebSocketHandshakeHeaders {
41
+ upgrade: string;
42
+ connection: string;
43
+ 'sec-websocket-key': string;
44
+ 'sec-websocket-version': string;
45
+ 'sec-websocket-protocol'?: string;
46
+ 'sec-websocket-extensions'?: string;
47
+ [key: string]: string | undefined;
48
+ }
49
+
50
+ /**
51
+ * Type for WebSocket raw data (matching ws library)
52
+ */
53
+ export type RawData = Buffer | ArrayBuffer | Buffer[] | any;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * WebSocket Protocol Utilities
3
+ */
4
+
5
+ import * as crypto from 'crypto';
6
+ import { WEBSOCKET_MAGIC_STRING } from './constants.js';
7
+ import type { RawData } from './types.js';
8
+
9
+ /**
10
+ * Get the length of a WebSocket message regardless of its type
11
+ * (handles all possible WebSocket message data types)
12
+ */
13
+ export function getMessageSize(data: RawData): number {
14
+ if (typeof data === 'string') {
15
+ // For string data, get the byte length
16
+ return Buffer.from(data, 'utf8').length;
17
+ } else if (data instanceof Buffer) {
18
+ // For Node.js Buffer
19
+ return data.length;
20
+ } else if (data instanceof ArrayBuffer) {
21
+ // For ArrayBuffer
22
+ return data.byteLength;
23
+ } else if (Array.isArray(data)) {
24
+ // For array of buffers, sum their lengths
25
+ return data.reduce((sum, chunk) => {
26
+ if (chunk instanceof Buffer) {
27
+ return sum + chunk.length;
28
+ } else if (chunk instanceof ArrayBuffer) {
29
+ return sum + chunk.byteLength;
30
+ }
31
+ return sum;
32
+ }, 0);
33
+ } else {
34
+ // For other types, try to determine the size or return 0
35
+ try {
36
+ return Buffer.from(data).length;
37
+ } catch (e) {
38
+ return 0;
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Convert any raw WebSocket data to Buffer for consistent handling
45
+ */
46
+ export function toBuffer(data: RawData): Buffer {
47
+ if (typeof data === 'string') {
48
+ return Buffer.from(data, 'utf8');
49
+ } else if (data instanceof Buffer) {
50
+ return data;
51
+ } else if (data instanceof ArrayBuffer) {
52
+ return Buffer.from(data);
53
+ } else if (Array.isArray(data)) {
54
+ // For array of buffers, concatenate them
55
+ return Buffer.concat(data.map(chunk => {
56
+ if (chunk instanceof Buffer) {
57
+ return chunk;
58
+ } else if (chunk instanceof ArrayBuffer) {
59
+ return Buffer.from(chunk);
60
+ }
61
+ return Buffer.from(chunk);
62
+ }));
63
+ } else {
64
+ // For other types, try to convert to Buffer or return empty Buffer
65
+ try {
66
+ return Buffer.from(data);
67
+ } catch (e) {
68
+ return Buffer.alloc(0);
69
+ }
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Generate WebSocket accept key from client key
75
+ */
76
+ export function generateAcceptKey(clientKey: string): string {
77
+ const hash = crypto.createHash('sha1');
78
+ hash.update(clientKey + WEBSOCKET_MAGIC_STRING);
79
+ return hash.digest('base64');
80
+ }
81
+
82
+ /**
83
+ * Validate WebSocket upgrade request
84
+ */
85
+ export function isWebSocketUpgrade(headers: Record<string, string>): boolean {
86
+ const upgrade = headers['upgrade'];
87
+ const connection = headers['connection'];
88
+
89
+ return upgrade?.toLowerCase() === 'websocket' &&
90
+ connection?.toLowerCase().includes('upgrade');
91
+ }
92
+
93
+ /**
94
+ * Generate random WebSocket key for client handshake
95
+ */
96
+ export function generateWebSocketKey(): string {
97
+ return crypto.randomBytes(16).toString('base64');
98
+ }