更新答案 - 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 代理链。
所以你有三个选择:
如果您选择最后一个,请务必查看 createConnectionChain 函数 for the chain creation logic 的 socks 库源代码。
另见: