Adds group functionality to TorPool
This commit is contained in:
parent
94a6511fd5
commit
22908b7bba
|
@ -14,6 +14,7 @@
|
|||
- The `Config` property of instance definitions will now inherit from `TorPool.default_tor_config`.
|
||||
- The mocha test has been split into individual files all under `test/`
|
||||
- DNS shows the source/destination hostname/port in logs instead of what the query was resolved to
|
||||
- `TorProcess` takes an instance definition as the second argument in its constructor.
|
||||
|
||||
### Removes
|
||||
- The `new_ips` and `new_ip_at` TorPool and `new_ip` TorProcess have been removed. Use `new_identites`, `new_identity_at` and `new_identity` instead.
|
||||
|
|
|
@ -144,14 +144,14 @@ class ControlServer {
|
|||
}
|
||||
|
||||
async createSOCKSServer(port, hostname) {
|
||||
this.socksServer = new SOCKSServer(this.torPool, this.logger, (this.nconf.get('proxyByName') ? { deny_unidentified_users: this.nconf.get('denyUnidentifedUsers') } : ""));
|
||||
this.socksServer = new SOCKSServer(this.torPool, this.logger, (this.nconf.get('proxyByName') ? { mode: this.nconf.get('proxyByName'), deny_unidentified_users: this.nconf.get('denyUnidentifedUsers') } : ""));
|
||||
await this.socksServer.listen(port || default_ports.socks, hostname);
|
||||
this.logger.info(`[socks]: listening on socks5://${hostname}:${port}`);
|
||||
this.socksServer;
|
||||
}
|
||||
|
||||
async createHTTPServer(port, hostname) {
|
||||
this.httpServer = new HTTPServer(this.torPool, this.logger, (this.nconf.get('proxyByName') ? { deny_unidentified_users: this.nconf.get('denyUnidentifedUsers') } : ""));
|
||||
this.httpServer = new HTTPServer(this.torPool, this.logger, (this.nconf.get('proxyByName') ? { mode: this.nconf.get('proxyByName'), deny_unidentified_users: this.nconf.get('denyUnidentifedUsers') } : ""));
|
||||
await this.httpServer.listen(port || default_ports.http, hostname);
|
||||
this.logger.info(`[http]: listening on http://${hostname}:${port}`);
|
||||
this.httpServer;
|
||||
|
|
|
@ -45,6 +45,100 @@ class TorPool extends EventEmitter {
|
|||
this.granax_options = granax_options;
|
||||
}
|
||||
|
||||
get group_names() {
|
||||
return _.uniq(_.flatten(this.instances.map((instance) => instance.instance_group).filter(Boolean)));
|
||||
}
|
||||
|
||||
add_instance_to_group(group, instance) {
|
||||
instance.definition.Group = _.union(instance.instance_group, [group]);
|
||||
}
|
||||
|
||||
add_instance_to_group_by_name(group, instance_name) {
|
||||
let instance = this.instance_by_name(instance_name);
|
||||
|
||||
if (!instance) throw new Error(`Instance "${instance_name}" not found`);
|
||||
|
||||
return this.add_instance_to_group(group, instance);
|
||||
}
|
||||
|
||||
add_instance_to_group_at(group, instance_index) {
|
||||
let instance = this.instance_at(instance_index);
|
||||
|
||||
if (!instance) throw new Error(`Instance at "${instance_index}" not found`);
|
||||
|
||||
return this.add_instance_to_group(group, instance);
|
||||
}
|
||||
|
||||
remove_instance_from_group(group, instance) {
|
||||
_.remove(instance.definition.Group, (g) => g === group);
|
||||
}
|
||||
|
||||
remove_instance_from_group_by_name(group, instance_name) {
|
||||
let instance = this.instance_by_name(instance_name);
|
||||
|
||||
if (!instance) throw new Error(`Instance "${instance_name}" not found`);
|
||||
|
||||
return this.remove_instance_from_group(group, instance);
|
||||
}
|
||||
|
||||
remove_instance_from_group_at(group, instance_index) {
|
||||
let instance = this.instance_at(instance_index);
|
||||
|
||||
if (!instance) throw new Error(`Instance at "${instance_index}" not found`);
|
||||
|
||||
return this.remove_instance_from_group(group, instance);
|
||||
}
|
||||
|
||||
get groups() {
|
||||
let groupHandler = {
|
||||
get: (instances, prop) => {
|
||||
if (!Number.isNaN(Number(prop)))
|
||||
return instances[prop];
|
||||
|
||||
let { group_name } = instances;
|
||||
|
||||
if (prop === 'add')
|
||||
return (instance) => {
|
||||
return this.add_instance_to_group(group_name, instance);
|
||||
};
|
||||
|
||||
if (prop === 'add_by_name')
|
||||
return this.add_instance_to_group_by_name.bind(this, group_name);
|
||||
|
||||
if (prop === 'remove')
|
||||
return (instance) => {
|
||||
return this.remove_instance_from_group(group_name, instance);
|
||||
};
|
||||
|
||||
if (prop === 'remove_by_name')
|
||||
return this.remove_instance_from_group_by_name.bind(this, group_name);
|
||||
|
||||
if (prop === 'remove_at')
|
||||
return (instance_index) => {
|
||||
return this.remove_instance_from_group(group_name, instances[instance_index]);
|
||||
};
|
||||
|
||||
return void(0);
|
||||
}
|
||||
};
|
||||
|
||||
let groupsHandler = {
|
||||
get: (group_names, prop) => {
|
||||
let instances_in_group = [];
|
||||
|
||||
if (group_names.indexOf(prop) !== -1) {
|
||||
instances_in_group = this.instances.filter((instance) => instance.instance_group.indexOf(prop) !== -1);
|
||||
}
|
||||
|
||||
instances_in_group.group_name = prop;
|
||||
|
||||
return new Proxy(instances_in_group, groupHandler);
|
||||
}
|
||||
};
|
||||
|
||||
return new Proxy(this.group_names, groupsHandler);
|
||||
}
|
||||
|
||||
get default_tor_config() {
|
||||
if (typeof(this._default_tor_config) === 'function')
|
||||
return this._default_tor_config();
|
||||
|
@ -77,7 +171,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
get instances() {
|
||||
return this._instances.slice(0).filter((tor) => tor.ready);
|
||||
return this._instances.slice(0);
|
||||
}
|
||||
|
||||
async create_instance(instance_definition) {
|
||||
|
@ -89,10 +183,9 @@ class TorPool extends EventEmitter {
|
|||
let instance_id = nanoid();
|
||||
instance_definition.Config.DataDirectory = instance_definition.Config.DataDirectory || path.join(this.data_directory, (instance_definition.Name || instance_id));
|
||||
|
||||
let instance = new TorProcess(this.tor_path, instance_definition.Config, this.granax_options, this.logger);
|
||||
let instance = new TorProcess(this.tor_path, instance_definition, this.granax_options, this.logger);
|
||||
|
||||
instance.id = instance_id;
|
||||
instance.definition = instance_definition;
|
||||
|
||||
await instance.create();
|
||||
|
||||
|
|
|
@ -20,16 +20,19 @@ Promise.promisifyAll(fs);
|
|||
temp.track();
|
||||
|
||||
class TorProcess extends EventEmitter {
|
||||
constructor(tor_path, config, granax_options, logger) {
|
||||
constructor(tor_path, definition, granax_options, logger) {
|
||||
super();
|
||||
this.logger = logger || require('./winston-silent-logger');
|
||||
|
||||
definition.Group = definition.Group ? [].concat(definition.Group) : [];
|
||||
|
||||
this._definition = definition;
|
||||
|
||||
this.tor_path = tor_path;
|
||||
this.granax_options = granax_options;
|
||||
this.control_password = crypto.randomBytes(128).toString('base64');
|
||||
|
||||
config.DataDirectory = config.DataDirectory || temp.mkdirSync();
|
||||
|
||||
this.tor_config = config;
|
||||
this.tor_config.DataDirectory = this.tor_config.DataDirectory || temp.mkdirSync();
|
||||
}
|
||||
|
||||
async exit() {
|
||||
|
@ -43,11 +46,18 @@ class TorProcess extends EventEmitter {
|
|||
await p;
|
||||
}
|
||||
|
||||
get instance_group() {
|
||||
return (this.definition && this.definition.Group) || null;
|
||||
}
|
||||
|
||||
get instance_name() {
|
||||
return (this.definition && this.definition.Name) || this.process.pid;
|
||||
}
|
||||
|
||||
get definition() { return this._definition; }
|
||||
|
||||
get tor_config() { return this.definition.Config; }
|
||||
|
||||
get dns_port() {
|
||||
return this._dns_port || null;
|
||||
}
|
||||
|
@ -109,7 +119,7 @@ class TorProcess extends EventEmitter {
|
|||
HashedControlPassword: shell.exec(`${this.tor_path} --quiet --hash-password "${this.control_password}"`, { async: false, silent: true }).stdout.trim()
|
||||
};
|
||||
|
||||
let config = _.extend(_.extend({}, this.tor_config), options);
|
||||
let config = _.extend(_.cloneDeep(this.tor_config), options);
|
||||
let text = Object.keys(config).map((key) => `${key} ${config[key]}`).join(os.EOL);
|
||||
|
||||
let configFile = await temp.openAsync('tor-router');
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
"socksHost": null,
|
||||
"dnsHost": null,
|
||||
"httpHost": null,
|
||||
"proxyByName": true,
|
||||
"proxyByName": 'individual',
|
||||
"denyUnidentifedUsers": false,
|
||||
"logLevel": "info",
|
||||
"loadBalanceMethod": "round_robin",
|
||||
|
|
|
@ -31,6 +31,9 @@ async function main(nconf, logger) {
|
|||
let control_host = typeof(nconf.get('controlHost')) !== 'boolean' ? extractHost(nconf.get('controlHost')) : nconf.get('controlHost');
|
||||
let control_host_ws = typeof(nconf.get('websocketControlHost')) !== 'boolean' ? extractHost(nconf.get('websocketControlHost')) : nconf.get('websocketControlHost');
|
||||
|
||||
if (nconf.get('proxyByName') && nconf.get('proxyByName') === true)
|
||||
nconf.set('proxyByName', 'individual');
|
||||
|
||||
if (typeof(control_host) === 'boolean') {
|
||||
control_host = extractHost(9077);
|
||||
nconf.set('controlHost', assembleHost(control_port));
|
||||
|
@ -75,9 +78,10 @@ async function main(nconf, logger) {
|
|||
}
|
||||
|
||||
if (instances) {
|
||||
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instance(s)...`)
|
||||
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instance(s)...`);
|
||||
|
||||
await control.torPool.create(instances);
|
||||
|
||||
|
||||
logger.info('[tor]: tor started');
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -9,7 +9,7 @@ require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
|||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
describe('TorProcess', function () {
|
||||
let tor = new TorProcess(nconf.get('torPath'), { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 }, null);
|
||||
let tor = new TorProcess(nconf.get('torPath'), { Config: { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 } }, null);
|
||||
describe('#create()', function () {
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
||||
|
|
Loading…
Reference in a new issue