finished http proxy
This commit is contained in:
parent
cecdd2d9fd
commit
4620732805
|
@ -26,7 +26,7 @@ ADD tor-sources.list /etc/apt/sources.list.d/tor.list
|
|||
|
||||
RUN bash /tmp/nodejs_install
|
||||
|
||||
RUN apt install -y --allow-unauthenticated deb.torproject.org-keyring nodejs tor git tzdata
|
||||
RUN apt install -y nodejs tor git
|
||||
|
||||
ADD package.json /app/package.json
|
||||
|
||||
|
@ -34,8 +34,6 @@ RUN npm install
|
|||
|
||||
ADD . /app
|
||||
|
||||
# Grab the current local timezone from an external api and save it into /etc/timezone, otherwise Tor will complain and won't start
|
||||
|
||||
ENTRYPOINT [ "tor-router" ]
|
||||
|
||||
CMD [ "-s", "-d", "-j", "1" ]
|
|
@ -16,7 +16,7 @@ To install globally run: `npm install -g`
|
|||
Alternatively docker can be used. The build will retrieve the latest version of Tor from the offical Tor Project repository.
|
||||
|
||||
To build run: `docker build -t znetstar/tor-router .`
|
||||
To start run: `docker run --rm -it -p 9050:9050 znetstar/tor-router tor-router --help`
|
||||
To start run: `docker run --rm -it -p 9050:9050 znetstar/tor-router`
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
curl -sL http://ip-api.com/json | node -e "process.stdin.resume(); process.stdin.on('data', (data) => { process.stdout.write(JSON.parse(data.toString('utf8')).timezone); process.exit(0); });"
|
|
@ -16,6 +16,7 @@ program
|
|||
.option('-j, --instances <1>', 'Number of tor instances', Number)
|
||||
.option('-s, --socksPort [9050]', 'SOCKS Server port', Number)
|
||||
.option('-d, --dnsPort [9053]', 'DNS Server port', Number)
|
||||
.option('-h, --httpPort [9080]', 'HTTP Server port', Number)
|
||||
.option('-l, --logLevel [info]', 'Log level (defaults to "info") set to "null" to disable logging', Number)
|
||||
.parse(process.argv);
|
||||
|
||||
|
@ -29,6 +30,7 @@ let instances = program.instances || Number(process.env.INSTANCES);
|
|||
let log_level = program.logLevel || process.env.LOG_LEVEL;
|
||||
let socks_port = (program.socksPort === true ? 9050 : program.socksPort) || Number(process.env.SOCKS_PORT);
|
||||
let dns_port = (program.dnsPort === true ? 9053 : program.dnsPort) || Number(process.env.DNS_PORT);
|
||||
let http_port = (program.httpPort === true ? 9080 : program.httpPort) || Number(process.env.HTTP_PORT);
|
||||
let control_port = (program.controlPort === true ? 9077 : program.controlPort) || Number(process.env.CONTROL_PORT) || 9077;
|
||||
|
||||
if (log_level === 'null')
|
||||
|
@ -44,6 +46,10 @@ if (socks_port) {
|
|||
let socks = control.createSOCKSServer(socks_port);
|
||||
}
|
||||
|
||||
if (http_port) {
|
||||
let http = control.createHTTPServer(http_port);
|
||||
}
|
||||
|
||||
if (dns_port) {
|
||||
let dns = control.createDNSServer(dns_port);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tor-router",
|
||||
"version": "3.0.7",
|
||||
"version": "3.1.0",
|
||||
"main": "src/index.js",
|
||||
"repository": "git@github.com:znetstar/tor-router.git",
|
||||
"author": "Zachary Boyd <zachary@zacharyboyd.nyc>",
|
||||
|
@ -27,6 +27,7 @@
|
|||
"lodash": "^4.17.4",
|
||||
"native-dns": "git+https://github.com/znetstar/node-dns.git",
|
||||
"socket.io": "^1.7.3",
|
||||
"socks-proxy-agent": "^3.0.1",
|
||||
"socksv5": "git+https://github.com/lee-elenbaas/socksv5.git",
|
||||
"temp": "^0.8.3",
|
||||
"winston": "^2.3.1"
|
||||
|
|
|
@ -2,6 +2,7 @@ const HTTPServer = require('http').Server;
|
|||
const TorPool = require('./TorPool');
|
||||
const SOCKSServer = require('./SOCKSServer');
|
||||
const DNSServer = require('./DNSServer');
|
||||
const HTTPProxyServer = require('./HTTPServer');
|
||||
|
||||
class ControlServer {
|
||||
constructor(logger) {
|
||||
|
@ -21,6 +22,7 @@ class ControlServer {
|
|||
socket.on('createTorPool', this.createTorPool.bind(this));
|
||||
socket.on('createSOCKSServer', this.createSOCKSServer.bind(this));
|
||||
socket.on('createDNSServer', this.createDNSServer.bind(this));
|
||||
socket.on('createHTTPServer', this.createHTTPServer.bind(this));
|
||||
socket.on('queryInstances', (callback) => {
|
||||
if (!this.torPool)
|
||||
return callback({ message: 'No pool created' });
|
||||
|
@ -51,6 +53,13 @@ class ControlServer {
|
|||
return this.socksServer;
|
||||
}
|
||||
|
||||
createHTTPServer(port) {
|
||||
this.httpServer = new HTTPProxyServer(this.torPool, this.logger);
|
||||
this.httpServer.listen(port || 9080);
|
||||
this.logger && this.logger.info(`[http]: Listening on ${port}`);
|
||||
return this.httpServer;
|
||||
}
|
||||
|
||||
createDNSServer(port) {
|
||||
this.dnsServer = new DNSServer(this.torPool, this.logger);
|
||||
this.dnsServer.serve(port || 9053);
|
||||
|
|
166
src/HTTPServer.js
Normal file
166
src/HTTPServer.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
const http = require('http');
|
||||
const Server = http.Server;
|
||||
const domain = require('domain');
|
||||
const socks = require('socksv5');
|
||||
const URL = require('url');
|
||||
const SocksProxyAgent = require('socks-proxy-agent');
|
||||
|
||||
class HTTPServer extends Server {
|
||||
constructor(tor_pool, logger) {
|
||||
let handle_http_connections = (req, res) => {
|
||||
let d = domain.create();
|
||||
|
||||
d.add(req);
|
||||
d.add(res);
|
||||
|
||||
let url = URL.parse(req.url);
|
||||
url.port = url.port || 80;
|
||||
|
||||
var buffer = [];
|
||||
|
||||
function onIncomingData(chunk) {
|
||||
buffer.push(chunk);
|
||||
}
|
||||
|
||||
function preConnectClosed() {
|
||||
req.finished = true;
|
||||
}
|
||||
|
||||
req.on('data', onIncomingData);
|
||||
req.on('end', preConnectClosed);
|
||||
|
||||
|
||||
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}`);
|
||||
|
||||
d.run(() => {
|
||||
let proxy_req = http.request({
|
||||
method: req.method,
|
||||
hostname: url.hostname,
|
||||
port: url.port,
|
||||
path: url.path,
|
||||
headers: req.headers,
|
||||
agent: new SocksProxyAgent(`socks://127.0.0.1:${socks_port}`)
|
||||
}, (proxy_res) => {
|
||||
d.add(proxy_res);
|
||||
proxy_res.on('data', (chunk) => {
|
||||
res.write(chunk);
|
||||
});
|
||||
|
||||
proxy_res.on('end', () => {
|
||||
res.end();
|
||||
});
|
||||
|
||||
res.writeHead(proxy_res.statusCode, proxy_res.headers);
|
||||
});
|
||||
|
||||
req.removeListener('data', onIncomingData);
|
||||
|
||||
req.on('data', (chunk) => {
|
||||
proxy_req.write(chunk);
|
||||
})
|
||||
|
||||
req.on('end', () => {
|
||||
proxy_req.end();
|
||||
})
|
||||
|
||||
while (buffer.length) {
|
||||
proxy_req.write(buffer.shift());
|
||||
}
|
||||
|
||||
if (req.finished)
|
||||
proxy_req.end();
|
||||
|
||||
d.add(proxy_req);
|
||||
});
|
||||
};
|
||||
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`);
|
||||
tor_pool.once('instance_created', connect);
|
||||
}
|
||||
};
|
||||
|
||||
let handle_tcp_connections = (req, inbound_socket, head) => {
|
||||
let d = domain.create();
|
||||
|
||||
d.add(socket);
|
||||
|
||||
let url = URL.parse(req.url);
|
||||
let hostname = url.host.split(':').shift();
|
||||
let port = url.host.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);
|
||||
};
|
||||
|
||||
let onClose = (error) => {
|
||||
inbound_socket && inbound_socket.end();
|
||||
outbound_socket && outbound_socket.end();
|
||||
|
||||
inbound_socket = outbound_socket = buffer = void(0);
|
||||
|
||||
if (error)
|
||||
this.logger.error(`[http]: an error occured: ${error.message}`)
|
||||
|
||||
d.exit();
|
||||
};
|
||||
|
||||
d.run(() => {
|
||||
socks.connect({
|
||||
host: hostname,
|
||||
port: port,
|
||||
proxyHost: '127.0.0.1',
|
||||
proxyPort: socks_port,
|
||||
localDNS: false,
|
||||
auths: [ socks.auth.None() ]
|
||||
}, ($outbound_socket) => {
|
||||
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());
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
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`);
|
||||
tor_pool.once('instance_created', connect);
|
||||
}
|
||||
};
|
||||
|
||||
super(handle_http_connections);
|
||||
this.on('connect', handle_tcp_connections);
|
||||
|
||||
this.logger = logger;
|
||||
this.tor_pool = tor_pool;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = HTTPServer;
|
|
@ -3,5 +3,6 @@ module.exports = {
|
|||
TorPool: require('./TorPool'),
|
||||
DNSServer: require('./DNSServer'),
|
||||
SOCKSServer: require('./SOCKSServer'),
|
||||
HTTPServer: require('./HTTPServer'),
|
||||
ControlServer: require('./ControlServer')
|
||||
};
|
Loading…
Reference in a new issue