diff --git a/src/DNSServer.js b/src/DNSServer.js index 9321fc5..1620ebe 100644 --- a/src/DNSServer.js +++ b/src/DNSServer.js @@ -9,33 +9,42 @@ class DNSServer extends UDPServer { this.on('request', (req, res) => { for (let question of req.question) { - let dns_port = (tor_pool.next().dns_port); - - let outbound_req = dns.Request({ - question, - server: { address: '127.0.0.1', port: dns_port, type: 'udp' }, - timeout: this.timeout - }); + let connect = (tor_instance) => { + let dns_port = (tor_instance.dns_port); + let outbound_req = dns.Request({ + question, + server: { address: '127.0.0.1', port: dns_port, type: 'udp' }, + timeout: this.timeout + }); - outbound_req.on('message', (err, answer) => { - if (!err && answer) { - for (let a of answer.answer){ - res.answer.push(a); - this.logger && this.logger.info(`[dns]: ${question.name} type ${dns.consts.QTYPE_TO_NAME[question.type]} → 127.0.0.1:${dns_port} → ${a.address}`) + outbound_req.on('message', (err, answer) => { + if (!err && answer) { + for (let a of answer.answer){ + res.answer.push(a); + this.logger && this.logger.info(`[dns]: ${question.name} type ${dns.consts.QTYPE_TO_NAME[question.type]} → 127.0.0.1:${dns_port} → ${a.address}`) + } } - } - }); + }); - outbound_req.on('error', (err) => { + outbound_req.on('error', (err) => { - }); + }); - outbound_req.on('end', () => { - res.send(); - }); + outbound_req.on('end', () => { + res.send(); + }); - outbound_req.send(); + outbound_req.send(); + }; + + if (this.tor_pool.instances.length) { + connect(this.tor_pool.next()); + } + else { + this.log.debug(`[dns]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`); + this.tor_pool.once('instance_created', connect); + } } }); } diff --git a/src/SOCKSServer.js b/src/SOCKSServer.js index 71835bf..2d33bdb 100644 --- a/src/SOCKSServer.js +++ b/src/SOCKSServer.js @@ -12,60 +12,68 @@ class SOCKSServer extends SOCKS5Server{ var outbound_socket; let buffer = []; - let socks_port = (tor_pool.next().socks_port); - logger && logger.info(`[socks]: ${info.srcAddr}:${info.srcPort} → 127.0.0.1:${socks_port} → ${info.dstAddr}:${info.dstPort}`) + let connect = (tor_instance) => { + let socks_port = tor_instance.socks_port; + logger && logger.info(`[socks]: ${info.srcAddr}:${info.srcPort} → 127.0.0.1:${socks_port} → ${info.dstAddr}:${info.dstPort}`) - let onClose = (error) => { - inbound_socket && inbound_socket.end(); - outbound_socket && outbound_socket.end(); + let onClose = (error) => { + inbound_socket && inbound_socket.end(); + outbound_socket && outbound_socket.end(); - inbound_socket = outbound_socket = buffer = void(0); + inbound_socket = outbound_socket = buffer = void(0); - if (error) - this.logger.error(`[socks]: an error occured: ${error.message}`) + if (error) + this.logger.error(`[socks]: an error occured: ${error.message}`) - d.exit(); + d.exit(); + }; + + d.on('error', onClose); + + let onInboundData = (data) => buffer.push(data) + + if (!inbound_socket) return; + + inbound_socket.on('close', onClose); + inbound_socket.on('data', onInboundData); + inbound_socket.on('error', onClose); + + d.run(() => { + socks.connect({ + host: info.dstAddr, + port: info.dstPort, + 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()); + } + }) + }); }; - - d.on('error', onClose); - - let onInboundData = (data) => buffer.push(data) - - if (!inbound_socket) return; - - inbound_socket.on('close', onClose); - inbound_socket.on('data', onInboundData); - inbound_socket.on('error', onClose); - - d.run(() => { - socks.connect({ - host: info.dstAddr, - port: info.dstPort, - 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(`[socks]: 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(handleConnection); diff --git a/src/TorPool.js b/src/TorPool.js index 95340f7..ffb6b8d 100644 --- a/src/TorPool.js +++ b/src/TorPool.js @@ -37,7 +37,7 @@ class TorPool extends EventEmitter { this.logger = logger; } - get instances() { return this._instances.slice(0); } + get instances() { return this._instances.filter((tor) => tor.ready).slice(0); } create_instance(callback) { let config = _.extend({}, this.tor_config) @@ -48,6 +48,7 @@ class TorPool extends EventEmitter { instance.once('error', callback) instance.once('ready', () => { + this.emit('instance_created', instance); callback && callback(null, instance); }); }); diff --git a/src/TorProcess.js b/src/TorProcess.js index f1a0b01..ad1ff98 100644 --- a/src/TorProcess.js +++ b/src/TorProcess.js @@ -31,6 +31,7 @@ class TorProcess extends EventEmitter { } new_ip() { + this.log.info(`[tor-${this.process.pid}]: has requested a new identity`); this.process.kill('SIGHUP'); } @@ -82,6 +83,7 @@ class TorProcess extends EventEmitter { }); this.once('ready', () => { + this.ready = true; this.logger && this.logger.info(`[tor-${tor.pid}]: tor is ready`); });