Https requests via 2 socks5 proxies
Tags: help, node, javascript, typescript
Published: 2022-02-24 11:56:31

I am trying to achieve an experimental setup in nodejs as illustrated below:

https-server --> local socks5 proxy (Tor) --> my external socks5 proxy --> webserver.

The existing https-server was written in nodejs and it intercepts requests from the clients firefox browser, modifies the headers, and uses the request module to fetch the requested url provided by the client.
I would like the https request to tunnel through Tor, then through my external proxy (necessary for data collection for my experiments), and then to the webserver. 


I found that the socks module has a feature for chaining proxies but it has no Agent to send the https request. The code below works with the chain of proxies and with http and not https.

```
const SocksClient = require('socks').SocksClient;

const options = {
  destination: {
    host: 'ip-api.com', // host names are supported with SOCKS v4a and SOCKS v5.
    port: 80
  },
  command: 'connect', // Only the connect command is supported when chaining proxies.
  proxies: [ // The chain order is the order in the proxies array, meaning the last proxy will establish a connection to the destination.
    {
      ipaddress: '127.0.0.1', // ipv4, ipv6, or hostname
      port: 9050,
      type: 5
    },
    {
      ipaddress: 'my external proxy ip', // ipv4, ipv6, or hostname
      port: 1080,
      type: 5
    }
  ]
};


var socket = SocksClient.createConnectionChain(options)
  .then(info => {
    //console.log(info.socket);
    console.log(info.socket.remoteAddress); 
    info.socket.write('GET /json HTTP/1.1\nHost: ip-api.com\n\n');
    info.socket.on('data', (data) => {
      console.log(data.toString()); // ip-api.com sees that the last proxy in the chain is connected to it.    
    });
  })
  .catch(err => {
    // Handle errors
    console.log(err);
  });
```


Also, there is a module called socks5-https-client that is able to send https requests over a single socks5 proxy (see code below). It uses the request module and the socks5-https-client as an agent, a solution I would prefer. Unfortunately, it does not support proxy chaining (more than 1 proxy).

```
var Agent = require('socks5-https-client/lib/Agent');

request({
	url: 'https://encrypted.google.com/',
	strictSSL: true,
	agentClass: Agent,
	agentOptions: {
		socksHost: 'my-tor-proxy-host', // Defaults to 'localhost'.
		socksPort: 9050, // Defaults to 1080.

		// Optional credentials that I don't need
		//socksUsername: 'proxyuser',
		//socksPassword: 'p@ssw0rd',
	}
}, function(err, res) {
	console.log(err || res.body);
});
```
 

I am a beginner in node programming but these are my general thoughts to a solution. An https agent can be added to the existing socks module -- the module already supports chaining of proxies -- such that it can be parsed to the request module as an agent, just like in the second code. Alternatively, the socks5-https-client can be modified to have a function like the createConnectionChain() in the socks module to support multiple proxies.

I will be grateful if anyone can assist me with a solution or materials that I can follow to get this done. Thanks