Tracking and Changing Live Tor State

TorState

class txtorcon.TorState(protocol, bootstrap=True)

This tracks the current state of Tor using a TorControlProtocol.

On setup it first queries the initial state of streams and circuits. It then asks for updates via the listeners. It requires an ITorControlProtocol instance. The control protocol doesn’t need to be bootstrapped yet. The Deferred .post_boostrap is driggered when the TorState instance is fully ready to go. The easiest way is to use the helper method txtorcon.build_tor_connection(). For details, see the implementation of that.

You may add an txtorcon.interface.IStreamAttacher to provide a custom mapping for Strams to Circuits (by default Tor picks by itself).

This is also a good example of the various listeners, and acts as an txtorcon.interface.ICircuitContainer and txtorcon.interface.IRouterContainer.

Variables:

DO_NOT_ATTACH – Constant to return from an IAttacher indicating you don’t want to attach this stream at all.

Circuit

class txtorcon.Circuit(routercontainer)

Used by txtorcon.TorState to represent one of Tor’s circuits.

This is kept up-to-date by the :class`txtorcon.TorState` that owns it, and individual circuits can be listened to for updates (or listen to every one using txtorcon.TorState.add_circuit_listener())

Variables:
  • path – contains a list of txtorcon.Router objects representing the path this Circuit takes. Mostly this will be 3 or 4 routers long. Note that internally Tor uses single-hop paths for some things. See also the purpose instance-variable.

  • streams – contains a list of Stream objects representing all streams currently attached to this circuit.

  • state

    contains a string from Tor describing the current state of the stream. From control-spec.txt section 4.1.1, these are:

    • LAUNCHED: circuit ID assigned to new circuit

    • BUILT: all hops finished, can now accept streams

    • EXTENDED: one more hop has been completed

    • FAILED: circuit closed (was not built)

    • CLOSED: circuit closed (was built)

  • purpose

    The reason this circuit was built. For most purposes, you’ll want to look at GENERAL circuits only. Values can currently be one of (but see control-spec.txt 4.1.1):

    • GENERAL

    • HS_CLIENT_INTRO

    • HS_CLIENT_REND

    • HS_SERVICE_INTRO

    • HS_SERVICE_REND

    • TESTING

    • CONTROLLER

  • id – The ID of this circuit, a number (or None if unset).

Parameters:

routercontainer – should implement txtorcon.interface.IRouterContainer.

Stream

class txtorcon.Stream(circuitcontainer, addrmap=None)

Represents an active stream in Tor’s state (txtorcon.TorState).

Variables:
  • circuit – Streams will generally be attached to circuits pretty quickly. If they are attached, circuit will be a txtorcon.Circuit instance or None if this stream isn’t yet attached to a circuit.

  • state

    Tor’s idea of the stream’s state, one of:
    • NEW: New request to connect

    • NEWRESOLVE: New request to resolve an address

    • REMAP: Address re-mapped to another

    • SENTCONNECT: Sent a connect cell along a circuit

    • SENTRESOLVE: Sent a resolve cell along a circuit

    • SUCCEEDED: Received a reply; stream established

    • FAILED: Stream failed and not retriable

    • CLOSED: Stream closed

    • DETACHED: Detached from circuit; still retriable

  • target_host – Something like www.example.com – the host the stream is destined for.

  • target_port – The port the stream will exit to.

  • target_addr – Target address, looked up (usually) by Tor (e.g. 127.0.0.1).

  • id – The ID of this stream, a number (or None if unset).

Parameters:

circuitcontainer – an object which implements interface.ICircuitContainer

Router

class txtorcon.Router(controller)

Represents a Tor Router, including location.

The controller you pass in is really only used to do get_info calls for ip-to-country/IP in case the txtorcon.util.NetLocation stuff fails to find a country.

After an .update() call, the id_hex attribute contains a hex-encoded long hash (suitable, for example, to use in a GETINFO ns/id/* call).

After setting the policy property you may call accepts_port() to find out if the router will accept a given port. This works with the reject or accept based policies.