Controller¶
Controller is the main client that connects to Tor’s control port.
It is used to send commands, read the corresponding replies and receive events from Tor.
Create and connect¶
- class aiostem.controller.Controller[source]
- classmethod from_path(path: str = '/var/run/tor/control') Controller[source]¶
Create a new controller for a local unix socket.
USE EXAMPLE:
async with Controller.from_path('/run/tor/control.sock') as controller: await controller.authenticate() ...
- Parameters:
path (
str, default:'/var/run/tor/control') – path to the unix socket on the file system.- Returns:
Controller– A controller for the target unix socket.
- classmethod from_port(host: str = '127.0.0.1', port: int = 9051) Controller[source]¶
Create a new controller for a remote TCP host/port.
USE EXAMPLE:
async with Controller.from_port('10.0.0.1', 9051) as controller: await controller.authenticate('password') ...
- Parameters:
- Returns:
Controller– A controller for the target TCP host and port.
- __init__(connector: ControlConnector) None[source]¶
Initialize a new controller from a provided
ControlConnector.Notes
- You may want to alternatively use one of the following methods:
- Parameters:
connector (
ControlConnector) – the connector to the control socket.
- async __aenter__() Self[source]¶
Enter Controller’s context, connect to the target.
- Raises:
RuntimeError – when the context has already been entered.
- Returns:
Self– A connected controller (the same exact instance).
- async __aexit__(exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) bool[source]¶
Exit the controller’s context and close the underlying socket.
Properties¶
Unauthenticated commands¶
- class aiostem.controller.Controller[source]
- async auth_challenge(nonce: bytes | str | None = None) ReplyAuthChallenge[source]¶
Start the authentication for
SAFECOOKIE.When no
nonceis provided, once is generated and provided back in the reply. While this is obviously not part of the original reply from the server, it is added to the reply structure for convenience.Warning
This method is not meant to be called by the end-user but is rather used internally by
authenticate().Note
This command can be sent while not authenticated (but only once).
- Parameters:
nonce (
bytes|str|None, default:None) – 32 random bytes (optional).- Returns:
ReplyAuthChallenge– An authentication challenge reply.
- async authenticate(password: str | None = None) ReplyAuthenticate[source]¶
Authenticate to Tor’s controller.
Note
Available authentications are provided by
protocol_info().Important
- Authentication methods are tried in the following order (when available):
NULL: authentication is automatically grantedHASHEDPASSWORD: password authentication (when a password is provided)SAFECOOKIE: proof that we can read the cookie fileCOOKIE: provide the content of the cookie file
See also
- Parameters:
password (
str|None, default:None) – Optional password for methodHASHEDPASSWORD.- Raises:
ControllerError – When no known authentication method was found.
- Returns:
ReplyAuthenticate– The authentication reply (you should check the status here).
- async protocol_info(version: int | None = None) ReplyProtocolInfo[source]¶
Get control protocol information from Tor.
This command is performed as part of the authentication process in order to find out all supported authentication methods (see
AuthMethod).The
versionis supposed to set to1but Tor currently does not care.Note
The command result is cached when unauthenticated as we can only send this command once in this situation.
- Parameters:
version (
int|None, default:None) – Protocol version to ask for when provided.- Returns:
ReplyProtocolInfo– A completed protocol info reply from Tor.
Event management¶
- aiostem.controller.EventCallbackType¶
Alias for event callbacks registered with
Controller.add_event_handler().
- class aiostem.controller.Controller[source]
- async add_event_handler(event: EventWord | EventWordInternal | str, callback: EventCallbackType) None[source]¶
Register a callback function to be called when an event message is received.
Notes
A special event
DISCONNECTis handled internally by this library and can be registered here to be notified of any disconnection from the control socket.Multiple callbacks can be set for a single event. If so, they are called in the order they were registered.
USE EXAMPLE:
def client_status_callback(event: EventStatusClient): print(event) async with Controller.from_path('/run/tor/control.sock') as controller: await controller.authenticate() await controller.add_event_handler('STATUS_CLIENT', client_status_callback) ...
- Parameters:
event (
EventWord|EventWordInternal|str) – Name of the event linked to the callback.callback (
EventCallbackType) – A function or coroutine to be called when the event occurs.
- Raises:
CommandError – When the event name does not exit.
ReplyStatusError – When the event could not be registered.
- Return type:
- async del_event_handler(event: EventWord | EventWordInternal | str, callback: EventCallbackType) None[source]¶
Unregister a previously registered callback function.
- Parameters:
event (
EventWord|EventWordInternal|str) – Name of the event linked to the callback.callback (
EventCallbackType) – A function or coroutine to be removed from the event list.
- Return type:
- async set_events(events: Set[EventWord]) ReplySetEvents[source]¶
Set the list of events that we subscribe to.
Warning
This method should not probably be called by the end-user. Please see
add_event_handler()instead.- Parameters:
- Returns:
ReplySetEvents– A simple setevents reply where only the status is relevant.
Configuration commands¶
- class aiostem.controller.Controller[source]
- async get_conf(*args: str) ReplyGetConf[source]¶
Request the value of zero or move configuration variable(s).
Note that you can request the same key multiple times, and some configuration entries can provide multiple values. When any of this happens, the result dictionary provides a
Sequenceof strings as its value.- Parameters:
args (
str) – A list of configuration variables to request.- Returns:
ReplyGetConf– A reply containing the corresponding values (when successful).
- async load_conf(text: str) ReplyLoadConf[source]¶
Upload and replace the content of a config file.
This command allows a controller to upload the text of a config file to Tor over the control port. This config file is then loaded as if it had been read from disk.
- Returns:
ReplyLoadConf– A simple reply with only a status.
- async reset_conf(items: Mapping[str, MutableSequence[int | str] | int | str | None]) ReplyResetConf[source]¶
Change or reset configuration entries on the remote server.
Notes
- Parameters:
items (
Mapping[str,MutableSequence[int|str] |int|str|None]) – a map of configuration entries to apply or reset.- Returns:
ReplyResetConf– A simple resetconf reply where only the status is relevant.
- async save_conf(*, force: bool = False) ReplySaveConf[source]¶
Instructs the server to write out its configuration options into
torrc.If
%includeis used ontorrc,SAVECONFwill not write the configuration to disk. When set, the configuration will be overwritten even if %include is used. You can find out whether this flag is needed usingconfig-can-saveconfonCommandGetInfo.- Keyword Arguments:
force – force write the configuration to disk.
- Returns:
ReplySaveConf– A simple reply with only a status.
- async set_conf(items: Mapping[str, MutableSequence[int | str] | int | str | None]) ReplySetConf[source]¶
Change configuration entries on the remote server.
- Parameters:
items (
Mapping[str,MutableSequence[int|str] |int|str|None]) – a map of new configuration entries to apply or clear.- Returns:
ReplySetConf– A simple setconf reply where only the status is relevant.
Streams and circuits¶
- class aiostem.controller.Controller[source]
- async close_circuit(circuit: int, *, if_unused: bool = False) ReplyCloseCircuit[source]¶
Tell the server to close the specified circuit.
- Parameters:
circuit (
int) – The circuit identifier to close.- Keyword Arguments:
if_unused – Close the circuit only if it is unused.
- Returns:
ReplyCloseCircuit– A simple reply where only the status is relevant.
- async extend_circuit(circuit: int, servers: Sequence[LongServerName | str], *, purpose: CircuitPurpose | str | None = None) ReplyExtendCircuit[source]¶
Extend the provided circuit to the provided servers.
- Parameters:
circuit (
int) – The circuit identifier to extend to (0for a new circuit).servers (
Sequence[LongServerName|str]) – List of servers to extend the circuit to.
- Keyword Arguments:
purpose – Optional circuit purpose.
- Returns:
ReplyExtendCircuit– A circuit reply containing the circuit number.
- async set_circuit_purpose(circuit: int, purpose: CircuitPurpose | str) ReplySetCircuitPurpose[source]¶
Change the circuit purpose.
- Parameters:
circuit (
int) – The circuit identifier to change the purpose.purpose (
CircuitPurpose|str) – New purpose for the provided circuit.
- Returns:
ReplySetCircuitPurpose– A simple reply with only a status.
- async attach_stream(stream: int, circuit: int, *, hop: int | None = None) ReplyAttachStream[source]¶
Inform the server that the specified stream should be associated with a circuit.
- Parameters:
- Keyword Arguments:
hop – When specified, Tor choose the HopNumth hop in the circuit as the exit node.
- Returns:
ReplyAttachStream– A simple reply where only the status is relevant.
- async close_stream(stream: int, reason: StreamCloseReasonInt) ReplyCloseStream[source]¶
Tell the server to close the specified stream.
- Parameters:
stream (
int) – The stream identifier to close.reason (
StreamCloseReasonInt) – The provided reason why this stream should be closed.
- Returns:
ReplyCloseStream– A simple reply where only the status is relevant.
- async redirect_stream(stream: int, address: AnyHost, *, port: int | None = None) ReplyRedirectStream[source]¶
Tell the server to change the exit address on the specified stream.
- Parameters:
- Keyword Arguments:
port – Optional port to redirect the stream to.
- Returns:
ReplyRedirectStream– A simple reply where only the status is relevant.
- async post_descriptor(descriptor: str, *, cache: bool | None = None, purpose: DescriptorPurpose | None = None) ReplyPostDescriptor[source]¶
Inform the server about a new router descriptor.
- Parameters:
descriptor (
str) – The router descriptor content.- Keyword Arguments:
cache – Whether to cache the provided descriptor internally.
purpose – The purpose of the descriptor (default is
GENERAL).
- Returns:
ReplyPostDescriptor– A simple reply where only the status is relevant.
- async drop_guards() ReplyDropGuards[source]¶
Tell the server to drop all guard nodes.
Warning
Do not invoke this command lightly; it can increase vulnerability to tracking attacks over time.
- Returns:
ReplyDropGuards– A simple drop-guards reply where only the status is relevant.
- async drop_timeouts() ReplyDropTimeouts[source]¶
Tells the server to drop all circuit build times.
Warning
Do not invoke this command lightly; it can increase vulnerability to tracking attacks over time.
Note
Tor also emits the
BUILDTIMEOUT_SET RESETevent right after the reply.- Returns:
ReplyDropTimeouts– A simple drop-timeouts reply where only the status is relevant.
Control commands¶
- class aiostem.controller.Controller[source]
- async drop_ownership() ReplyDropOwnership[source]¶
Relinquish ownership of this control connection.
Hint
This ownership can be taken using
take_ownership().- Returns:
ReplyDropOwnership– A simple drop-ownership reply where only the status is relevant.
- async take_ownership() ReplyTakeOwnership[source]¶
Instructs Tor to shut down when this control connection is closed.
Hint
This ownership can be dropped with
drop_ownership().- Returns:
ReplyTakeOwnership– A simple take-ownership reply where only the status is relevant.
- async map_address(addresses: Mapping[AnyHost, AnyHost]) ReplyMapAddress[source]¶
Map provided addresses with their replacement.
The client tells the server that future SOCKS requests for connections to any original address provided here should be replaced with a connection to the specified replacement address.
The client may decline to provide a replacement address and instead provide a special address. This means that the server should choose the original address itself.
For IPv4:
0.0.0.0For IPv6:
::0For hostname:
.
Mapping values can be read using
get_info()withaddress-mappings/control.- Parameters:
addresses (
Mapping[AnyHost,AnyHost]) – A map of addresses to remap on socks requests.- Returns:
ReplyMapAddress– A list of individual replies for each map request.Note that some values can be rejected and others can be accepted, which means that you should check each individual value.
- async resolve(addresses: Sequence[AnyHost], *, reverse: bool = False) ReplyResolve[source]¶
Launch a remote hostname lookup request for every specified request.
Note
The result is not provided along with the reply here but can be caught using the
ADDRMAP.- Parameters:
addresses (
Sequence[AnyHost]) – List of addresses to launch a resolve request for.- Keyword Arguments:
reverse – Whether to perform a reverse DNS lookup.
- Returns:
ReplyResolve– A simple resolve reply where only the status is relevant.
- async get_info(*args: str) ReplyGetInfo[source]¶
Request for Tor daemon information.
Note that you can request the same key multiple times. When this happens, the result dictionary provides a
Sequenceof strings as its value.- Parameters:
args (
str) – A list of information data to request.- Returns:
ReplyGetInfo– A reply containing the corresponding values (when successful).
- async signal(signal: Signal | str) ReplySignal[source]¶
Send a signal to the controller.
- Parameters:
- Returns:
ReplySignal– A simple signal reply where only the status is relevant.
Generic request¶
- class aiostem.controller.Controller[source]
- async request(command: Command) Message[source]¶
Send any kind of command to the controller.
This method is the underlying call of any other command.
It can be used to send custom subclass of
Command, and get the rawMessagecorresponding to the response. ThisMessagecan then be parsed by an appropriateReply.Important
A single command can run at any time due to an internal lock.
- Parameters:
command (
Command) – The command we want to send to Tor.- Raises:
ControllerError – When the controller is not connected.
- Returns:
Message– The corresponding reply message from the remote daemon.