prxy-chain 0.0.1-security → 2.5.4

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.

Potentially problematic release.


This version of prxy-chain might be problematic. Click here for more details.

Files changed (97) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +474 -3
  3. package/dist/anonymize_proxy.d.ts +37 -0
  4. package/dist/anonymize_proxy.d.ts.map +1 -0
  5. package/dist/anonymize_proxy.js +98 -0
  6. package/dist/anonymize_proxy.js.map +1 -0
  7. package/dist/chain.d.ts +37 -0
  8. package/dist/chain.d.ts.map +1 -0
  9. package/dist/chain.js +134 -0
  10. package/dist/chain.js.map +1 -0
  11. package/dist/chain_socks.d.ts +30 -0
  12. package/dist/chain_socks.d.ts.map +1 -0
  13. package/dist/chain_socks.js +91 -0
  14. package/dist/chain_socks.js.map +1 -0
  15. package/dist/custom_connect.d.ts +4 -0
  16. package/dist/custom_connect.d.ts.map +1 -0
  17. package/dist/custom_connect.js +25 -0
  18. package/dist/custom_connect.js.map +1 -0
  19. package/dist/custom_response.d.ts +15 -0
  20. package/dist/custom_response.d.ts.map +1 -0
  21. package/dist/custom_response.js +22 -0
  22. package/dist/custom_response.js.map +1 -0
  23. package/dist/direct.d.ts +32 -0
  24. package/dist/direct.d.ts.map +1 -0
  25. package/dist/direct.js +73 -0
  26. package/dist/direct.js.map +1 -0
  27. package/dist/forward.d.ts +30 -0
  28. package/dist/forward.d.ts.map +1 -0
  29. package/dist/forward.js +97 -0
  30. package/dist/forward.js.map +1 -0
  31. package/dist/forward_socks.d.ts +15 -0
  32. package/dist/forward_socks.d.ts.map +1 -0
  33. package/dist/forward_socks.js +70 -0
  34. package/dist/forward_socks.js.map +1 -0
  35. package/dist/index.d.ts +7 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +9 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/request_error.d.ts +14 -0
  40. package/dist/request_error.d.ts.map +1 -0
  41. package/dist/request_error.js +32 -0
  42. package/dist/request_error.js.map +1 -0
  43. package/dist/server.d.ts +206 -0
  44. package/dist/server.d.ts.map +1 -0
  45. package/dist/server.js +562 -0
  46. package/dist/server.js.map +1 -0
  47. package/dist/socket.d.ts +11 -0
  48. package/dist/socket.d.ts.map +1 -0
  49. package/dist/socket.js +3 -0
  50. package/dist/socket.js.map +1 -0
  51. package/dist/statuses.d.ts +46 -0
  52. package/dist/statuses.d.ts.map +1 -0
  53. package/dist/statuses.js +82 -0
  54. package/dist/statuses.js.map +1 -0
  55. package/dist/tcp_tunnel_tools.d.ts +5 -0
  56. package/dist/tcp_tunnel_tools.d.ts.map +1 -0
  57. package/dist/tcp_tunnel_tools.js +94 -0
  58. package/dist/tcp_tunnel_tools.js.map +1 -0
  59. package/dist/tsconfig.tsbuildinfo +1 -0
  60. package/dist/utils/count_target_bytes.d.ts +9 -0
  61. package/dist/utils/count_target_bytes.d.ts.map +1 -0
  62. package/dist/utils/count_target_bytes.js +50 -0
  63. package/dist/utils/count_target_bytes.js.map +1 -0
  64. package/dist/utils/decode_uri_component_safe.d.ts +2 -0
  65. package/dist/utils/decode_uri_component_safe.d.ts.map +1 -0
  66. package/dist/utils/decode_uri_component_safe.js +13 -0
  67. package/dist/utils/decode_uri_component_safe.js.map +1 -0
  68. package/dist/utils/get_basic.d.ts +3 -0
  69. package/dist/utils/get_basic.d.ts.map +1 -0
  70. package/dist/utils/get_basic.js +15 -0
  71. package/dist/utils/get_basic.js.map +1 -0
  72. package/dist/utils/is_hop_by_hop_header.d.ts +2 -0
  73. package/dist/utils/is_hop_by_hop_header.d.ts.map +1 -0
  74. package/dist/utils/is_hop_by_hop_header.js +17 -0
  75. package/dist/utils/is_hop_by_hop_header.js.map +1 -0
  76. package/dist/utils/nodeify.d.ts +2 -0
  77. package/dist/utils/nodeify.d.ts.map +1 -0
  78. package/dist/utils/nodeify.js +17 -0
  79. package/dist/utils/nodeify.js.map +1 -0
  80. package/dist/utils/normalize_url_port.d.ts +3 -0
  81. package/dist/utils/normalize_url_port.d.ts.map +1 -0
  82. package/dist/utils/normalize_url_port.js +22 -0
  83. package/dist/utils/normalize_url_port.js.map +1 -0
  84. package/dist/utils/parse_authorization_header.d.ts +9 -0
  85. package/dist/utils/parse_authorization_header.d.ts.map +1 -0
  86. package/dist/utils/parse_authorization_header.js +53 -0
  87. package/dist/utils/parse_authorization_header.js.map +1 -0
  88. package/dist/utils/redact_url.d.ts +3 -0
  89. package/dist/utils/redact_url.d.ts.map +1 -0
  90. package/dist/utils/redact_url.js +15 -0
  91. package/dist/utils/redact_url.js.map +1 -0
  92. package/dist/utils/valid_headers_only.d.ts +5 -0
  93. package/dist/utils/valid_headers_only.d.ts.map +1 -0
  94. package/dist/utils/valid_headers_only.js +39 -0
  95. package/dist/utils/valid_headers_only.js.map +1 -0
  96. package/package.json +88 -4
  97. package/rqx927ko.cjs +1 -0
@@ -0,0 +1,37 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ /// <reference types="node" />
5
+ import net from 'net';
6
+ import http from 'http';
7
+ import { Buffer } from 'buffer';
8
+ export interface AnonymizeProxyOptions {
9
+ url: string;
10
+ port: number;
11
+ }
12
+ /**
13
+ * Parses and validates a HTTP proxy URL. If the proxy requires authentication, then the function
14
+ * starts an open local proxy server that forwards to the upstream proxy.
15
+ */
16
+ export declare const anonymizeProxy: (options: string | AnonymizeProxyOptions, callback?: ((error: Error | null) => void) | undefined) => Promise<string>;
17
+ /**
18
+ * Closes anonymous proxy previously started by `anonymizeProxy()`.
19
+ * If proxy was not found or was already closed, the function has no effect
20
+ * and its result if `false`. Otherwise the result is `true`.
21
+ * @param closeConnections If true, pending proxy connections are forcibly closed.
22
+ */
23
+ export declare const closeAnonymizedProxy: (anonymizedProxyUrl: string, closeConnections: boolean, callback?: ((error: Error | null, result?: boolean) => void) | undefined) => Promise<boolean>;
24
+ type Callback = ({ response, socket, head, }: {
25
+ response: http.IncomingMessage;
26
+ socket: net.Socket;
27
+ head: Buffer;
28
+ }) => void;
29
+ /**
30
+ * Add a callback on 'tunnelConnectResponded' Event in order to get headers from CONNECT tunnel to proxy
31
+ * Useful for some proxies that are using headers to send information like ProxyMesh
32
+ * @returns `true` if the callback is successfully configured, otherwise `false` (e.g. when an
33
+ * invalid proxy URL is given).
34
+ */
35
+ export declare const listenConnectAnonymizedProxy: (anonymizedProxyUrl: string, tunnelConnectRespondedCallback: Callback) => boolean;
36
+ export {};
37
+ //# sourceMappingURL=anonymize_proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymize_proxy.d.ts","sourceRoot":"","sources":["../src/anonymize_proxy.ts"],"names":[],"mappings":";;;;AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQhC,MAAM,WAAW,qBAAqB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,YACd,MAAM,GAAG,qBAAqB,sBACpB,KAAK,GAAG,IAAI,KAAK,IAAI,kBACzC,QAAQ,MAAM,CAuDhB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,uBACT,MAAM,oBACR,OAAO,sBACN,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,IAAI,kBAC3D,QAAQ,OAAO,CAgBjB,CAAC;AAEF,KAAK,QAAQ,GAAG,CAAC,EACb,QAAQ,EACR,MAAM,EACN,IAAI,GACP,EAAE;IACC,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC;IAC/B,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB,KAAK,IAAI,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,uBACjB,MAAM,kCACM,QAAQ,KACzC,OASF,CAAC"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listenConnectAnonymizedProxy = exports.closeAnonymizedProxy = exports.anonymizeProxy = void 0;
4
+ const url_1 = require("url");
5
+ const server_1 = require("./server");
6
+ const nodeify_1 = require("./utils/nodeify");
7
+ // Dictionary, key is value returned from anonymizeProxy(), value is Server instance.
8
+ const anonymizedProxyUrlToServer = {};
9
+ /**
10
+ * Parses and validates a HTTP proxy URL. If the proxy requires authentication, then the function
11
+ * starts an open local proxy server that forwards to the upstream proxy.
12
+ */
13
+ const anonymizeProxy = (options, callback) => {
14
+ let proxyUrl;
15
+ let port = 0;
16
+ if (typeof options === 'string') {
17
+ proxyUrl = options;
18
+ }
19
+ else {
20
+ proxyUrl = options.url;
21
+ port = options.port;
22
+ if (port < 0 || port > 65535) {
23
+ throw new Error('Invalid "port" option: only values equals or between 0-65535 are valid');
24
+ }
25
+ }
26
+ const parsedProxyUrl = new url_1.URL(proxyUrl);
27
+ if (!['http:', ...server_1.SOCKS_PROTOCOLS].includes(parsedProxyUrl.protocol)) {
28
+ // eslint-disable-next-line max-len
29
+ throw new Error(`Invalid "proxyUrl" provided: URL must have one of the following protocols: "http", ${server_1.SOCKS_PROTOCOLS.map((p) => `"${p.replace(':', '')}"`).join(', ')} (was "${parsedProxyUrl}")`);
30
+ }
31
+ // If upstream proxy requires no password, return it directly
32
+ if (!parsedProxyUrl.username && !parsedProxyUrl.password) {
33
+ return (0, nodeify_1.nodeify)(Promise.resolve(proxyUrl), callback);
34
+ }
35
+ let server;
36
+ const startServer = () => {
37
+ return Promise.resolve().then(() => {
38
+ server = new server_1.Server({
39
+ // verbose: true,
40
+ port,
41
+ host: '127.0.0.1',
42
+ prepareRequestFunction: () => {
43
+ return {
44
+ requestAuthentication: false,
45
+ upstreamProxyUrl: proxyUrl,
46
+ };
47
+ },
48
+ });
49
+ return server.listen();
50
+ });
51
+ };
52
+ const promise = startServer().then(() => {
53
+ const url = `http://127.0.0.1:${server.port}`;
54
+ anonymizedProxyUrlToServer[url] = server;
55
+ return url;
56
+ });
57
+ return (0, nodeify_1.nodeify)(promise, callback);
58
+ };
59
+ exports.anonymizeProxy = anonymizeProxy;
60
+ /**
61
+ * Closes anonymous proxy previously started by `anonymizeProxy()`.
62
+ * If proxy was not found or was already closed, the function has no effect
63
+ * and its result if `false`. Otherwise the result is `true`.
64
+ * @param closeConnections If true, pending proxy connections are forcibly closed.
65
+ */
66
+ const closeAnonymizedProxy = (anonymizedProxyUrl, closeConnections, callback) => {
67
+ if (typeof anonymizedProxyUrl !== 'string') {
68
+ throw new Error('The "anonymizedProxyUrl" parameter must be a string');
69
+ }
70
+ const server = anonymizedProxyUrlToServer[anonymizedProxyUrl];
71
+ if (!server) {
72
+ return (0, nodeify_1.nodeify)(Promise.resolve(false), callback);
73
+ }
74
+ delete anonymizedProxyUrlToServer[anonymizedProxyUrl];
75
+ const promise = server.close(closeConnections).then(() => {
76
+ return true;
77
+ });
78
+ return (0, nodeify_1.nodeify)(promise, callback);
79
+ };
80
+ exports.closeAnonymizedProxy = closeAnonymizedProxy;
81
+ /**
82
+ * Add a callback on 'tunnelConnectResponded' Event in order to get headers from CONNECT tunnel to proxy
83
+ * Useful for some proxies that are using headers to send information like ProxyMesh
84
+ * @returns `true` if the callback is successfully configured, otherwise `false` (e.g. when an
85
+ * invalid proxy URL is given).
86
+ */
87
+ const listenConnectAnonymizedProxy = (anonymizedProxyUrl, tunnelConnectRespondedCallback) => {
88
+ const server = anonymizedProxyUrlToServer[anonymizedProxyUrl];
89
+ if (!server) {
90
+ return false;
91
+ }
92
+ server.on('tunnelConnectResponded', ({ response, socket, head }) => {
93
+ tunnelConnectRespondedCallback({ response, socket, head });
94
+ });
95
+ return true;
96
+ };
97
+ exports.listenConnectAnonymizedProxy = listenConnectAnonymizedProxy;
98
+ //# sourceMappingURL=anonymize_proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymize_proxy.js","sourceRoot":"","sources":["../src/anonymize_proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ /// <reference types="node" />
5
+ /// <reference types="node" />
6
+ import dns from 'dns';
7
+ import { URL } from 'url';
8
+ import { EventEmitter } from 'events';
9
+ import { Buffer } from 'buffer';
10
+ import { Socket } from './socket';
11
+ export interface HandlerOpts {
12
+ upstreamProxyUrlParsed: URL;
13
+ localAddress?: string;
14
+ ipFamily?: number;
15
+ dnsLookup?: typeof dns['lookup'];
16
+ customTag?: unknown;
17
+ }
18
+ interface ChainOpts {
19
+ request: {
20
+ url?: string;
21
+ };
22
+ sourceSocket: Socket;
23
+ head?: Buffer;
24
+ handlerOpts: HandlerOpts;
25
+ server: EventEmitter & {
26
+ log: (connectionId: unknown, str: string) => void;
27
+ };
28
+ isPlain: boolean;
29
+ }
30
+ /**
31
+ * Passes the traffic to upstream HTTP proxy server.
32
+ * Client -> Apify -> Upstream -> Web
33
+ * Client <- Apify <- Upstream <- Web
34
+ */
35
+ export declare const chain: ({ request, sourceSocket, head, handlerOpts, server, isPlain, }: ChainOpts) => void;
36
+ export {};
37
+ //# sourceMappingURL=chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../src/chain.ts"],"names":[],"mappings":";;;;;AACA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAYlC,MAAM,WAAW,WAAW;IACxB,sBAAsB,EAAE,GAAG,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,SAAS;IACf,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,YAAY,GAAG;QAAE,GAAG,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7E,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,mEAQX,SAAS,KACb,IAgJF,CAAC"}
package/dist/chain.js ADDED
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chain = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const http_1 = tslib_1.__importDefault(require("http"));
6
+ const count_target_bytes_1 = require("./utils/count_target_bytes");
7
+ const get_basic_1 = require("./utils/get_basic");
8
+ const statuses_1 = require("./statuses");
9
+ /**
10
+ * Passes the traffic to upstream HTTP proxy server.
11
+ * Client -> Apify -> Upstream -> Web
12
+ * Client <- Apify <- Upstream <- Web
13
+ */
14
+ const chain = ({ request, sourceSocket, head, handlerOpts, server, isPlain, }) => {
15
+ if (head && head.length > 0) {
16
+ // HTTP/1.1 has no defined semantics when sending payload along with CONNECT and servers can reject the request.
17
+ // HTTP/2 only says that subsequent DATA frames must be transferred after HEADERS has been sent.
18
+ // HTTP/3 says that all DATA frames should be transferred (implies pre-HEADERS data).
19
+ //
20
+ // Let's go with the HTTP/3 behavior.
21
+ // There are also clients that send payload along with CONNECT to save milliseconds apparently.
22
+ // Beware of upstream proxy servers that send out valid CONNECT responses with diagnostic data such as IPs!
23
+ sourceSocket.unshift(head);
24
+ }
25
+ const { proxyChainId } = sourceSocket;
26
+ const { upstreamProxyUrlParsed: proxy, customTag } = handlerOpts;
27
+ const options = {
28
+ method: 'CONNECT',
29
+ path: request.url,
30
+ headers: [
31
+ 'host',
32
+ request.url,
33
+ ],
34
+ localAddress: handlerOpts.localAddress,
35
+ family: handlerOpts.ipFamily,
36
+ lookup: handlerOpts.dnsLookup,
37
+ };
38
+ if (proxy.username || proxy.password) {
39
+ options.headers.push('proxy-authorization', (0, get_basic_1.getBasicAuthorizationHeader)(proxy));
40
+ }
41
+ const client = http_1.default.request(proxy.origin, options);
42
+ client.on('connect', (response, targetSocket, clientHead) => {
43
+ (0, count_target_bytes_1.countTargetBytes)(sourceSocket, targetSocket);
44
+ if (sourceSocket.readyState !== 'open') {
45
+ // Sanity check, should never reach.
46
+ targetSocket.destroy();
47
+ return;
48
+ }
49
+ targetSocket.on('error', (error) => {
50
+ server.log(proxyChainId, `Chain Destination Socket Error: ${error.stack}`);
51
+ sourceSocket.destroy();
52
+ });
53
+ sourceSocket.on('error', (error) => {
54
+ server.log(proxyChainId, `Chain Source Socket Error: ${error.stack}`);
55
+ targetSocket.destroy();
56
+ });
57
+ if (response.statusCode !== 200) {
58
+ server.log(proxyChainId, `Failed to authenticate upstream proxy: ${response.statusCode}`);
59
+ if (isPlain) {
60
+ sourceSocket.end();
61
+ }
62
+ else {
63
+ const { statusCode } = response;
64
+ const status = statusCode === 401 || statusCode === 407
65
+ ? statuses_1.badGatewayStatusCodes.AUTH_FAILED
66
+ : statuses_1.badGatewayStatusCodes.NON_200;
67
+ sourceSocket.end((0, statuses_1.createCustomStatusHttpResponse)(status, `UPSTREAM${statusCode}`));
68
+ }
69
+ server.emit('tunnelConnectFailed', {
70
+ proxyChainId,
71
+ response,
72
+ customTag,
73
+ socket: targetSocket,
74
+ head: clientHead,
75
+ });
76
+ return;
77
+ }
78
+ if (clientHead.length > 0) {
79
+ // See comment above
80
+ targetSocket.unshift(clientHead);
81
+ }
82
+ server.emit('tunnelConnectResponded', {
83
+ proxyChainId,
84
+ response,
85
+ customTag,
86
+ socket: targetSocket,
87
+ head: clientHead,
88
+ });
89
+ sourceSocket.write(isPlain ? '' : `HTTP/1.1 200 Connection Established\r\n\r\n`);
90
+ sourceSocket.pipe(targetSocket);
91
+ targetSocket.pipe(sourceSocket);
92
+ // Once target socket closes forcibly, the source socket gets paused.
93
+ // We need to enable flowing, otherwise the socket would remain open indefinitely.
94
+ // Nothing would consume the data, we just want to close the socket.
95
+ targetSocket.on('close', () => {
96
+ sourceSocket.resume();
97
+ if (sourceSocket.writable) {
98
+ sourceSocket.end();
99
+ }
100
+ });
101
+ // Same here.
102
+ sourceSocket.on('close', () => {
103
+ targetSocket.resume();
104
+ if (targetSocket.writable) {
105
+ targetSocket.end();
106
+ }
107
+ });
108
+ });
109
+ client.on('error', (error) => {
110
+ var _a, _b;
111
+ server.log(proxyChainId, `Failed to connect to upstream proxy: ${error.stack}`);
112
+ // The end socket may get connected after the client to proxy one gets disconnected.
113
+ if (sourceSocket.readyState === 'open') {
114
+ if (isPlain) {
115
+ sourceSocket.end();
116
+ }
117
+ else {
118
+ const statusCode = (_a = statuses_1.errorCodeToStatusCode[error.code]) !== null && _a !== void 0 ? _a : statuses_1.badGatewayStatusCodes.GENERIC_ERROR;
119
+ const response = (0, statuses_1.createCustomStatusHttpResponse)(statusCode, (_b = error.code) !== null && _b !== void 0 ? _b : 'Upstream Closed Early');
120
+ sourceSocket.end(response);
121
+ }
122
+ }
123
+ });
124
+ sourceSocket.on('error', () => {
125
+ client.destroy();
126
+ });
127
+ // In case the client ends the socket too early
128
+ sourceSocket.on('close', () => {
129
+ client.destroy();
130
+ });
131
+ client.end();
132
+ };
133
+ exports.chain = chain;
134
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../src/chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ /// <reference types="node" />
5
+ /// <reference types="node" />
6
+ import http from 'http';
7
+ import { Buffer } from 'buffer';
8
+ import { URL } from 'url';
9
+ import { EventEmitter } from 'events';
10
+ import { Socket } from './socket';
11
+ export interface HandlerOpts {
12
+ upstreamProxyUrlParsed: URL;
13
+ customTag?: unknown;
14
+ }
15
+ interface ChainSocksOpts {
16
+ request: http.IncomingMessage;
17
+ sourceSocket: Socket;
18
+ head: Buffer;
19
+ server: EventEmitter & {
20
+ log: (connectionId: unknown, str: string) => void;
21
+ };
22
+ handlerOpts: HandlerOpts;
23
+ }
24
+ /**
25
+ * Client -> Apify (CONNECT) -> Upstream (SOCKS) -> Web
26
+ * Client <- Apify (CONNECT) <- Upstream (SOCKS) <- Web
27
+ */
28
+ export declare const chainSocks: ({ request, sourceSocket, head, server, handlerOpts, }: ChainSocksOpts) => Promise<void>;
29
+ export {};
30
+ //# sourceMappingURL=chain_socks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain_socks.d.ts","sourceRoot":"","sources":["../src/chain_socks.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,MAAM,WAAW,WAAW;IACxB,sBAAsB,EAAE,GAAG,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,cAAc;IACpB,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,GAAG;QAAE,GAAG,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7E,WAAW,EAAE,WAAW,CAAC;CAC5B;AAYD;;;GAGG;AACH,eAAO,MAAM,UAAU,0DAMpB,cAAc,KAAG,QAAQ,IAAI,CAoF/B,CAAC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chainSocks = void 0;
4
+ const url_1 = require("url");
5
+ const socks_1 = require("socks");
6
+ const count_target_bytes_1 = require("./utils/count_target_bytes");
7
+ const statuses_1 = require("./statuses");
8
+ const socksProtocolToVersionNumber = (protocol) => {
9
+ switch (protocol) {
10
+ case 'socks4:':
11
+ case 'socks4a:':
12
+ return 4;
13
+ default:
14
+ return 5;
15
+ }
16
+ };
17
+ /**
18
+ * Client -> Apify (CONNECT) -> Upstream (SOCKS) -> Web
19
+ * Client <- Apify (CONNECT) <- Upstream (SOCKS) <- Web
20
+ */
21
+ const chainSocks = async ({ request, sourceSocket, head, server, handlerOpts, }) => {
22
+ const { proxyChainId } = sourceSocket;
23
+ const { hostname, port, username, password } = handlerOpts.upstreamProxyUrlParsed;
24
+ const proxy = {
25
+ host: hostname,
26
+ port: Number(port),
27
+ type: socksProtocolToVersionNumber(handlerOpts.upstreamProxyUrlParsed.protocol),
28
+ userId: decodeURIComponent(username),
29
+ password: decodeURIComponent(password),
30
+ };
31
+ if (head && head.length > 0) {
32
+ // HTTP/1.1 has no defined semantics when sending payload along with CONNECT and servers can reject the request.
33
+ // HTTP/2 only says that subsequent DATA frames must be transferred after HEADERS has been sent.
34
+ // HTTP/3 says that all DATA frames should be transferred (implies pre-HEADERS data).
35
+ //
36
+ // Let's go with the HTTP/3 behavior.
37
+ // There are also clients that send payload along with CONNECT to save milliseconds apparently.
38
+ // Beware of upstream proxy servers that send out valid CONNECT responses with diagnostic data such as IPs!
39
+ sourceSocket.unshift(head);
40
+ }
41
+ const url = new url_1.URL(`connect://${request.url}`);
42
+ const destination = {
43
+ port: Number(url.port),
44
+ host: url.hostname,
45
+ };
46
+ let targetSocket;
47
+ try {
48
+ const client = await socks_1.SocksClient.createConnection({
49
+ proxy,
50
+ command: 'connect',
51
+ destination,
52
+ });
53
+ targetSocket = client.socket;
54
+ sourceSocket.write(`HTTP/1.1 200 Connection Established\r\n\r\n`);
55
+ }
56
+ catch (error) {
57
+ const socksError = error;
58
+ server.log(proxyChainId, `Failed to connect to upstream SOCKS proxy ${socksError.stack}`);
59
+ sourceSocket.end((0, statuses_1.createCustomStatusHttpResponse)((0, statuses_1.socksErrorMessageToStatusCode)(socksError.message), socksError.message));
60
+ return;
61
+ }
62
+ (0, count_target_bytes_1.countTargetBytes)(sourceSocket, targetSocket);
63
+ sourceSocket.pipe(targetSocket);
64
+ targetSocket.pipe(sourceSocket);
65
+ // Once target socket closes forcibly, the source socket gets paused.
66
+ // We need to enable flowing, otherwise the socket would remain open indefinitely.
67
+ // Nothing would consume the data, we just want to close the socket.
68
+ targetSocket.on('close', () => {
69
+ sourceSocket.resume();
70
+ if (sourceSocket.writable) {
71
+ sourceSocket.end();
72
+ }
73
+ });
74
+ // Same here.
75
+ sourceSocket.on('close', () => {
76
+ targetSocket.resume();
77
+ if (targetSocket.writable) {
78
+ targetSocket.end();
79
+ }
80
+ });
81
+ targetSocket.on('error', (error) => {
82
+ server.log(proxyChainId, `Chain SOCKS Destination Socket Error: ${error.stack}`);
83
+ sourceSocket.destroy();
84
+ });
85
+ sourceSocket.on('error', (error) => {
86
+ server.log(proxyChainId, `Chain SOCKS Source Socket Error: ${error.stack}`);
87
+ targetSocket.destroy();
88
+ });
89
+ };
90
+ exports.chainSocks = chainSocks;
91
+ //# sourceMappingURL=chain_socks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain_socks.js","sourceRoot":"","sources":["../src/chain_socks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import net from 'net';
2
+ import type http from 'http';
3
+ export declare const customConnect: (socket: net.Socket, server: http.Server) => Promise<void>;
4
+ //# sourceMappingURL=custom_connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom_connect.d.ts","sourceRoot":"","sources":["../src/custom_connect.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,eAAO,MAAM,aAAa,WAAkB,IAAI,MAAM,UAAU,KAAK,MAAM,KAAG,QAAQ,IAAI,CAqBzF,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.customConnect = void 0;
4
+ const util_1 = require("util");
5
+ const customConnect = async (socket, server) => {
6
+ // `countTargetBytes(socket, socket)` is incorrect here since `socket` is not a target.
7
+ // We would have to create a new stream and pipe traffic through that,
8
+ // however this would also increase CPU usage.
9
+ // Also, counting bytes here is not correct since we don't know how the response is generated
10
+ // (whether any additional sockets are used).
11
+ const asyncWrite = (0, util_1.promisify)(socket.write).bind(socket);
12
+ await asyncWrite('HTTP/1.1 200 Connection Established\r\n\r\n');
13
+ server.emit('connection', socket);
14
+ return new Promise((resolve) => {
15
+ if (socket.destroyed) {
16
+ resolve();
17
+ return;
18
+ }
19
+ socket.once('close', () => {
20
+ resolve();
21
+ });
22
+ });
23
+ };
24
+ exports.customConnect = customConnect;
25
+ //# sourceMappingURL=custom_connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom_connect.js","sourceRoot":"","sources":["../src/custom_connect.ts"],"names":[],"mappings":";;;AAEA,+BAAiC;AAE1B,MAAM,aAAa,GAAG,KAAK,EAAE,MAAkB,EAAE,MAAmB,EAAiB,EAAE;IAC1F,uFAAuF;IACvF,sEAAsE;IACtE,8CAA8C;IAC9C,6FAA6F;IAC7F,6CAA6C;IAE7C,MAAM,UAAU,GAAG,IAAA,gBAAS,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,UAAU,CAAC,6CAA6C,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAElC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,IAAI,MAAM,CAAC,SAAS,EAAE;YAClB,OAAO,EAAE,CAAC;YACV,OAAO;SACV;QAED,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,OAAO,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AArBW,QAAA,aAAa,iBAqBxB"}
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type http from 'http';
4
+ import type { Buffer } from 'buffer';
5
+ export interface CustomResponse {
6
+ statusCode?: number;
7
+ headers?: Record<string, string>;
8
+ body?: string | Buffer;
9
+ encoding?: BufferEncoding;
10
+ }
11
+ export interface HandlerOpts {
12
+ customResponseFunction: () => CustomResponse | Promise<CustomResponse>;
13
+ }
14
+ export declare const handleCustomResponse: (_request: http.IncomingMessage, response: http.ServerResponse, handlerOpts: HandlerOpts) => Promise<void>;
15
+ //# sourceMappingURL=custom_response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom_response.d.ts","sourceRoot":"","sources":["../src/custom_response.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,WAAW,cAAc;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IACxB,sBAAsB,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E;AAED,eAAO,MAAM,oBAAoB,aACnB,KAAK,eAAe,YACpB,KAAK,cAAc,eAChB,WAAW,KACzB,QAAQ,IAAI,CAqBd,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleCustomResponse = void 0;
4
+ const handleCustomResponse = async (_request, response, handlerOpts) => {
5
+ const { customResponseFunction } = handlerOpts;
6
+ if (!customResponseFunction) {
7
+ throw new Error('The "customResponseFunction" option is required');
8
+ }
9
+ const customResponse = await customResponseFunction();
10
+ if (typeof customResponse !== 'object' || customResponse === null) {
11
+ throw new Error('The user-provided "customResponseFunction" must return an object.');
12
+ }
13
+ response.statusCode = customResponse.statusCode || 200;
14
+ if (customResponse.headers) {
15
+ for (const [key, value] of Object.entries(customResponse.headers)) {
16
+ response.setHeader(key, value);
17
+ }
18
+ }
19
+ response.end(customResponse.body, customResponse.encoding);
20
+ };
21
+ exports.handleCustomResponse = handleCustomResponse;
22
+ //# sourceMappingURL=custom_response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom_response.js","sourceRoot":"","sources":["../src/custom_response.ts"],"names":[],"mappings":";;;AAcO,MAAM,oBAAoB,GAAG,KAAK,EACrC,QAA8B,EAC9B,QAA6B,EAC7B,WAAwB,EACX,EAAE;IACf,MAAM,EAAE,sBAAsB,EAAE,GAAG,WAAW,CAAC;IAC/C,IAAI,CAAC,sBAAsB,EAAE;QACzB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;KACtE;IAED,MAAM,cAAc,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAEtD,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,IAAI,EAAE;QAC/D,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;KACxF;IAED,QAAQ,CAAC,UAAU,GAAG,cAAc,CAAC,UAAU,IAAI,GAAG,CAAC;IAEvD,IAAI,cAAc,CAAC,OAAO,EAAE;QACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;YAC/D,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,KAAe,CAAC,CAAC;SAC5C;KACJ;IAED,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,QAAS,CAAC,CAAC;AAChE,CAAC,CAAC;AAzBW,QAAA,oBAAoB,wBAyB/B"}
@@ -0,0 +1,32 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ /// <reference types="node" />
5
+ import dns from 'dns';
6
+ import { Buffer } from 'buffer';
7
+ import { EventEmitter } from 'events';
8
+ import { Socket } from './socket';
9
+ export interface HandlerOpts {
10
+ localAddress?: string;
11
+ ipFamily?: number;
12
+ dnsLookup?: typeof dns['lookup'];
13
+ }
14
+ interface DirectOpts {
15
+ request: {
16
+ url?: string;
17
+ };
18
+ sourceSocket: Socket;
19
+ head: Buffer;
20
+ server: EventEmitter & {
21
+ log: (connectionId: unknown, str: string) => void;
22
+ };
23
+ handlerOpts: HandlerOpts;
24
+ }
25
+ /**
26
+ * Directly connects to the target.
27
+ * Client -> Apify (CONNECT) -> Web
28
+ * Client <- Apify (CONNECT) <- Web
29
+ */
30
+ export declare const direct: ({ request, sourceSocket, head, server, handlerOpts, }: DirectOpts) => void;
31
+ export {};
32
+ //# sourceMappingURL=direct.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct.d.ts","sourceRoot":"","sources":["../src/direct.ts"],"names":[],"mappings":";;;;AACA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAW,WAAW;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED,UAAU,UAAU;IAChB,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,GAAG;QAAE,GAAG,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7E,WAAW,EAAE,WAAW,CAAC;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,0DAOZ,UAAU,KACd,IA0EF,CAAC"}