如何在node.js中同时使用多个代理(代理)

For*_*vin 5 proxy http socks http-proxy node.js

我正在使用一个 HTTP 请求库,它可以使用http.Agent实例来通过特定代理路由您的请求。让我举一个例子:

const SocksProxyAgent = require('socks-proxy-agent')
const HttpProxyAgent = require('http-proxy-agent') // not used
const axios = require('axios')

// requires Tor service to be running
const torProxyAgent = new SocksProxyAgent('socks://circuit1@127.0.0.1:9050')
// not used
const otherProxyAgent = new HttpProxyAgent('http://admin:1234@localhost:8888')

const axiosConfig = {
    httpsAgent: torProxyAgent,
    httpAgent: torProxyAgent
}

const axiosInstance = axios.create(axiosConfig)

axiosInstance.get('https://ifconfig.io/ip')
  .then(res => {
    console.log('Public IP address:', res.data)
  }).catch(err => {
    console.log(err)
  })
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我指定了多个代理 (torProxyAgentotherProxyAgent),但我只能使用一个。

因此,我正在寻找一种超级代理,我可以将其传递给我的 HTTP 请求库,然后该超级代理通过将所有请求路由到第一个代理,然后通过第二个代理,然后将任意数量的普通代理链接在一起。到第三个,依此类推……

这可能吗?有现成的解决方案吗?

是否有一种方法可以使用Proxy类创建一个假代理,将所有方法调用传递给一个代理,然后传递给第二个代理?

编辑:
虽然我很欣赏lifeisfoo的回答,但它只解决了一个理论问题,我碰巧只使用了两个代理(一个HTTP代理和一个socks代理)。实际上,我不想仅限于两个代理,并且我希望能够指定顺序。

lif*_*foo 5

更新的答案 - axios +ocks-proxy-agent + http代理

看起来解决方案比我想象的更容易:

const SocksProxyAgent = require('socks-proxy-agent')
const axios = require('axios')

const torProxyAgent = new SocksProxyAgent('socks://circuit1@127.0.0.1:9050')

const axiosConfig = {
    httpsAgent: torProxyAgent,
    httpAgent: torProxyAgent,
    proxy: {
        protocol: 'http', //'http',
        host: '89.208.35.81', // your http proxy ip
        port: 3128, // your http proxy port
        // optional - add it if your proxy require auth
        auth: {
          username: 'myuser',
          password: 'mypass'
        }
    }
}

const axiosInstance = axios.create(axiosConfig)

axiosInstance.get('https://ifconfig.io/ip')
  .then(res => {
    console.log('Public IP address:', res.data)
  }).catch(err => {
    console.log(err)
  })
Run Code Online (Sandbox Code Playgroud)

确保仅当您的袜子代理在本地运行时才使用本地主机 HTTP 代理,否则将无法访问它。显然,socks 和代理 IP 应该使用可用的 IP 进行更新,我使用了在公共代理列表中找到的一些 IP作为测试,但它们不可靠。

怎么运行的

Nodejs 文档说代理

[...] 负责管理 HTTP 客户端的连接持久性和重用。它维护给定主机和端口的待处理请求队列,为每个请求重用单个套接字连接,直到队列为空。

基本上,它公开了一个返回套接字的createConnection函数:

此方法保证返回 <net.Socket> 类(<stream.Duplex> 的子类)的实例,除非用户指定除 <net.Socket> 之外的套接字类型。

如果您查看另一个袜子代理(例如socks5-http-client/lib/Agent)的源代码,很容易看出这种行为:

var http = require('http');
var inherits = require('util').inherits;
var socksClient = require('socks5-client');

function Agent(options) {
    http.Agent.call(this, options);
    this.createConnection = socksClient.createConnection;
}

inherits(Agent, http.Agent);

module.exports = Agent;
Run Code Online (Sandbox Code Playgroud)

尝试调试请求流,您将看到socks连接数据和http数据都写入了套接字上。在Socks5ClientSocket.prototype.write函数中添加断点或日志

Socks5ClientSocket.prototype.write = function(data, encoding, cb) {
    console.log('Writing', data);
    return this.socket.write(data, encoding, cb);
};
Run Code Online (Sandbox Code Playgroud)

你会看到这样的东西:

Writing <Buffer 05 01 00>
Writing <Buffer 05 01 00 01 59 d0 23 51 0c 38>
Writing GET http://ip-api.com/json HTTP/1.1 ....// http request data
Run Code Online (Sandbox Code Playgroud)

前两行是建立与socks代理的socks连接的字节,然后将http数据写入同一套接字,但使用http代理作为目标主机。

因此,从 http 库的角度来看,代理只是一个套接字提供者,因此您可以根据需要创建此套接字,可能会在同一个套接字上链接更多连接(请参阅我的原始答案)。

axios+socks5-http-client+http代理

var Agent = require('socks5-http-client/lib/Agent');
var axios = require('axios');

const socksProxyOpts = {
    socksHost: '5.189.130.21',
    socksPort: 1080
};
const socksAgent = new Agent(socksProxyOpts);
const axiosConfig = {
    httpAgent: socksAgent,
    proxy: {
        protocol: 'http',
        host: '89.208.35.81',// or '45.33.99.194',
        port: 3128 // or 8888
      }
}

const axiosInstance = axios.create(axiosConfig)

axiosInstance.get('http://ip-api.com/json')
.then(res => {
    console.log('Public IP address:', res.data)
  }).catch(err => {
    console.log(err)
  })
Run Code Online (Sandbox Code Playgroud)

原答案

是的,这是可能的,正如您从这个C proxychains 应用程序及其配置文件中看到的那样:

[ProxyList]
# based on you configuration
socks4  127.0.0.1 9050  circuit1
http    localhost 8888  admin 1234
Run Code Online (Sandbox Code Playgroud)

但看起来没有一个现有的节点模块能够处理混合类型的代理链(socks、http)。

袜子可以处理一系列袜子代理,但此功能尚未公开给您正在使用的袜子代理代理。

可以使用http-proxy和此gist中的代码来实现 http 代理链。

所以你有三个选择:

如果您选择最后一个,请务必检查socks库源代码以了解链创建逻辑的createConnectionChain函数。

也可以看看: