@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.
- package/changelog.md +18 -0
- package/dist_ts/core/utils/proxy-protocol.d.ts +5 -17
- package/dist_ts/core/utils/proxy-protocol.js +13 -97
- package/dist_ts/core/utils/websocket-utils.d.ts +6 -7
- package/dist_ts/core/utils/websocket-utils.js +10 -66
- package/dist_ts/detection/detectors/http-detector-v2.d.ts +33 -0
- package/dist_ts/detection/detectors/http-detector-v2.js +87 -0
- package/dist_ts/detection/detectors/http-detector.d.ts +33 -0
- package/dist_ts/detection/detectors/http-detector.js +89 -0
- package/dist_ts/detection/detectors/quick-detector.d.ts +28 -0
- package/dist_ts/detection/detectors/quick-detector.js +131 -0
- package/dist_ts/detection/detectors/routing-extractor.d.ts +28 -0
- package/dist_ts/detection/detectors/routing-extractor.js +122 -0
- package/dist_ts/detection/detectors/tls-detector-v2.d.ts +33 -0
- package/dist_ts/detection/detectors/tls-detector-v2.js +80 -0
- package/dist_ts/detection/detectors/tls-detector.d.ts +55 -0
- package/dist_ts/detection/detectors/tls-detector.js +206 -0
- package/dist_ts/detection/index.d.ts +17 -0
- package/dist_ts/detection/index.js +22 -0
- package/dist_ts/detection/models/detection-types.d.ts +87 -0
- package/dist_ts/detection/models/detection-types.js +5 -0
- package/dist_ts/detection/models/interfaces.d.ts +97 -0
- package/dist_ts/detection/models/interfaces.js +5 -0
- package/dist_ts/detection/protocol-detector-v2.d.ts +46 -0
- package/dist_ts/detection/protocol-detector-v2.js +116 -0
- package/dist_ts/detection/protocol-detector.d.ts +74 -0
- package/dist_ts/detection/protocol-detector.js +173 -0
- package/dist_ts/detection/utils/buffer-utils.d.ts +61 -0
- package/dist_ts/detection/utils/buffer-utils.js +127 -0
- package/dist_ts/detection/utils/fragment-manager.d.ts +31 -0
- package/dist_ts/detection/utils/fragment-manager.js +53 -0
- package/dist_ts/detection/utils/parser-utils.d.ts +42 -0
- package/dist_ts/detection/utils/parser-utils.js +63 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/protocols/common/fragment-handler.d.ts +73 -0
- package/dist_ts/protocols/common/fragment-handler.js +117 -0
- package/dist_ts/protocols/common/index.d.ts +7 -0
- package/dist_ts/protocols/common/index.js +8 -0
- package/dist_ts/protocols/common/types.d.ts +68 -0
- package/dist_ts/protocols/common/types.js +7 -0
- package/dist_ts/protocols/http/constants.d.ts +119 -0
- package/dist_ts/protocols/http/constants.js +200 -0
- package/dist_ts/protocols/http/index.d.ts +7 -0
- package/dist_ts/protocols/http/index.js +8 -0
- package/dist_ts/protocols/http/parser.d.ts +58 -0
- package/dist_ts/protocols/http/parser.js +184 -0
- package/dist_ts/protocols/http/types.d.ts +62 -0
- package/dist_ts/protocols/http/types.js +5 -0
- package/dist_ts/protocols/index.d.ts +11 -0
- package/dist_ts/protocols/index.js +12 -0
- package/dist_ts/protocols/proxy/index.d.ts +6 -0
- package/dist_ts/protocols/proxy/index.js +7 -0
- package/dist_ts/protocols/proxy/parser.d.ts +44 -0
- package/dist_ts/protocols/proxy/parser.js +153 -0
- package/dist_ts/protocols/proxy/types.d.ts +47 -0
- package/dist_ts/protocols/proxy/types.js +6 -0
- package/dist_ts/protocols/tls/alerts/index.d.ts +4 -0
- package/dist_ts/protocols/tls/alerts/index.js +5 -0
- package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +150 -0
- package/dist_ts/protocols/tls/alerts/tls-alert.js +226 -0
- package/dist_ts/protocols/tls/constants.d.ts +122 -0
- package/dist_ts/protocols/tls/constants.js +135 -0
- package/dist_ts/protocols/tls/index.d.ts +12 -0
- package/dist_ts/protocols/tls/index.js +27 -0
- package/dist_ts/protocols/tls/parser.d.ts +53 -0
- package/dist_ts/protocols/tls/parser.js +294 -0
- package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +100 -0
- package/dist_ts/protocols/tls/sni/client-hello-parser.js +463 -0
- package/dist_ts/protocols/tls/sni/index.d.ts +5 -0
- package/dist_ts/protocols/tls/sni/index.js +6 -0
- package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +58 -0
- package/dist_ts/protocols/tls/sni/sni-extraction.js +275 -0
- package/dist_ts/protocols/tls/types.d.ts +65 -0
- package/dist_ts/protocols/tls/types.js +5 -0
- package/dist_ts/protocols/tls/utils/index.d.ts +4 -0
- package/dist_ts/protocols/tls/utils/index.js +5 -0
- package/dist_ts/protocols/tls/utils/tls-utils.d.ts +158 -0
- package/dist_ts/protocols/tls/utils/tls-utils.js +187 -0
- package/dist_ts/protocols/websocket/constants.d.ts +55 -0
- package/dist_ts/protocols/websocket/constants.js +58 -0
- package/dist_ts/protocols/websocket/index.d.ts +7 -0
- package/dist_ts/protocols/websocket/index.js +8 -0
- package/dist_ts/protocols/websocket/types.d.ts +47 -0
- package/dist_ts/protocols/websocket/types.js +5 -0
- package/dist_ts/protocols/websocket/utils.d.ts +25 -0
- package/dist_ts/protocols/websocket/utils.js +103 -0
- package/dist_ts/proxies/http-proxy/models/http-types.d.ts +25 -27
- package/dist_ts/proxies/http-proxy/models/http-types.js +24 -44
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +81 -61
- package/dist_ts/proxies/smart-proxy/tls-manager.js +2 -1
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +2 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +61 -52
- package/dist_ts/tls/index.d.ts +5 -7
- package/dist_ts/tls/index.js +8 -11
- package/dist_ts/tls/sni/client-hello-parser.js +3 -2
- package/dist_ts/tls/sni/sni-handler.js +4 -4
- package/dist_ts/tls/utils/tls-utils.d.ts +1 -110
- package/dist_ts/tls/utils/tls-utils.js +4 -116
- package/package.json +1 -1
- package/readme.plan.md +0 -0
- package/ts/core/utils/proxy-protocol.ts +14 -131
- package/ts/core/utils/websocket-utils.ts +12 -60
- package/ts/detection/detectors/http-detector.ts +114 -0
- package/ts/detection/detectors/quick-detector.ts +148 -0
- package/ts/detection/detectors/routing-extractor.ts +147 -0
- package/ts/detection/detectors/tls-detector.ts +252 -0
- package/ts/detection/index.ts +25 -0
- package/ts/detection/models/detection-types.ts +102 -0
- package/ts/detection/models/interfaces.ts +115 -0
- package/ts/detection/protocol-detector.ts +230 -0
- package/ts/detection/utils/buffer-utils.ts +141 -0
- package/ts/detection/utils/fragment-manager.ts +64 -0
- package/ts/detection/utils/parser-utils.ts +77 -0
- package/ts/index.ts +3 -1
- package/ts/protocols/common/fragment-handler.ts +163 -0
- package/ts/protocols/common/index.ts +8 -0
- package/ts/protocols/common/types.ts +76 -0
- package/ts/protocols/http/constants.ts +219 -0
- package/ts/protocols/http/index.ts +8 -0
- package/ts/protocols/http/parser.ts +219 -0
- package/ts/protocols/http/types.ts +70 -0
- package/ts/protocols/index.ts +12 -0
- package/ts/protocols/proxy/index.ts +7 -0
- package/ts/protocols/proxy/parser.ts +183 -0
- package/ts/protocols/proxy/types.ts +53 -0
- package/ts/{tls → protocols/tls}/alerts/tls-alert.ts +1 -1
- package/ts/protocols/tls/index.ts +37 -0
- package/ts/protocols/tls/sni/index.ts +6 -0
- package/ts/{tls → protocols/tls}/utils/tls-utils.ts +1 -1
- package/ts/protocols/websocket/constants.ts +60 -0
- package/ts/protocols/websocket/index.ts +8 -0
- package/ts/protocols/websocket/types.ts +53 -0
- package/ts/protocols/websocket/utils.ts +98 -0
- package/ts/proxies/http-proxy/models/http-types.ts +29 -46
- package/ts/proxies/smart-proxy/models/interfaces.ts +7 -0
- package/ts/proxies/smart-proxy/route-connection-handler.ts +91 -68
- package/ts/proxies/smart-proxy/tls-manager.ts +1 -0
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +72 -56
- package/ts/tls/index.ts +8 -12
- package/ts/tls/sni/sni-handler.ts +3 -3
- /package/ts/{tls → protocols/tls}/alerts/index.ts +0 -0
- /package/ts/{tls → protocols/tls}/sni/client-hello-parser.ts +0 -0
- /package/ts/{tls → protocols/tls}/sni/sni-extraction.ts +0 -0
- /package/ts/{tls → protocols/tls}/utils/index.ts +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Protocol Parser
|
|
3
|
+
* Generic HTTP parsing utilities
|
|
4
|
+
*/
|
|
5
|
+
import { type THttpMethod } from './constants.js';
|
|
6
|
+
import type { IHttpRequestLine, IHttpHeader } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* HTTP parser utilities
|
|
9
|
+
*/
|
|
10
|
+
export declare class HttpParser {
|
|
11
|
+
/**
|
|
12
|
+
* Check if string is a valid HTTP method
|
|
13
|
+
*/
|
|
14
|
+
static isHttpMethod(str: string): str is THttpMethod;
|
|
15
|
+
/**
|
|
16
|
+
* Parse HTTP request line
|
|
17
|
+
*/
|
|
18
|
+
static parseRequestLine(line: string): IHttpRequestLine | null;
|
|
19
|
+
/**
|
|
20
|
+
* Parse HTTP header line
|
|
21
|
+
*/
|
|
22
|
+
static parseHeaderLine(line: string): IHttpHeader | null;
|
|
23
|
+
/**
|
|
24
|
+
* Parse HTTP headers from lines
|
|
25
|
+
*/
|
|
26
|
+
static parseHeaders(lines: string[]): Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Extract domain from Host header value
|
|
29
|
+
*/
|
|
30
|
+
static extractDomainFromHost(hostHeader: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Validate domain name
|
|
33
|
+
*/
|
|
34
|
+
static isValidDomain(domain: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Extract line from buffer
|
|
37
|
+
*/
|
|
38
|
+
static extractLine(buffer: Buffer, offset?: number): {
|
|
39
|
+
line: string;
|
|
40
|
+
nextOffset: number;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* Check if buffer contains printable ASCII
|
|
44
|
+
*/
|
|
45
|
+
static isPrintableAscii(buffer: Buffer, length?: number): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Quick check if buffer starts with HTTP method
|
|
48
|
+
*/
|
|
49
|
+
static quickCheck(buffer: Buffer): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Parse query string
|
|
52
|
+
*/
|
|
53
|
+
static parseQueryString(queryString: string): Record<string, string>;
|
|
54
|
+
/**
|
|
55
|
+
* Build query string from params
|
|
56
|
+
*/
|
|
57
|
+
static buildQueryString(params: Record<string, string>): string;
|
|
58
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Protocol Parser
|
|
3
|
+
* Generic HTTP parsing utilities
|
|
4
|
+
*/
|
|
5
|
+
import { HTTP_METHODS } from './constants.js';
|
|
6
|
+
/**
|
|
7
|
+
* HTTP parser utilities
|
|
8
|
+
*/
|
|
9
|
+
export class HttpParser {
|
|
10
|
+
/**
|
|
11
|
+
* Check if string is a valid HTTP method
|
|
12
|
+
*/
|
|
13
|
+
static isHttpMethod(str) {
|
|
14
|
+
return HTTP_METHODS.includes(str);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse HTTP request line
|
|
18
|
+
*/
|
|
19
|
+
static parseRequestLine(line) {
|
|
20
|
+
const parts = line.trim().split(' ');
|
|
21
|
+
if (parts.length !== 3) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const [method, path, version] = parts;
|
|
25
|
+
// Validate method
|
|
26
|
+
if (!this.isHttpMethod(method)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// Validate version
|
|
30
|
+
if (!version.startsWith('HTTP/')) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
method: method,
|
|
35
|
+
path,
|
|
36
|
+
version: version
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse HTTP header line
|
|
41
|
+
*/
|
|
42
|
+
static parseHeaderLine(line) {
|
|
43
|
+
const colonIndex = line.indexOf(':');
|
|
44
|
+
if (colonIndex === -1) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const name = line.slice(0, colonIndex).trim();
|
|
48
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
49
|
+
if (!name) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return { name, value };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse HTTP headers from lines
|
|
56
|
+
*/
|
|
57
|
+
static parseHeaders(lines) {
|
|
58
|
+
const headers = {};
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
const header = this.parseHeaderLine(line);
|
|
61
|
+
if (header) {
|
|
62
|
+
// Convert header names to lowercase for consistency
|
|
63
|
+
headers[header.name.toLowerCase()] = header.value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return headers;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Extract domain from Host header value
|
|
70
|
+
*/
|
|
71
|
+
static extractDomainFromHost(hostHeader) {
|
|
72
|
+
// Remove port if present
|
|
73
|
+
const colonIndex = hostHeader.lastIndexOf(':');
|
|
74
|
+
if (colonIndex !== -1) {
|
|
75
|
+
// Check if it's not part of IPv6 address
|
|
76
|
+
const beforeColon = hostHeader.slice(0, colonIndex);
|
|
77
|
+
if (!beforeColon.includes(']')) {
|
|
78
|
+
return beforeColon;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return hostHeader;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate domain name
|
|
85
|
+
*/
|
|
86
|
+
static isValidDomain(domain) {
|
|
87
|
+
// Basic domain validation
|
|
88
|
+
if (!domain || domain.length > 253) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
// Check for valid characters and structure
|
|
92
|
+
const domainRegex = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z0-9-]{1,63})*$/;
|
|
93
|
+
return domainRegex.test(domain);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extract line from buffer
|
|
97
|
+
*/
|
|
98
|
+
static extractLine(buffer, offset = 0) {
|
|
99
|
+
// Look for CRLF
|
|
100
|
+
const crlfIndex = buffer.indexOf('\r\n', offset);
|
|
101
|
+
if (crlfIndex === -1) {
|
|
102
|
+
// Look for just LF
|
|
103
|
+
const lfIndex = buffer.indexOf('\n', offset);
|
|
104
|
+
if (lfIndex === -1) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
line: buffer.slice(offset, lfIndex).toString('utf8'),
|
|
109
|
+
nextOffset: lfIndex + 1
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
line: buffer.slice(offset, crlfIndex).toString('utf8'),
|
|
114
|
+
nextOffset: crlfIndex + 2
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Check if buffer contains printable ASCII
|
|
119
|
+
*/
|
|
120
|
+
static isPrintableAscii(buffer, length) {
|
|
121
|
+
const checkLength = Math.min(length || buffer.length, buffer.length);
|
|
122
|
+
for (let i = 0; i < checkLength; i++) {
|
|
123
|
+
const byte = buffer[i];
|
|
124
|
+
// Allow printable ASCII (32-126) plus tab (9), LF (10), and CR (13)
|
|
125
|
+
if (byte < 32 || byte > 126) {
|
|
126
|
+
if (byte !== 9 && byte !== 10 && byte !== 13) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Quick check if buffer starts with HTTP method
|
|
135
|
+
*/
|
|
136
|
+
static quickCheck(buffer) {
|
|
137
|
+
if (buffer.length < 3) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
// Check common HTTP methods
|
|
141
|
+
const start = buffer.slice(0, 7).toString('ascii');
|
|
142
|
+
return start.startsWith('GET ') ||
|
|
143
|
+
start.startsWith('POST ') ||
|
|
144
|
+
start.startsWith('PUT ') ||
|
|
145
|
+
start.startsWith('DELETE ') ||
|
|
146
|
+
start.startsWith('HEAD ') ||
|
|
147
|
+
start.startsWith('OPTIONS') ||
|
|
148
|
+
start.startsWith('PATCH ') ||
|
|
149
|
+
start.startsWith('CONNECT') ||
|
|
150
|
+
start.startsWith('TRACE ');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Parse query string
|
|
154
|
+
*/
|
|
155
|
+
static parseQueryString(queryString) {
|
|
156
|
+
const params = {};
|
|
157
|
+
if (!queryString) {
|
|
158
|
+
return params;
|
|
159
|
+
}
|
|
160
|
+
// Remove leading '?' if present
|
|
161
|
+
if (queryString.startsWith('?')) {
|
|
162
|
+
queryString = queryString.slice(1);
|
|
163
|
+
}
|
|
164
|
+
const pairs = queryString.split('&');
|
|
165
|
+
for (const pair of pairs) {
|
|
166
|
+
const [key, value] = pair.split('=');
|
|
167
|
+
if (key) {
|
|
168
|
+
params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return params;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Build query string from params
|
|
175
|
+
*/
|
|
176
|
+
static buildQueryString(params) {
|
|
177
|
+
const pairs = [];
|
|
178
|
+
for (const [key, value] of Object.entries(params)) {
|
|
179
|
+
pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
180
|
+
}
|
|
181
|
+
return pairs.length > 0 ? '?' + pairs.join('&') : '';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJvdG9jb2xzL2h0dHAvcGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxZQUFZLEVBQXVDLE1BQU0sZ0JBQWdCLENBQUM7QUFHbkY7O0dBRUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUNyQjs7T0FFRztJQUNILE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBVztRQUM3QixPQUFPLFlBQVksQ0FBQyxRQUFRLENBQUMsR0FBa0IsQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFZO1FBQ2xDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFckMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE1BQU0sQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQztRQUV0QyxrQkFBa0I7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMvQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxtQkFBbUI7UUFDbkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNqQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxPQUFPO1lBQ0wsTUFBTSxFQUFFLE1BQXFCO1lBQzdCLElBQUk7WUFDSixPQUFPLEVBQUUsT0FBdUI7U0FDakMsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxlQUFlLENBQUMsSUFBWTtRQUNqQyxNQUFNLFVBQVUs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
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Protocol Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
import type { THttpMethod, THttpVersion, HttpStatus } from './constants.js';
|
|
5
|
+
/**
|
|
6
|
+
* HTTP request line structure
|
|
7
|
+
*/
|
|
8
|
+
export interface IHttpRequestLine {
|
|
9
|
+
method: THttpMethod;
|
|
10
|
+
path: string;
|
|
11
|
+
version: THttpVersion;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* HTTP response line structure
|
|
15
|
+
*/
|
|
16
|
+
export interface IHttpResponseLine {
|
|
17
|
+
version: THttpVersion;
|
|
18
|
+
status: HttpStatus;
|
|
19
|
+
statusText: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* HTTP header structure
|
|
23
|
+
*/
|
|
24
|
+
export interface IHttpHeader {
|
|
25
|
+
name: string;
|
|
26
|
+
value: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* HTTP message structure (base for request and response)
|
|
30
|
+
*/
|
|
31
|
+
export interface IHttpMessage {
|
|
32
|
+
headers: Record<string, string>;
|
|
33
|
+
body?: Buffer;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* HTTP request structure
|
|
37
|
+
*/
|
|
38
|
+
export interface IHttpRequest extends IHttpMessage {
|
|
39
|
+
method: THttpMethod;
|
|
40
|
+
path: string;
|
|
41
|
+
version: THttpVersion;
|
|
42
|
+
query?: Record<string, string>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* HTTP response structure
|
|
46
|
+
*/
|
|
47
|
+
export interface IHttpResponse extends IHttpMessage {
|
|
48
|
+
status: HttpStatus;
|
|
49
|
+
statusText: string;
|
|
50
|
+
version: THttpVersion;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parsed URL structure
|
|
54
|
+
*/
|
|
55
|
+
export interface IParsedUrl {
|
|
56
|
+
protocol?: string;
|
|
57
|
+
hostname?: string;
|
|
58
|
+
port?: number;
|
|
59
|
+
path?: string;
|
|
60
|
+
query?: string;
|
|
61
|
+
fragment?: string;
|
|
62
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Protocol Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm90b2NvbHMvaHR0cC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRyJ9
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol-specific modules for smartproxy
|
|
3
|
+
*
|
|
4
|
+
* This directory contains generic protocol knowledge separated from
|
|
5
|
+
* smartproxy-specific implementation details.
|
|
6
|
+
*/
|
|
7
|
+
export * as common from './common/index.js';
|
|
8
|
+
export * as tls from './tls/index.js';
|
|
9
|
+
export * as http from './http/index.js';
|
|
10
|
+
export * as proxy from './proxy/index.js';
|
|
11
|
+
export * as websocket from './websocket/index.js';
|
|
@@ -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
|
+
export * as common from './common/index.js';
|
|
8
|
+
export * as tls from './tls/index.js';
|
|
9
|
+
export * as http from './http/index.js';
|
|
10
|
+
export * as proxy from './proxy/index.js';
|
|
11
|
+
export * as websocket from './websocket/index.js';
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9wcm90b2NvbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEtBQUssTUFBTSxNQUFNLG1CQUFtQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxHQUFHLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEtBQUssS0FBSyxNQUFNLGtCQUFrQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sc0JBQXNCLENBQUMifQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PROXY Protocol Module
|
|
3
|
+
* HAProxy PROXY protocol implementation
|
|
4
|
+
*/
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
export * from './parser.js';
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm90b2NvbHMvcHJveHkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxhQUFhLENBQUMifQ==
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
import type { IProxyInfo, IProxyParseResult, TProxyProtocol } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* PROXY protocol parser
|
|
9
|
+
*/
|
|
10
|
+
export declare class ProxyProtocolParser {
|
|
11
|
+
static readonly PROXY_V1_SIGNATURE = "PROXY ";
|
|
12
|
+
static readonly MAX_HEADER_LENGTH = 107;
|
|
13
|
+
static readonly HEADER_TERMINATOR = "\r\n";
|
|
14
|
+
/**
|
|
15
|
+
* Parse PROXY protocol v1 header from buffer
|
|
16
|
+
* Returns proxy info and remaining data after header
|
|
17
|
+
*/
|
|
18
|
+
static parse(data: Buffer): IProxyParseResult;
|
|
19
|
+
/**
|
|
20
|
+
* Generate PROXY protocol v1 header
|
|
21
|
+
*/
|
|
22
|
+
static generate(info: IProxyInfo): Buffer;
|
|
23
|
+
/**
|
|
24
|
+
* Validate IP address format
|
|
25
|
+
*/
|
|
26
|
+
static isValidIP(ip: string, protocol: TProxyProtocol): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Check if string is valid IPv4
|
|
29
|
+
*/
|
|
30
|
+
static isIPv4(ip: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if string is valid IPv6
|
|
33
|
+
*/
|
|
34
|
+
static isIPv6(ip: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Create a connection ID string for tracking
|
|
37
|
+
*/
|
|
38
|
+
static createConnectionId(connectionInfo: {
|
|
39
|
+
sourceIp?: string;
|
|
40
|
+
sourcePort?: number;
|
|
41
|
+
destIp?: string;
|
|
42
|
+
destPort?: number;
|
|
43
|
+
}): string;
|
|
44
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
* PROXY protocol parser
|
|
8
|
+
*/
|
|
9
|
+
export class ProxyProtocolParser {
|
|
10
|
+
static { this.PROXY_V1_SIGNATURE = 'PROXY '; }
|
|
11
|
+
static { this.MAX_HEADER_LENGTH = 107; } // Max length for v1 header
|
|
12
|
+
static { this.HEADER_TERMINATOR = '\r\n'; }
|
|
13
|
+
/**
|
|
14
|
+
* Parse PROXY protocol v1 header from buffer
|
|
15
|
+
* Returns proxy info and remaining data after header
|
|
16
|
+
*/
|
|
17
|
+
static parse(data) {
|
|
18
|
+
// Check if buffer starts with PROXY signature
|
|
19
|
+
if (!data.toString('ascii', 0, 6).startsWith(this.PROXY_V1_SIGNATURE)) {
|
|
20
|
+
return {
|
|
21
|
+
proxyInfo: null,
|
|
22
|
+
remainingData: data
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Find header terminator
|
|
26
|
+
const headerEndIndex = data.indexOf(this.HEADER_TERMINATOR);
|
|
27
|
+
if (headerEndIndex === -1) {
|
|
28
|
+
// Header incomplete, need more data
|
|
29
|
+
if (data.length > this.MAX_HEADER_LENGTH) {
|
|
30
|
+
// Header too long, invalid
|
|
31
|
+
throw new Error('PROXY protocol header exceeds maximum length');
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
proxyInfo: null,
|
|
35
|
+
remainingData: data
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Extract header line
|
|
39
|
+
const headerLine = data.toString('ascii', 0, headerEndIndex);
|
|
40
|
+
const remainingData = data.slice(headerEndIndex + 2); // Skip \r\n
|
|
41
|
+
// Parse header
|
|
42
|
+
const parts = headerLine.split(' ');
|
|
43
|
+
if (parts.length < 2) {
|
|
44
|
+
throw new Error(`Invalid PROXY protocol header format: ${headerLine}`);
|
|
45
|
+
}
|
|
46
|
+
const [signature, protocol] = parts;
|
|
47
|
+
// Validate protocol
|
|
48
|
+
if (!['TCP4', 'TCP6', 'UNKNOWN'].includes(protocol)) {
|
|
49
|
+
throw new Error(`Invalid PROXY protocol: ${protocol}`);
|
|
50
|
+
}
|
|
51
|
+
// For UNKNOWN protocol, ignore addresses
|
|
52
|
+
if (protocol === 'UNKNOWN') {
|
|
53
|
+
return {
|
|
54
|
+
proxyInfo: {
|
|
55
|
+
protocol: 'UNKNOWN',
|
|
56
|
+
sourceIP: '',
|
|
57
|
+
sourcePort: 0,
|
|
58
|
+
destinationIP: '',
|
|
59
|
+
destinationPort: 0
|
|
60
|
+
},
|
|
61
|
+
remainingData
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// For TCP4/TCP6, we need all 6 parts
|
|
65
|
+
if (parts.length !== 6) {
|
|
66
|
+
throw new Error(`Invalid PROXY protocol header format: ${headerLine}`);
|
|
67
|
+
}
|
|
68
|
+
const [, , srcIP, dstIP, srcPort, dstPort] = parts;
|
|
69
|
+
// Validate and parse ports
|
|
70
|
+
const sourcePort = parseInt(srcPort, 10);
|
|
71
|
+
const destinationPort = parseInt(dstPort, 10);
|
|
72
|
+
if (isNaN(sourcePort) || sourcePort < 0 || sourcePort > 65535) {
|
|
73
|
+
throw new Error(`Invalid source port: ${srcPort}`);
|
|
74
|
+
}
|
|
75
|
+
if (isNaN(destinationPort) || destinationPort < 0 || destinationPort > 65535) {
|
|
76
|
+
throw new Error(`Invalid destination port: ${dstPort}`);
|
|
77
|
+
}
|
|
78
|
+
// Validate IP addresses
|
|
79
|
+
const protocolType = protocol;
|
|
80
|
+
if (!this.isValidIP(srcIP, protocolType)) {
|
|
81
|
+
throw new Error(`Invalid source IP for ${protocol}: ${srcIP}`);
|
|
82
|
+
}
|
|
83
|
+
if (!this.isValidIP(dstIP, protocolType)) {
|
|
84
|
+
throw new Error(`Invalid destination IP for ${protocol}: ${dstIP}`);
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
proxyInfo: {
|
|
88
|
+
protocol: protocolType,
|
|
89
|
+
sourceIP: srcIP,
|
|
90
|
+
sourcePort,
|
|
91
|
+
destinationIP: dstIP,
|
|
92
|
+
destinationPort
|
|
93
|
+
},
|
|
94
|
+
remainingData
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Generate PROXY protocol v1 header
|
|
99
|
+
*/
|
|
100
|
+
static generate(info) {
|
|
101
|
+
if (info.protocol === 'UNKNOWN') {
|
|
102
|
+
return Buffer.from(`PROXY UNKNOWN\r\n`, 'ascii');
|
|
103
|
+
}
|
|
104
|
+
const header = `PROXY ${info.protocol} ${info.sourceIP} ${info.destinationIP} ${info.sourcePort} ${info.destinationPort}\r\n`;
|
|
105
|
+
if (header.length > this.MAX_HEADER_LENGTH) {
|
|
106
|
+
throw new Error('Generated PROXY protocol header exceeds maximum length');
|
|
107
|
+
}
|
|
108
|
+
return Buffer.from(header, 'ascii');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Validate IP address format
|
|
112
|
+
*/
|
|
113
|
+
static isValidIP(ip, protocol) {
|
|
114
|
+
if (protocol === 'TCP4') {
|
|
115
|
+
return this.isIPv4(ip);
|
|
116
|
+
}
|
|
117
|
+
else if (protocol === 'TCP6') {
|
|
118
|
+
return this.isIPv6(ip);
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if string is valid IPv4
|
|
124
|
+
*/
|
|
125
|
+
static isIPv4(ip) {
|
|
126
|
+
const parts = ip.split('.');
|
|
127
|
+
if (parts.length !== 4)
|
|
128
|
+
return false;
|
|
129
|
+
for (const part of parts) {
|
|
130
|
+
const num = parseInt(part, 10);
|
|
131
|
+
if (isNaN(num) || num < 0 || num > 255 || part !== num.toString()) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Check if string is valid IPv6
|
|
139
|
+
*/
|
|
140
|
+
static isIPv6(ip) {
|
|
141
|
+
// Basic IPv6 validation
|
|
142
|
+
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]))$/;
|
|
143
|
+
return ipv6Regex.test(ip);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Create a connection ID string for tracking
|
|
147
|
+
*/
|
|
148
|
+
static createConnectionId(connectionInfo) {
|
|
149
|
+
const { sourceIp, sourcePort, destIp, destPort } = connectionInfo;
|
|
150
|
+
return `${sourceIp}:${sourcePort}-${destIp}:${destPort}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJvdG9jb2xzL3Byb3h5L3BhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBSUg7O0dBRUc7QUFDSCxNQUFNLE9BQU8sbUJBQW1CO2FBQ2QsdUJBQWtCLEdBQUcsUUFBUSxDQUFDO2FBQzlCLHNCQUFpQixHQUFHLEdBQUcsQ0FBQyxHQUFDLDJCQUEyQjthQUNwRCxzQkFBaUIsR0FBRyxNQUFNLENBQUM7SUFFM0M7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFZO1FBQ3ZCLDhDQUE4QztRQUM5QyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO1lBQ3RFLE9BQU87Z0JBQ0wsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsYUFBYSxFQUFFLElBQUk7YUFDcEIsQ0FBQztRQUNKLENBQUM7UUFFRCx5QkFBeUI7UUFDekIsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUM1RCxJQUFJLGNBQWMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzFCLG9DQUFvQztZQUNwQyxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3pDLDJCQUEyQjtnQkFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1lBQ2xFLENBQUM7WUFDRCxPQUFPO2dCQUNMLFNBQVMsRUFBRSxJQUFJO2dCQUNmLGFBQWEsRUFBRSxJQUFJO2FBQ3BCLENBQUM7UUFDSixDQUFDO1FBRUQsc0JBQXNCO1FBQ3RCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUM3RCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVk7UUFFbEUsZUFBZTtRQUNmLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFcEMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDekUsQ0FBQztRQUVELE1BQU0sQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBRXBDLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3BELE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMzQixPQUFPO2dCQUNMLFNBQVMsRUFBRTtvQkFDVCxRQUFRLEVBQUUsU0FBUztvQkFDbkIsUUFBUSxFQUFFLEVBQUU7b0JBQ1osVUFBVSxFQUFFLENBQUM7b0JBQ2IsYUFBYSxFQUFFLEVBQUU7b0JBQ2pCLGVBQWUsRUFBRSxDQUFDO2lCQUNuQjtnQkFDRCxhQUFhO2FBQ2QsQ0FBQztRQUNKLENBQUM7UUFFRCxxQ0FBcUM7UUFDckMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDekUsQ0FBQztRQUVELE1BQU0sQ0FBQyxFQUFFLEFBQUQsRUFBRyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsR0FBRyxLQUFLLENBQUM7UUFFbkQsMkJBQTJCO1FBQzNCLE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU5QyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxVQUFVLEdBQUcsQ0FBQyxJQUFJLFVBQVUsR0FBRyxLQUFLLEVBQUUsQ0FBQztZQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSSxlQUFlLEdBQUcsQ0FBQyxJQUFJLGVBQWUsR0FBRyxLQUFLLEVBQUUsQ0FBQztZQUM3RSxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzFELENBQUM7UUFFRCx3QkFBd0I7UUFDeEIsTUFBTSxZQUFZLEdBQUcsUUFBMEIsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixRQUFRLEtBQUssS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsUUFBUSxLQUFLLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdEUsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUU7Z0JBQ1QsUUFBUSxFQUFFLFlBQVk7Z0JBQ3RCLFFBQVEsRUFBRSxLQUFLO2dCQUNmLFVBQVU7Z0JBQ1YsYUFBYSxFQUFFLEtBQUs7Z0JBQ3BCLGVBQWU7YUFDaEI7WUFDRCxhQUFhO1NBQ2QsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBZ0I7UUFDOUIsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsU0FBUyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxlQUFlLE1BQU0sQ0FBQztRQUU5SCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDM0MsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQzVFLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBVSxFQUFFLFFBQXdCO1FBQ25ELElBQUksUUFBUSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QixDQUFDO2FBQU0sSUFBSSxRQUFRLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDL0IsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBVTtRQUN0QixNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzVCLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFckMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxJQUFJLEtBQUssR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7Z0JBQ2xFLE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBVTtRQUN0Qix3QkFBd0I7UUFDeEIsTUFBTSxTQUFTLEdBQUcsaXBCQUFpcEIsQ0FBQztRQUNwcUIsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxjQUt6QjtRQUNDLE1BQU0sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxjQUFjLENBQUM7UUFDbEUsT0FBTyxHQUFHLFFBQVEsSUFBSSxVQUFVLElBQUksTUFBTSxJQUFJLFFBQVEsRUFBRSxDQUFDO0lBQzNELENBQUMifQ==
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PROXY Protocol Type Definitions
|
|
3
|
+
* Based on HAProxy PROXY protocol specification
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* PROXY protocol version
|
|
7
|
+
*/
|
|
8
|
+
export type TProxyProtocolVersion = 'v1' | 'v2';
|
|
9
|
+
/**
|
|
10
|
+
* Connection protocol type
|
|
11
|
+
*/
|
|
12
|
+
export type TProxyProtocol = 'TCP4' | 'TCP6' | 'UNKNOWN';
|
|
13
|
+
/**
|
|
14
|
+
* Interface representing parsed PROXY protocol information
|
|
15
|
+
*/
|
|
16
|
+
export interface IProxyInfo {
|
|
17
|
+
protocol: TProxyProtocol;
|
|
18
|
+
sourceIP: string;
|
|
19
|
+
sourcePort: number;
|
|
20
|
+
destinationIP: string;
|
|
21
|
+
destinationPort: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Interface for parse result including remaining data
|
|
25
|
+
*/
|
|
26
|
+
export interface IProxyParseResult {
|
|
27
|
+
proxyInfo: IProxyInfo | null;
|
|
28
|
+
remainingData: Buffer;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* PROXY protocol v2 header format
|
|
32
|
+
*/
|
|
33
|
+
export interface IProxyV2Header {
|
|
34
|
+
signature: Buffer;
|
|
35
|
+
versionCommand: number;
|
|
36
|
+
family: number;
|
|
37
|
+
length: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Connection information for PROXY protocol
|
|
41
|
+
*/
|
|
42
|
+
export interface IProxyConnectionInfo {
|
|
43
|
+
sourceIp?: string;
|
|
44
|
+
sourcePort?: number;
|
|
45
|
+
destIp?: string;
|
|
46
|
+
destPort?: number;
|
|
47
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PROXY Protocol Type Definitions
|
|
3
|
+
* Based on HAProxy PROXY protocol specification
|
|
4
|
+
*/
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm90b2NvbHMvcHJveHkvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHIn0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
/**
|
|
3
|
+
* TLS alerts
|
|
4
|
+
*/
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9wcm90b2NvbHMvdGxzL2FsZXJ0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUcifQ==
|