Hacking Tor's Control Protocol
by iphelix
0. Introduction
This guide will show you how to enhance (or completely break) your privacy on the Intertubes by delving into Tor's internals.
You will learn how to create custom circuits of any size, monitor every aspect of Tor activity, and other really cool hacks. The key to all of this is Tor's embedded control protocol which gives you a lot more control over Tor's operations compared to the standard "push-the-big-red-button" GUI interfaces.
1. Setting Up
First things first, you must enable the Tor control port by editing /etc/tor/torrc.
Uncomment ControlPort line:
## The port on which Tor will listen for local connections from Tor ## controller applications, as documented in control-spec.txt. ControlPort 9051Hint: You can quickly enable control port by passing --controlport 9051 when executing Tor from the command line.
With the control port open, we can now connect to the Tor server:
$ telnet localhost 9051Once connected, we need to authenticate (password hash is "" by default):
authenticate "" 250 OKNote: Vidalia enables control port with a password, you will need to look up that password or avoid using Vidalia to start Tor.
1.1. Tor Control Commands
We can now control the Tor client's operation by issuing a number of commands. This is a bit boring, but you will need to learn some of the more important commands before you can start messing with Tor.
1.1.1 Viewing and Setting Configuration Variables
You can view and set Tor configuration variables to change Tor's operation. Most of these variables are set in the /etc/tor/torrc file, but you can override them dynamically as you see fit. Play with these commands to learn more about Tor's configuration.
getconf - Gets a value stored in a configuration variable.
getconf controlport 250 ControlPort=9051setconf - Sets configuration variables. For the most part these variables can be set inside /etc/tor/torrc; there are several variables (e.g. __DisablePredictedCircuits) which can only be set through the Tor control interface.
setconf controlport=9051 250 OKresetconf - Reset configuration variable to its default value.
resetconf controlport 250 OK getconf controlport 250 ControlPort=0saveconf - Saves current configuration values to the /etc/tor/torrc file. Values such as __DisablePredictedCircuits will not be saved.
For a complete listing of configuration variables that you can view or set issue the following command:
getinfo config/names1.1.2 Viewing What Tor is Doing
Tor has a highly customizable logging system which allows us to see exactly what it is doing in the background. Before any information will be displayed, we must tell Tor exactly what we want to see using the setevents command. setevents enables console log output of predefined event types. Valid event types include:
- CIRC - Circuit events. Includes information on newly created, already existing, and closed circuits.
- STREAM - Stream events. Provides information on the status of application streams, including which circuit is used for the connection.
- ORCONN - Tor network connection events. These events display newly established and closed connections to Tor nodes.
- BW - Bandwidth in the last second. If you enable this event, it will produce output every second, even if there is no activity.
- STREAM_BW - Bandwidth used by individual streams. Unlike BW, STREAM_BW displays data only when there is activity.
- DEBUG, INFO, NOTICE, WARN, ERR - Informational messages of varying severity.
- ADDRMAP - Address mapping events. These events show domain-to-IP mappings that are cached by the Tor client.
- NEWDESC, AUTHDIR_NEWDESCS, DESCCHANGED - dirserver events.
- STATUS_GENERAL, STATUS_CLIENT, STATUS_SERVER - Status information.
- GUARD - Guard node events.
- NS - Network status events.
So, in order to enable console output of event types circ (circuit events) issue the following command:
setevents circMultiple events can be specified at the same time:
setevents circ stream orconnPrepend keyword extended to see extended event information where available:
setevents extended circNote: Every time you issue a setevents command, all displayed event types will be reset.
I personally find the following set of events most informative:
setevents extended circ stream orconn addrmap status_general status_client guardFor a complete listing of event types that you can enable, use the following command:
getinfo events/names1.1.3 Querying Tor for Runtime Information
Tor has a large number of runtime variables that it needs to keep track of in order to successfully build circuits. We can query this information using the getinfo command.
Get information on currently open circuits:
getinfo circuit-status 250+circuit-status= 4 BUILT Xaishacha,Bellum,croeso 3 BUILT blutroth,TorMiddleMan391,sabotage 2 BUILT blutroth,poolTOR,$9E9FAD3187C9911B71849E0E63F35C7CD41FAAA3 1 BUILT blutroth,$E285783006B1B7193B296A5C858B95FD85566A60,$E56FEABE3E7D822931F768A7A0F18E7BEA901EBD . 250 OKGet information about currently open streams:
getinfo stream-status 250+stream-status= 4 SUCCEEDED 2 74.125.39.147:80 2 SUCCEEDED 2 74.125.39.147:80 3 SUCCEEDED 2 74.125.39.147:80 250 OKIn case you don't see expected output, enable appropriate event output using the setevents command.
For a complete listing of information types that you can view issue the following command:
getinfo info/names2. Creating Custom Circuits
Now that you know how to configure Tor, we are ready for some fun.
First, you will need to change some configs to disable circuit autocreation and allow us to create and destroy all circuits manually:
# disable preemptively creating circuits setconf __DisablePredictedCircuits=1 # maximum circuits pending setconf MaxOnionsPending=0 # longer period before creating new circuit setconf newcircuitperiod=999999999 # longer period for circuit expiration setconf maxcircuitdirtiness=999999999Let's delete already created circuits so that they don't interfere with us:
closecircuit 2 250 OK closecircuit 1 250 OK getinfo circuit-status 250-circuit-status= 250 OK2.1 Creating Five or More Hop Circuits
How about creating a five-hop circuit for privacy overkill ;).
Use the extendcircuit command to create, or extend, circuits.
extendcircuit 0 blutroth,TorMiddleMan391,sabotage,croeso,chaoscomputerclub23 250 EXTENDED 5 getinfo circuit-status 250-circuit-status=5 EXTENDED blutroth,TorMiddleMan391,sabotage 250 OK getinfo circuit-status 250-circuit-status=5 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso 250 OK getinfo circuit-status 250-circuit-status=5 BUILT blutroth,TorMiddleMan391,sabotage,croeso,chaoscomputerclub23 250 OKImmediately following extendcircuit is the circuit ID. 0 means create new circuit. Any other number will extend an already existing circuit with the supplied circuit ID.
Let's go insane with a ten-hop circuit. To build a circuit of this size, we will need to increase the circuit build timeout. This does not really increase your anonymity, but it is still awesome to send your packets flying around the world:
setconf circuitbuildtimeout=300 250 OK extendcircuit 0 blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga,bettyboop,optipiii866,chaoscomputerclub23 250 EXTENDED 18 650 CIRC 18 LAUNCHED 650 CIRC 18 EXTENDED blutroth 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga,bettyboop 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga,bettyboop,optipiii866 650 CIRC 18 EXTENDED blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga,bettyboop,optipiii866,chaoscomputerclub23 650 CIRC 18 BUILT blutroth,TorMiddleMan391,sabotage,croeso,Xaishacha,aim1loxal1net,Tonga,bettyboop,optipiii866,chaoscomputerclub23Now when we request google.com, you will see the following output in your console (provided you have used setevents beforehand). In summary, a new circuit ID 60 is created, destined for google.com port 80, which than connects using circuit ID 18 that we have created. We will appear to be coming from tor.anonymizer.ccc.de [81.169.137.209].
650 STREAM 60 NEW 0 google.com:80 650 STREAM 60 SENTCONNECT 18 google.com:80 650 STREAM 60 REMAP 18 64.233.187.99:80 650 STREAM 60 SUCCEEDED 18 64.233.187.99:80 650 STREAM 61 NEW 0 www.google.com:80 650 STREAM 61 SENTCONNECT 18 www.google.com:80 650 STREAM 61 REMAP 18 209.85.135.147:80 650 STREAM 61 SUCCEEDED 18 209.85.135.147:80 650 STREAM 62 NEW 0 www.google.de:80 650 STREAM 62 SENTCONNECT 18 www.google.de:80 650 STREAM 62 REMAP 18 209.85.135.147:80 650 STREAM 62 SUCCEEDED 18 209.85.135.147:80 650 STREAM 60 CLOSED 18 64.233.187.99:80 650 STREAM 61 CLOSED 18 209.85.135.147:80 650 STREAM 62 CLOSED 18 209.85.135.147:802.2 Creating Two-Hop Circuits
Let's create a two-hop circuit instead of the usual three hops.
Our circuit will be going through tor.anonymizer.ccc.de. Two-hop Tor circuits increase connection bandwidth, for which we pay with reduced anonymity:
extendcircuit 0 blutroth,chaoscomputerclub23 250 EXTENDED 11 getinfo circuit-status 250-circuit-status=18 BUILT blutroth,chaoscomputerclub23 250 OK2.3 Creating Really Fast One-Hop Circuits
If privacy is not an issue, and we simply need to use a specific Tor exit node, we can use single node Tor circuits. This comes in handy when a service is offered only to a specific IP space. For example, you can watch Top Gear on the BBC for free only if you come from a U.K. IP address space.
We will need to modify Tor source to make this work, so go ahead and download the latest Tor source tarball from www.torproject.org/download-unix.html.en.
You will need to edit the tor/src/or/control.c file.
Remove or comment out the following lines of code, which limit one-hop circuit creation:
if (circ && (circuit_get_cpath_len(circ) < 2 || hop == 1)) { connection_write_str_to_buf("551 Can't attach stream to one-hop circuit.\r\n", conn); return 0; }Compile with the usual:
$ ./configure $ make $ make installNote: I had to apt-get install libevent-dev libssl libssl-dev on my test Ubuntu box for compilation to work.
Tor was never built for single hop circuits, so we will need to disable a few more safety mechanisms:
setconf FastFirstHop=0 setconf EnforceDistinctSubnets=0 setconf UseEntryGuards=0Now let's create a really fast one-hop circuit with a compatible exit node desync:
getinfo circuit-status 250-circuit-status= 250 OK extendcircuit 0 desync 250 EXTENDED 40 650 CIRC 40 LAUNCHED 650 CIRC 40 EXTENDED desync 650 CIRC 40 BUILT desync getinfo circuit-status 250-circuit-status=40 BUILT desync 250 OK 650 STREAM 29 NEW 0 whatismyip.org:80 SOURCE_ADDR=127.0.0.1:37631 PURPOSE=USER 650 STREAM 29 REMAP 0 206.176.224.3:80 SOURCE=CACHE 650 STREAM 29 SENTCONNECT 40 206.176.224.3:80 650 STREAM 29 REMAP 40 206.176.224.3:80 SOURCE=EXIT 650 STREAM 29 SUCCEEDED 40 206.176.224.3:80 650 STREAM 29 CLOSED 40 206.176.224.3:80 REASON=DONE 650 CIRC 40 CLOSED desync REASON=FINISHEDNote: Sometimes you will encounter a STREAM message saying that it ended the stream before any data was received due to TORPROTOCOL error. Try finding a different Tor exit node or reconnecting to the same exit node a few times.
2.4 Being Extra Sneaky by Using Leaky Circuits
It is possible to be extra sneaky about the final exit node by using any one of the circuit nodes as an exit node (provided the node has the necessary exit policy).
First, we will need to disable automated stream to circuit assignment:
setconf __LeaveStreamsUnattached=1Next, let's use a one-hop example to display how we can manually attach outgoing streams to previously created circuits:
getinfo circuit-status 250-circuit-status= 250 OK extendcircuit 0 desync 250 EXTENDED 56 650 CIRC 56 LAUNCHED 650 CIRC 56 EXTENDED desync 650 CIRC 56 BUILT desync 650 STREAM 61 NEW 0 whatismyip.org:80 SOURCE_ADDR=127.0.0.1:59353 PURPOSE=USER attachstream 61 56 650 STREAM 61 REMAP 0 206.176.224.3:80 SOURCE=CACHE 650 STREAM 61 SENTCONNECT 56 206.176.224.3:80 250 OK 650 STREAM 61 REMAP 56 206.176.224.3:80 SOURCE=EXIT 650 STREAM 61 SUCCEEDED 56 206.176.224.3:80 650 STREAM 61 CLOSED 56 206.176.224.3:80 REASON=DONE 650 CIRC 56 CLOSED desync REASON=FINISHEDNow, let's create a new four-hop circuit.
In this case, we will exit from hop three instead of default hop four using HOP=3 parameter of the attachstream command:
extendcircuit 0 sabotage,SEC,chaoscomputerclub23,desync 250 EXTENDED 17 650 CIRC 17 LAUNCHED 650 CIRC 17 EXTENDED sabotage 650 CIRC 17 EXTENDED sabotage,SEC 650 CIRC 17 EXTENDED sabotage,SEC,chaoscomputerclub23 650 CIRC 17 EXTENDED sabotage,SEC,chaoscomputerclub23,desync 650 CIRC 17 BUILT sabotage,SEC,chaoscomputerclub23,desync 650 STREAM 11 NEW 0 whatismyip.org:80 SOURCE_ADDR=127.0.0.1:45597 PURPOSE=USER attachstream 11 17 HOP=3 650 STREAM 11 REMAP 0 206.176.224.3:80 SOURCE=CACHE 650 STREAM 11 SENTCONNECT 17 206.176.224.3:80 250 OK 650 STREAM 11 REMAP 17 206.176.224.3:80 SOURCE=EXIT 650 STREAM 11 SUCCEEDED 17 206.176.224.3:80 650 STREAM 11 CLOSED 17 206.176.224.3:80 REASON=DONEThe IP address returned by whatismyip.org is 81.169.137.209 (tor.anonymizer.ccc.de), which corresponds to the chaoscomputerclub23 exit node.
Hint: Use attach a stream to circuit 0 to let the Tor client assign it automatically.
3. Other Tricks
Below are a few more random tricks:
Get the country code for an IP address:
getinfo ip-to-country/216.66.24.2 250-ip-to-country/216.66.24.2=us 250 OKSwitch to new circuits:
signal newnymLet's redirect all CNN traffic to BBC ;)
mapaddress www.cnn.com=www.bbc.co.ukReduce Tor traffic by disabling preemptive circuit creation:
setconf __DisablePredictedCircuits=1Speed-up Tor:
setconf CircuitBuildTimeout 10Use specific exit node for a website:
mapaddress www.bbc.co.uk=www.bbc.co.uk.ephemer.exitResolve domains and IP addresses using Tor:
setevents addrmap 250 OK resolve 2600.com 650 ADDRMAP 2600.com 216.66.24.2 "2008-10-11 05:07:45" EXPIRES="2008-10-11 12:07:45" 250 OK resolve mode=reverse 216.66.24.2 250 OK 650 ADDRMAP REVERSE[216.66.24.2] phalse.2600.COM "2008-10-11 05:09:10" EXPIRES="2008-10-11 12:09:10"4. Automation
I have developed a Python script to automate circuit creation using the TorCtl library.
Using this script, you will be able to specify which countries you want to use for each hop, how many ocean and continent crossings you want to take, specify circuit sizes, and many other tweaks.
You can get it here: thesprawl.org/code/src/tor-autocircuit.tar.gz
Also, for a quick listing of Tor exit nodes to use in your custom circuits, use another script I wrote to query the exit node directory listing: thesprawl.org/code/src/tor-nodes.py
5. Conclusion
There was a lot of ground covered in this guide, but there are even more interesting hacks still out there, waiting to be discovered.
So go ahead and have some fun! Here are a few links to get you started:
- www.torproject.org/svn/trunk/doc/spec/control-spec.txt
- svn.torproject.org/svn/torctl/trunk/doc/howto.txt
Root teh moon!
Greetz to all mrlers, good folks from trin, and leet dudez of sf2600.
#!/usr/bin/python # Name : tor-nodes.py # Description: prints a list of IP addresses belonging to # tor nodes by quering TOR client. For this # script to work you must have TorCtl.py available # in the current directory. # Author : iphelix import socket import TorCtl #Connect to TOR try: s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(("localhost",9051)) c = TorCtl.Connection(s) c.authenticate() except socket.error, e: print "[!] Couldn't connect to TOR.",e print "[?] You must enable TOR control port by running" print " 'tor -controlport 9051' from the command line" print " or by editing torrc to enable control port" sys.exit(-1) #Query exit nodes orouters = c.get_network_status() for orouter in orouters: print str(orouter.ip)Code: tor-autocircuit.tar.gz
Code: tor-nodes.py