From 54fa83bdf5d44489bc7e901dcd43b765cde41db2 Mon Sep 17 00:00:00 2001 From: Zachary Boyd Date: Thu, 7 Dec 2017 17:52:10 -0800 Subject: [PATCH] Adds HTTP Connect proxy --- README.md | 3 ++- src/HTTPServer.js | 63 ++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index e64c944..e0c8636 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ *Tor Router* is a simple SOCKS5 forward proxy for distributing traffic across multiple instances of Tor. At startup Tor Router will run an arbitrary number of instances Tor an each request will be sent to a different instance in round-robin fashion. This can be used to increase anonymity, because each request will be sent on a different circut and will most likely use a different exit-node, and also to increase performance since outbound traffic is now split across several instances of Tor. -Tor Router also includes a DNS forward proxy as well, which like the SOCKS proxy will distribute traffic across multiple instances of Tor in round-robin fashion. +Tor Router also includes a DNS forward proxy and a HTTP forward proxy as well, which like the SOCKS proxy will distribute traffic across multiple instances of Tor in round-robin fashion. ## Building and Running @@ -28,6 +28,7 @@ The following command line switches and their environment variable equivalents a |-j, --instances |INSTANCES |Number of Tor instances to spawn| |-s, --socksPort |SOCKS_PORT |Port the SOCKS proxy will bind to| |-d, --dnsPort |DNS_PORT |Port the DNS proxy will bind to| +|-h, --httpPort |HTTP_PORT |Port the HTTP proxy will bind to| |-l, --logLevel |LOG_LEVEL |The log level, "info" by default. Set to "null" to disable logging| diff --git a/src/HTTPServer.js b/src/HTTPServer.js index 5909f0d..0064cd2 100644 --- a/src/HTTPServer.js +++ b/src/HTTPServer.js @@ -9,7 +9,10 @@ class HTTPServer extends Server { constructor(tor_pool, logger) { let handle_http_connections = (req, res) => { let d = domain.create(); - + d.on('error', (error) => { + this.logger.error(`[http-proxy]: an error occured: ${error.message}`) + res.end(); + }); d.add(req); d.add(res); @@ -32,7 +35,7 @@ class HTTPServer extends Server { let connect = (tor_instance) => { let socks_port = tor_instance.socks_port; - logger && logger.info(`[http]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${url.hostname}:${url.port}`); + logger && logger.info(`[http-proxy]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${url.hostname}:${url.port}`); d.run(() => { let proxy_req = http.request({ @@ -78,32 +81,23 @@ class HTTPServer extends Server { if (tor_pool.instances.length) { connect(tor_pool.next()); } else { - logger.debug(`[http]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`); + logger.debug(`[http-proxy]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`); tor_pool.once('instance_created', connect); } }; - let handle_tcp_connections = (req, inbound_socket, head) => { + let handle_connect_connections = (req, inbound_socket, head) => { let d = domain.create(); - d.add(socket); + d.add(inbound_socket); - let url = URL.parse(req.url); - let hostname = url.host.split(':').shift(); - let port = url.host.split(':').pop(); + let hostname = req.url.split(':').shift(); + let port = Number(req.url.split(':').pop()); let connect = (tor_instance) => { let socks_port = tor_instance.socks_port; - logger && logger.info(`[http]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${hostname}:${port}`) - - d.on('error', onClose); - - d.add(inbound_socket); - - var buffer = []; - let onInboundData = function (data) { - buffer.push(data); - }; + logger && logger.info(`[http-connect]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${hostname}:${port}`) + var outbound_socket; let onClose = (error) => { inbound_socket && inbound_socket.end(); @@ -112,11 +106,20 @@ class HTTPServer extends Server { inbound_socket = outbound_socket = buffer = void(0); if (error) - this.logger.error(`[http]: an error occured: ${error.message}`) + this.logger.error(`[http-connect]: an error occured: ${error.message}`) d.exit(); }; + d.on('error', onClose); + + d.add(inbound_socket); + + var buffer = [head]; + let onInboundData = function (data) { + buffer.push(data); + }; + d.run(() => { socks.connect({ host: hostname, @@ -129,34 +132,26 @@ class HTTPServer extends Server { outbound_socket = $outbound_socket; d.add(outbound_socket); outbound_socket && outbound_socket.on('close', onClose); - - inbound_socket && inbound_socket.removeListener('data', onInboundData); - inbound_socket && inbound_socket.on('data', (data) => { - outbound_socket && outbound_socket.write(data); - }); - - outbound_socket && outbound_socket.on('data', (data) => { - inbound_socket && inbound_socket.write(data); - }); - outbound_socket && outbound_socket.on('error', onClose); - while (buffer && buffer.length && outbound_socket) { - outbound_socket.write(buffer.shift()); - } + inbound_socket.write('HTTP/1.1 200 Connection Established\r\n'+'Proxy-agent: tor-router\r\n' +'\r\n'); + outbound_socket.write(head); + + outbound_socket.pipe(inbound_socket); + inbound_socket.pipe(outbound_socket); }) }); }; if (tor_pool.instances.length) { connect(tor_pool.next()); } else { - logger.debug(`[http]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`); + logger.debug(`[http-connect]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`); tor_pool.once('instance_created', connect); } }; super(handle_http_connections); - this.on('connect', handle_tcp_connections); + this.on('connect', handle_connect_connections); this.logger = logger; this.tor_pool = tor_pool;