what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Tormux Ruby TOR Controller 0.1

Tormux Ruby TOR Controller 0.1
Posted Jul 21, 2012
Authored by dirtyfilthy | Site github.com

tormux.rb is a single file, zero dependency ruby tor controller for reverse multiplexing outgoing connections between tor exit nodes. By default tor only builds a single circuit, and all your traffic will travel out of a single exit node until the circuit is destroyed and a new circuit is created. but tormux.rb will build and maintain one circuit for each of the number of exit nodes you specify, and round robin your outgoing tor connections between them automatically.

tags | tool, ruby
systems | unix
SHA-256 | 527f59cc6a812254ef01ef67daeaf6d9554561605fa74a844bc39f29447d4419

Tormux Ruby TOR Controller 0.1

Change Mirror Download
#!/usr/bin/ruby

############
#
# tormux.rb v0.1 by dirtyfilthy, latest code at http://github.com/dirtyfilthy/tormux.rb
#
############

<<README


tormux.rb is a single file, zero dependency ruby tor controller for reverse multiplexing outgoing
connections between tor exit nodes. By default tor only builds a single circuit, and all your
traffic will travel out of a single exit node until the circuit is destroyed and a new circuit is
created. but tormux.rb will build and maintain one circuit for each of the number of exit nodes you
specify, and round robin your outgoing tor connections between them automatically.

## INSTALLATION

If you have ruby and tor you already have everthing you need. simply "chmod +x tormux.rb",
uncomment the ControlPort line in your /etc/tor/torrc and restart tor. You may also want to add a
password to your tor controller service. To do this, run "tor --hash-password YOURPASS" and copy
& paste the resulting hash into your torrc with a line like:
"HashedControlPassword 16:8129231FD5FB5CB460C8223024AD08B5B268596F1CF0142EFCA99C9150"

## USAGE

