Skip to content

Instantly share code, notes, and snippets.

@estliberitas
Created January 3, 2013 23:27
Show Gist options
  • Save estliberitas/4448496 to your computer and use it in GitHub Desktop.
Save estliberitas/4448496 to your computer and use it in GitHub Desktop.
Node.js script which makes Tor change identity (i.e. IP address)
/**
* Created with IntelliJ IDEA.
* User: Alexander <estliberitas> Makarenko
* Date: 04.01.13
* Time: 3:25
*/
'use strict';
var fs = require('fs')
, net = require('net')
, q = require('q')
, util = require('util')
, cookiePath = process.argv[2] || '/var/run/tor/control.authcookie'
, cookie = fs.readFileSync(cookiePath).toString('hex');
/**
* Request tor get new identity, i.e. reset circuit
*
* @param {String} host
* Hostname of Tor control service
* @param {String|Number} port
* Tor control port
* @param {String} [auth]
* Auth cookie (optional)
* @param {Function} callback
* Callback taking result (err)
*/
function new_identity(host, port, auth, callback) {
if (typeof auth === 'function') {
callback = auth;
auth = null;
}
var sock = new net.Socket({ allowHalfOpen: false });
connect(sock, port, host)
.then(function() {
return write(sock, util.format('AUTHENTICATE %s', auth));
})
.then(function() {
return write(sock, 'signal NEWNYM');
})
.then(function() {
sock.destroy();
callback();
})
.fail(function(err) {
sock.destroy();
callback(err);
});
}
/**
* Write data to socket in promise-style
*
* @param {net.Socket} sock
* Socket object
* @param {String} cmd
* Command to execute
* @return {promise}
* Promise object
*/
function write(sock, cmd) {
var deferred = q.defer();
if (!sock.writable) {
process.nextTick(function() {
deferred.reject(new Error('Socket is not writable'));
});
return deferred.promise;
}
sock.removeAllListeners('error');
sock.removeAllListeners('data');
sock.once('data', function(data) {
var res = data.toString().replace(/[\r\n]/g, '')
, tokens = res.split(' ')
, code = parseInt(tokens[0]);
if (code !== 250) {
deferred.reject(new Error(res));
} else {
deferred.resolve();
}
});
sock.once('err', deferred.reject);
sock.write(cmd + '\r\n');
return deferred.promise;
}
/**
* Connect to Tor control service in promise-style
*
* @param {net.Socket} sock
* Socket object
* @param {String|Number} port
* Tor control port
* @param host
* Tor control host
* @return {promise}
* Promise object
*/
function connect(sock, port, host) {
var deferred = q.defer();
sock.once('connect', deferred.resolve);
sock.once('error', deferred.reject);
sock.connect(port, host);
return deferred.promise;
}
new_identity('127.0.0.1', 9051, cookie, function(err) {
if (err) {
console.error(err);
} else {
console.log('Finished');
}
});
@sidpagariya
Copy link

So how do we use this, again?
Sorry, I am not sure!

Thanks,
Sid.

Copy link

ghost commented Sep 5, 2017

copy everything till line 114 and paste it in your nodejs program and call the new_identity function when you want to change the ip of the tor server! simple right ?...

@hack-tramp
Copy link

Note: This uses signal NEWNYM @line 41 which only changes the Tor route, it does not guarantee a new ip address - just a change of exit node - which may of course result in the same one again

@acba
Copy link

acba commented Oct 5, 2020

const net = require('net');

class TorService {

  private host;
  private port;

  constructor(host = '127.0.0.1', port = 9051) {
    this.host = host;
    this.port = port;
  }

  async reset() {

    const socket = new net.Socket({ allowHalfOpen: false });

    try {
      await this.connect(socket);
      await this.write(socket, 'AUTHENTICATE');
      await this.write(socket, 'signal NEWNYM');

      socket.destroy();
      return true;
    } catch (error) {
      socket.destroy();
      return false;
    }
  }

  private write(socket, cmd) {
    return new Promise((resolve, reject) => {
      if (!socket.writable) {
        reject(new Error('Socket is not writable'));
      }

      socket.removeAllListeners('error');
      socket.removeAllListeners('data');

      socket.once('data', function(data) {
        const res    = data.toString().replace(/[\r\n]/g, '');
        const tokens = res.split(' ')
        const code   = parseInt(tokens[0]);

        if (code !== 250) {
          reject(new Error(res));
        } else {
          resolve(true);
        }
      });

      socket.once('err', reject);
      socket.write(cmd + '\r\n');
    })
  }

  private connect(sock) {
    return new Promise((resolve, reject) => {
      sock.once('connect', resolve);
      sock.once('error', reject);
      sock.connect(this.port, this.host);
    })
  }
}

export const tors = new TorService();

A typescript version. I'm using inside a docker container, so I don't need any auth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment