01. Connection¶
There are several ways to connect to Tor’s control port, depending on the daemon configuration.
Tor configuration is out of this scope, to find out how to configure the control port, please
take a look at the torrc manpage and specifically the ControlPort option.
This service typically listens on port TCP/9051 or on a local UNIX socket (on Linux).
TCP port connection¶
The following code shows how to connect to the control port through the TCP local port:
1#!/usr/bin/env python
2
3import asyncio
4import os
5from aiostem import Controller
6
7async def main():
8 host = os.environ.get('AIOSTEM_HOST', 'localhost')
9 port = os.environ.get('AIOSTEM_PORT', 9051)
10
11 print(f'[>] Connecting to {host} on port {port}')
12 async with Controller.from_port(host, int(port)) as ctrl:
13 reply = await ctrl.protocol_info()
14 reply.raise_for_status()
15 print(f'[+] Connected to Tor v{reply.data.tor_version}')
16
17if __name__ == '__main__':
18 asyncio.run(main())
This code uses Controller.from_port(), which is a helper method to create a new client
(a controller) from pair of host and port.
This is what the output of this script looks like:
$ python examples/connect_from_port.py
[>] Connecting to localhost on port 9051
[+] Connected to Tor v0.4.8.13
Socket file connection¶
The following code is an alternative version connecting through a local socket file:
1#!/usr/bin/env python
2
3import asyncio
4import os
5from aiostem import Controller
6
7async def main():
8 path = os.environ.get('AIOSTEM_PATH', '/run/tor/control')
9 print(f'[>] Connecting to {path}')
10 async with Controller.from_path(path) as ctrl:
11 reply = await ctrl.protocol_info()
12 reply.raise_for_status()
13 print(f'[+] Connected to Tor v{reply.data.tor_version}')
14
15if __name__ == '__main__':
16 asyncio.run(main())
This code uses Controller.from_path(), which is another helper method used to
create a controller for a socket file. This code also uses Controller.protocol_info()
which is one of the rare commands you can run while not authenticated.
This is intended here to get the version of the remote Tor daemon.
This is what the output of this script looks like:
$ python examples/connect_from_socket.py
[>] Connecting to /run/tor/control
[+] Connected to Tor v0.4.8.13
When available, you should probably prefer this version since local sockets have less overhead over a full TCP connection.
Advanced connection¶
Controller.from_port() and Controller.from_path() are only wrappers using
classes derived from ControlConnector.
Users can build new sub-classes for custom uses, such as providing support for TLS or any
kind of proxy. A Controller only requires the connector to provide
connect() which returns a tuple of
asyncio.StreamReader and asyncio.StreamWriter.
The following code connects to the TCP port using ControlConnectorPort:
1#!/usr/bin/env python
2
3import asyncio
4import os
5from aiostem.connector import ControlConnectorPort
6from aiostem import Controller
7
8async def main():
9 host = os.environ.get('AIOSTEM_HOST', 'localhost')
10 port = int(os.environ.get('AIOSTEM_PORT', 9051))
11 connector = ControlConnectorPort(host, port)
12
13 print(f'[>] Connecting to {host} on port {port} (with a connector)')
14 async with Controller(connector) as ctrl:
15 reply = await ctrl.protocol_info()
16 reply.raise_for_status()
17 print(f'[+] Connected to Tor v{reply.data.tor_version}')
18
19if __name__ == '__main__':
20 asyncio.run(main())