tormux.rb builds 2 hop circuits and does not support .onion addresses. It will kill any current
tor circuits and connections you have running. The number of guards refers to the the number of
entry nodes you're going to use, this doesn't have to (and probably shouldn't) be equal to the
number of exit nodes. It's usable as soon as you start seeing "built circuit" lines in the output.
Simply use tor as per normal, each connection you make will be automatically routed to a
different exit node in a round robin fashion.

## OPTIONS

./tormux.rb
tormux v0.1 -- simple controller to multiplex between tor exit nodes
Usage: ./tormux.rb [options] -x EXITNODES
NOTE: You will need to enable ControlPort in your torrc and possibly set a password,
tormux will also kill any current tor circuits.

Options:
-p, --password PASS the password for tor control (plaintext)
-x, --exits EXITNODES number of exit nodes to spin up
-g, --guards GUARDNODES number of guards to use (default 10)
-t, --tor-control IP:PORT the tor control port to connect to (default 127.0.0.1:9051)


README

require 'socket'
require 'base64'
require 'time'
require 'optparse'

class TorCtl

class Reply
attr_accessor :code
attr_accessor :lines

def to_s
return "#{code} #{lines.join("\n")}"
end

end

class NetworkStatus
attr_accessor :nick
attr_accessor :idhash
attr_accessor :orhash
attr_accessor :ip
attr_accessor :orport
attr_accessor :dirport
attr_accessor :flags
attr_accessor :updated
attr_accessor :idhex

def idhash=(r)
@idhex=Base64.decode64(r+"=").unpack("H*").first
@idhash=r
end

end


def initialize(options = {}, &block)
@options = options.dup
@host = (@options.delete(:host) || '127.0.0.1').to_s
@port = (@options.delete(:port) || 9051).to_i
@num_circuits = (@options.delete(:circuits) || 10).to_i

@num_guards = (@options.delete(:guards) || 10).to_i
@authenticated=false
@event_queue=[]
@routers = []
@exits = []
@guards = []
@gc=0

@xc=0
@pool = []
@cur_circuit=0
connect
authenticate
@max_onions_pending=get_conf("MaxOnionsPending")
@new_circuit_period=get_conf("newcircuitperiod")
@new_circuit_dirtiness=get_conf("newcircuitdirtiness")
set_conf "__DisablePredictedCircuits",1
set_conf "MaxOnionsPending", 0
set_conf "newcircuitperiod", 99999999
set_conf "maxcircuitdirtiness", 99999999
set_conf "__LeaveStreamsUnattached",1


trap("INT"){ shutdown }

end


# tidy up after ourselves

def shutdown
puts "shutting down"
@pool = []
close_current_circuits
set_conf "__DisablePredictedCircuits",0
set_conf "__LeaveStreamsUnattached",0
set_conf "MaxOnionsPending", @max_onions_pending
set_conf "newcircuitperiod", @new_circuit_period
set_conf "newcircuitdirtiness", @new_circuit_dirtiness
@stop_now=true
end

def close_current_circuits
puts "killing old circuits"
r=send_command("GETINFO","circuit-status")
r.lines.shift
r.lines.each do |l|
if l=~/\d+ BUILT/
send_command("CLOSECIRCUIT",l.scan(/^\d+/).first)
end
end
end

def build_circuit
f=@guards[@gc]
x=@exits[@xc]
return nil if x.nil?
extend_circuit(0,["$#{f.idhex}","$#{x.idhex}"])
@gc=(@gc+1) % @guards.size
@xc=(@xc+1) % @exits.size
end

def build_circuits
puts "spinning up #{@num_circuits} circuits"
@guards=@guards.shuffle[0..(@num_guards-1)]
@exits.shuffle
@num_circuits.times do
build_circuit
end
end

def get_routers
puts "gettings tor directory"
r=send_command("GETINFO","ns/all")
r.lines.shift
ns=nil
loop do
line=r.lines.shift
break if line=="OK" or line.nil?
case line[0]
when 'r'
@routers << ns unless ns.nil?
ns=NetworkStatus.new
ns_ary=line.scan(/r (\S+) (\S+) (\S+) (\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d) (\d+\.\d+\.\d+\.\d+) (\d+) (\d+)/).first
ns.nick = ns_ary[0]
ns.idhash = ns_ary[1]
ns.orhash = ns_ary[2]
ns.updated = Time.parse(ns_ary[3])
ns.ip = ns_ary[4]
ns.orport = ns_ary[5]
ns.dirport = ns_ary[6]
when 's'
ns.flags = line.split
ns.flags.shift
end
end
@exits=@routers.select{|r| r.flags.include?("Exit")}
@guards=@routers.select{|r| r.flags.include?("Guard")} - @exits
puts "#{@exits.count} exits & #{@guards.count} guards found"
end

def extend_circuit(circuit_id, hops)
args=[circuit_id]
hops=[hops] if hops.is_a?(String)
args<<hops.join(",")
r=send_command("EXTENDCIRCUIT", *args);
raise "failed to extend circuit '#{r.lines[0]}'" if !(r.lines[0]=~/EXTENDED/)
return r.lines[0].scan(/EXTENDED (\S*)/).first.first
end

def connect
puts "connecting to tor control #{@host}:#{@port}"
@socket = TCPSocket.new(@host, @port)
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
self
end

def send_command(command, *args)
authenticate unless authenticated?
send_line(["#{command.to_s.upcase}", *args].join(' '))
loop do
r=read_reply
if(r.code[0]=='6')
@event_queue<<r
else
return r
end
end
end

def send_line(line)
@socket.write(line.to_s + "\r\n")
@socket.flush
end



def read_line
@socket.readline.chomp
end

def read_reply
reply=Reply.new
lines = []
loop do
line=read_line
code=line[0..2]
mode=line[3]
line=line[4..-1]
lines << line
case mode
when ' '
reply.lines=lines
reply.code=code
return reply
when '-'
reply.code=code
when '+'
while((r=read_line)!=".") do
lines << r
end
end
end
end

def authenticated?
return (@authenticated==true)
end


def set_conf(key,value)
send_command("SETCONF","#{key}=#{value}")
end



def get_conf(key)
r=send_command("GETCONF","#{key}")
return r.lines[0].split("=")[1]
end



def set_events(events)
args=["EXTENDED"]
args<<events
send_command("SETEVENTS",*args)
end

def authenticate(cookie = nil)
puts "authenticating"
cookie ||= @options[:cookie]
send(:send_line, cookie ? "AUTHENTICATE \"#{@cookie}\"" : "AUTHENTICATE")
case reply = read_line
when '250 OK' then @authenticated = true
else raise "Couldn't auth: #{reply}"
end
self
end

def process_events
while(e=@event_queue.shift) do
if e.code=="650" and e.lines.first=~/STREAM \d+ NEW/
next if @pool.size==0
stream_id=e.lines.first.scan(/STREAM (\d+) NEW/).first.first
@cur_circuit=(@cur_circuit+1) % @pool.size
next if @pool[@cur_circuit].nil?
p=send_command("ATTACHSTREAM",stream_id,@pool[@cur_circuit])
end

if e.code=="650" and e.lines.first=~/STREAM \d+ DETACHED/
next if @pool.size==0
stream_id=e.lines.first.scan(/STREAM (\d+) DETACHED/).first.first
@cur_circuit=(@cur_circuit+1) % @pool.size
next if @pool[@cur_circuit].nil?
p=send_command("ATTACHSTREAM",stream_id,@pool[@cur_circuit])
end


if e.code=="650" and e.lines.first=~/CIRC \d+ BUILT/
circ = e.lines.first.scan(/CIRC (\d+) BUILT/).first.first
@pool << circ
puts "built circuit #{circ}"
end



if e.code=="650" and e.lines.first=~/CIRC \d+ CLOSED/
circ = e.lines.first.scan(/CIRC (\d+) CLOSED/).first.first
build_circuit if @pool.delete(circ)
end


if e.code=="650" and e.lines.first=~/CIRC \d+ FAILED/
build_circuit
end

end
end

def main_loop
loop do
break if @stop_now
r=read_reply
@event_queue << r if r.code[0]=='6'
process_events
end
@socket.close
end

end
options={}
options[:circuits]=0
opts=OptionParser.new do |opts|

opts.banner = <<-eos
tormux v0.1 -- simple tor controller to reverse multiplex between tor exit nodes
Usage: ./tormux.rb [options] -x EXITNODES
NOTE: You will need to enable ControlPort in your torrc and possibly set a password,
tormux will also kill any current tor circuits.
eos
opts.separator ""
opts.separator "Options:"
opts.on("-p", "--password PASS", "the password for tor control (plaintext)") do |pass|
options[:cookie] = pass
end

opts.on("-x", "--exits EXITNODES", "number of exit nodes to spin up") do |ex|
options[:circuits] = ex.to_i
end

opts.on("-g", "--guards GUARDNODES", "number of guards to use (default 10)") do |g|
options[:guards] = g.to_i
end


opts.on("-t", "--tor-control IP:PORT", "the tor control port to connect to (default 127.0.0.1:9051)") do |t|
options[:host]=t.split(":")[0]
options[:port]=t.split(":")[1]
end

end
opts.parse!
if options[:circuits]==0
puts opts
exit(0)
end
t=TorCtl.new(options)

t.set_events(["STREAM", "CIRC", "ADDRMAP", "NEWDESC"]);
t.close_current_circuits
t.get_routers
t.build_circuits
t.main_loop
Login or Register to add favorites

File Archive:

March 2023

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    13 Files
  • 3
    Mar 3rd
    15 Files
  • 4
    Mar 4th
    0 Files
  • 5
    Mar 5th
    0 Files
  • 6
    Mar 6th
    16 Files
  • 7
    Mar 7th
    31 Files
  • 8
    Mar 8th
    16 Files
  • 9
    Mar 9th
    13 Files
  • 10
    Mar 10th
    9 Files
  • 11
    Mar 11th
    0 Files
  • 12
    Mar 12th
    0 Files
  • 13
    Mar 13th
    10 Files
  • 14
    Mar 14th
    6 Files
  • 15
    Mar 15th
    17 Files
  • 16
    Mar 16th
    22 Files
  • 17
    Mar 17th
    13 Files
  • 18
    Mar 18th
    0 Files
  • 19
    Mar 19th
    0 Files
  • 20
    Mar 20th
    16 Files
  • 21
    Mar 21st
    13 Files
  • 22
    Mar 22nd
    5 Files
  • 23
    Mar 23rd
    6 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    0 Files
  • 26
    Mar 26th
    0 Files
  • 27
    Mar 27th
    0 Files
  • 28
    Mar 28th
    0 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close