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

Posted

技术标签:

【中文标题】如何在 node.js 中同时使用多个代理(代理)【英文标题】:How to use multiple proxies (agents) at the same time in node.js 【发布时间】:2020-11-22 13:26:12 【问题描述】:

我正在使用一个 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)
  )

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

所以我正在寻找一种超级代理,我可以将它传递给我的 HTTP 请求库,然后这个超级代理将任意数量的普通代理链接在一起,方法是将我的所有请求通过第一个路由,然后通过第二个,然后通过第三个等等......

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

有没有办法使用Proxy 类创建一个假代理,将所有方法调用传递给一个代理,然后再传递给第二个代理?

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

【问题讨论】:

你为什么要做这个?你想达到什么结果?通过多个节点传递连接? 是的,我希望能够创建支持不同类型代理的代理链,例如 socks 和 http 代理。例如。 PC->Tor-socks-proxy->HTTP-proxy->服务器 我更新了我的答案,这应该可以解决你的问题 【参考方案1】:

更新答案 - axios + socks-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)
  )

确保仅当您的 socks 代理在本地运行时才使用 localhost HTTP 代理,否则将无法访问。显然,socks 和代理 IP 应该更新为可用的,我使用在 public proxy list 上找到的一些 IP 作为测试,但它们不可靠。

工作原理

Agent 的 nodejs 文档 sasys:

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

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

此方法保证返回 类的实例, 的子类,除非用户指定 以外的套接字类型。

这种行为如果你查看另一个像socks5-http-client/lib/Agent这样的socks代理的源代码很容易看出:

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;

尝试调试请求流,你会看到socks连接数据和http数据都写在了socket上。添加断点或登录Socks5ClientSocket.prototype.write function

Socks5ClientSocket.prototype.write = function(data, encoding, cb) 
    console.log('Writing', data);
    return this.socket.write(data, encoding, cb);
;

你会看到这样的东西:

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

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

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

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)
  )

原答案

是的,您可以从这个C proxychains application 和它的configuration file 看到:

[ProxyList]
# based on you configuration
socks4  127.0.0.1 9050  circuit1
http    localhost 8888  admin 1234

但似乎没有现有的节点模块能够处理一系列混合类型的代理(socks、http)。

socks 库可以处理 chain of socks proxies,但此功能 isn't already exposed 可以处理您正在使用的 socks-proxy-agent。

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

所以你有三个选择:

使用现有的proxychains application 使用socks 使用一系列袜子代理 破解 socks 库以在链中添加对 http 代理的支持

如果您选择最后一个,请务必查看 createConnectionChain 函数 for the chain creation logic 的 socks 库源代码。

另见:

[斯卡拉]https://github.com/Karasiq/proxychain [锈]https://github.com/eycorsican/leaf [JS]https://www.npmjs.com/package/tunnel

【讨论】:

以上是关于如何在 node.js 中同时使用多个代理(代理)的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个 HTTP 反向代理服务器

如何使用 Node.js 通过代理发送 HTTP/2 请求?

基于 Unix Socket 的可靠 Node.js HTTP 代理实现(支持 WebSocket 协议)

node.js 中的代理身份验证与模块请求

第1882期基于Unix Socket的可靠Node.js HTTP代理实现(支持WebSocket协议)

8 行 Node.js 代码实现代理服务器