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.
- package/LICENSE +201 -0
- package/README.md +474 -3
- package/dist/anonymize_proxy.d.ts +37 -0
- package/dist/anonymize_proxy.d.ts.map +1 -0
- package/dist/anonymize_proxy.js +98 -0
- package/dist/anonymize_proxy.js.map +1 -0
- package/dist/chain.d.ts +37 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +134 -0
- package/dist/chain.js.map +1 -0
- package/dist/chain_socks.d.ts +30 -0
- package/dist/chain_socks.d.ts.map +1 -0
- package/dist/chain_socks.js +91 -0
- package/dist/chain_socks.js.map +1 -0
- package/dist/custom_connect.d.ts +4 -0
- package/dist/custom_connect.d.ts.map +1 -0
- package/dist/custom_connect.js +25 -0
- package/dist/custom_connect.js.map +1 -0
- package/dist/custom_response.d.ts +15 -0
- package/dist/custom_response.d.ts.map +1 -0
- package/dist/custom_response.js +22 -0
- package/dist/custom_response.js.map +1 -0
- package/dist/direct.d.ts +32 -0
- package/dist/direct.d.ts.map +1 -0
- package/dist/direct.js +73 -0
- package/dist/direct.js.map +1 -0
- package/dist/forward.d.ts +30 -0
- package/dist/forward.d.ts.map +1 -0
- package/dist/forward.js +97 -0
- package/dist/forward.js.map +1 -0
- package/dist/forward_socks.d.ts +15 -0
- package/dist/forward_socks.d.ts.map +1 -0
- package/dist/forward_socks.js +70 -0
- package/dist/forward_socks.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/request_error.d.ts +14 -0
- package/dist/request_error.d.ts.map +1 -0
- package/dist/request_error.js +32 -0
- package/dist/request_error.js.map +1 -0
- package/dist/server.d.ts +206 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +562 -0
- package/dist/server.js.map +1 -0
- package/dist/socket.d.ts +11 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +3 -0
- package/dist/socket.js.map +1 -0
- package/dist/statuses.d.ts +46 -0
- package/dist/statuses.d.ts.map +1 -0
- package/dist/statuses.js +82 -0
- package/dist/statuses.js.map +1 -0
- package/dist/tcp_tunnel_tools.d.ts +5 -0
- package/dist/tcp_tunnel_tools.d.ts.map +1 -0
- package/dist/tcp_tunnel_tools.js +94 -0
- package/dist/tcp_tunnel_tools.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/count_target_bytes.d.ts +9 -0
- package/dist/utils/count_target_bytes.d.ts.map +1 -0
- package/dist/utils/count_target_bytes.js +50 -0
- package/dist/utils/count_target_bytes.js.map +1 -0
- package/dist/utils/decode_uri_component_safe.d.ts +2 -0
- package/dist/utils/decode_uri_component_safe.d.ts.map +1 -0
- package/dist/utils/decode_uri_component_safe.js +13 -0
- package/dist/utils/decode_uri_component_safe.js.map +1 -0
- package/dist/utils/get_basic.d.ts +3 -0
- package/dist/utils/get_basic.d.ts.map +1 -0
- package/dist/utils/get_basic.js +15 -0
- package/dist/utils/get_basic.js.map +1 -0
- package/dist/utils/is_hop_by_hop_header.d.ts +2 -0
- package/dist/utils/is_hop_by_hop_header.d.ts.map +1 -0
- package/dist/utils/is_hop_by_hop_header.js +17 -0
- package/dist/utils/is_hop_by_hop_header.js.map +1 -0
- package/dist/utils/nodeify.d.ts +2 -0
- package/dist/utils/nodeify.d.ts.map +1 -0
- package/dist/utils/nodeify.js +17 -0
- package/dist/utils/nodeify.js.map +1 -0
- package/dist/utils/normalize_url_port.d.ts +3 -0
- package/dist/utils/normalize_url_port.d.ts.map +1 -0
- package/dist/utils/normalize_url_port.js +22 -0
- package/dist/utils/normalize_url_port.js.map +1 -0
- package/dist/utils/parse_authorization_header.d.ts +9 -0
- package/dist/utils/parse_authorization_header.d.ts.map +1 -0
- package/dist/utils/parse_authorization_header.js +53 -0
- package/dist/utils/parse_authorization_header.js.map +1 -0
- package/dist/utils/redact_url.d.ts +3 -0
- package/dist/utils/redact_url.d.ts.map +1 -0
- package/dist/utils/redact_url.js +15 -0
- package/dist/utils/redact_url.js.map +1 -0
- package/dist/utils/valid_headers_only.d.ts +5 -0
- package/dist/utils/valid_headers_only.d.ts.map +1 -0
- package/dist/utils/valid_headers_only.js +39 -0
- package/dist/utils/valid_headers_only.js.map +1 -0
- package/package.json +88 -4
- 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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"}
|
package/dist/chain.d.ts
ADDED
@@ -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 @@
|
|
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"}
|
package/dist/direct.d.ts
ADDED
@@ -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"}
|