Node.js中的全局SOCKS5代理

时间:2019-12-21 06:34:44

标签: javascript node.js proxy

有一些npm软件包,用于在Node.js中设置全局http(s)代理。但是可以设置一个全球的socks5代理吗?

我首先深入the source code中的global-agent,发现核心部分是这些行:

// Overriding globalAgent was added in v11.7.
// @see https://nodejs.org/uk/blog/release/v11.7.0/
if (semver.gte(process.version, 'v11.7.0')) {
  // @see https://github.com/facebook/flow/issues/7670
  // $FlowFixMe
  http.globalAgent = httpAgent;

  // $FlowFixMe
  https.globalAgent = httpsAgent;
}

从v11.7版本开始,Node.js提供http.globalAgenthttps.globalAgent用于全局修改来自http(s)模块的所有请求的代理。我想知道是否可以用袜子代理代替。因此,我尝试使用socks-proxy-agent软件包,就像这样:

import http = require("http");
import https = require("https");
import SocksProxyAgent = require("socks-proxy-agent");

export function setSocksProxy(host: string, port: number) {
    const proxyUrl = `socks://${host}:${port}`;
    const agent = new SocksProxyAgent(proxyUrl);

    http.globalAgent = https.globalAgent = agent;
}

事实证明:

1)在那些仅使用Node.js http(s)模块(在我的情况下为oauth)的程序包中,它工作正常。

2)但是,在那些使用request的软件包中,它失败了。错误消息是:

Error: a SOCKS proxy server `host` and `port` must be specified!
    at new SocksProxyAgent (./node_modules/socks-proxy-agent/index.js:28:11)
    at new ClientRequest (_http_client.js:116:13)
    at TunnelingAgent.request (http.js:44:10)
    at TunnelingAgent.createSocket (./node_modules/tunnel-agent/index.js:135:25)
    at TunnelingAgent.createSecureSocket [as createSocket] (./node_modules/tunnel-agent/index.js:200:41)
    at TunnelingAgent.createConnection (./node_modules/tunnel-agent/index.js:98:8)
    at TunnelingAgent.addRequest (./node_modules/tunnel-agent/index.js:92:8)
    at new ClientRequest (_http_client.js:277:16)
    at Object.request (https.js:305:10)
    at Object.request (./node_modules/agent-base/patch-core.js:23:20)

我遵循了调用堆栈,发现了一些东西。

TunnelingAgent.createSocket(./node_modules/tunnel-agent/index.js:135:25)中,connectOptions.agent设置为false

var connectOptions = mergeOptions({}, self.proxyOptions,
    { method: 'CONNECT'
    , path: options.host + ':' + options.port
    , agent: false
    }
  )
var connectReq = self.request(connectOptions)

然后self.request(connectOptions)呼叫http.request

在内部代码ClientRequest(_http_client.js:116:13)中,由于options.agent设置为false,因此agent = new defaultAgent.constructor()将运行。

let agent = options.agent;
const defaultAgent = options._defaultAgent || Agent.globalAgent;
if (agent === false) {
  agent = new defaultAgent.constructor();
} else if (agent === null || agent === undefined) {
  if (typeof options.createConnection !== 'function') {
    agent = defaultAgent;
  }
  // Explicitly pass through this statement as agent will not be used
  // when createConnection is provided.
} else if ...
this.agent = agent;

不幸的是,new SocksProxyAgent(proxyUrl)需要一个参数。也就是说,我的先前的全局设置已丢失,因为http尝试创建一个新的SocksProxyAgent(不带参数)。先前的代码:

const proxyUrl = `socks://${host}:${port}`;
const agent = new SocksProxyAgent(proxyUrl);
http.globalAgent = https.globalAgent = agent;

那么...我应该如何使它按理行事?

0 个答案:

没有答案