Pure python tor protocol implementation
Project description
Torpy
A pure-Python implementation of the Tor protocol. Torpy can be used to communicate with clearnet hosts or hidden services through the Tor Network.
Features
- No Stem or official Tor client required
- Support v2 hidden services (v2 specification)
- Support Basic and Stealth authorization protocol
- Provide simple TorHttpAdapter for requests
- Provide simple Socks5 proxy
Note: This product is produced independently from the Tor® anonymity software and carries no guarantee from The Tor Project about quality, suitability or anything else.
Console examples
There are several console utilities to test the client.
A simple HTTP/HTTPS request:
$ torpy_cli --url https://ifconfig.me --header "User-Agent" "curl/7.37.0"
Downloading new consensus from gabelmoo authority
Connecting to guard node 144.217.94.84:443 (ezrin; Tor 0.3.5.8)...
Sending: GET https://ifconfig.me
Creating new circuit #80000001 with 144.217.94.84:443 (ezrin; Tor 0.3.5.8) router...
Building 3 hops circuit...
Extending the circuit #80000001 with 95.211.147.99:9001 (RNVR217; Tor 0.3.5.7)...
Extending the circuit #80000001 with 45.33.43.215:443 (a0xo; Tor 0.3.5.8)...
Creating stream #1 attached to #80000001 circuit...
Stream #1: connecting to ('ifconfig.me', 443)
Response status: 200
> 45.33.43.215
Stream #1: closing...
Closing guard connections...
Destroy circuit #80000001
Create Socks5 proxy to relay requests via the Tor Network:
$ torpy_socks -p 1050 --hops 3
Downloading new consensus from bastet authority
Connecting to guard node 45.77.80.140:9001 (sparklingengine; Tor 0.2.9.11)...
Creating new circuit #80000001 with 45.77.80.140:9001 (sparklingengine; Tor 0.2.9.11) router...
Building 3 hops circuit...
Extending the circuit #80000001 with 185.13.39.197:443 (Neldoreth; Tor 0.3.5.8)...
Extending the circuit #80000001 with 77.247.181.163:22 (amartysen; Tor 0.3.5.8)...
Start socks proxy at 127.0.0.1:1050
...
Torpy module also has a command-line interface:
$ python3.7 -m torpy --url https://facebookcorewwwi.onion --to-file index.html
Downloading new consensus from bastet authority
Connecting to guard node 5.9.173.35:443 (killto; Tor 0.2.9.16)...
Sending: GET https://facebookcorewwwi.onion
Creating new circuit #80000001 with 5.9.173.35:443 (killto; Tor 0.2.9.16) router...
Building 3 hops circuit...
Extending the circuit #80000001 with 54.39.151.167:9001 (DeusVult; Tor 0.3.5.8)...
Extending the circuit #80000001 with 171.25.193.78:443 (DFRI4; Tor 0.3.3.9)...
Creating stream #1 attached to #80000001 circuit...
Stream #1: connecting to ('facebookcorewwwi.onion', 443)
Extending #80000001 circuit for hidden service facebookcorewwwi.onion...
Rendezvous established (CellRelayRendezvousEstablished())
Iterate over responsible dirs of the hidden service
Iterate over introduction points of the hidden service
Create circuit for hsdir
Creating new circuit #80000002 with 5.9.173.35:443 (killto; Tor 0.2.9.16) router...
Building 0 hops circuit...
Extending the circuit #80000002 with 45.77.196.39:9001 (Fractalia; Tor 0.2.9.16)...
Creating stream #2 attached to #80000002 circuit...
Stream #2: connecting to hsdir
Stream #2: closing...
Destroy circuit #80000002
Creating new circuit #80000003 with 5.9.173.35:443 (killto; Tor 0.2.9.16) router...
Building 0 hops circuit...
Extending the circuit #80000003 with 213.136.81.89:9001 (unnamed314; Tor 0.3.5.8)...
Introduced (CellRelayIntroduceAck())
Destroy circuit #80000003
Creating stream #3 attached to #80000001 circuit...
Stream #3: connecting to ('www.facebookcorewwwi.onion', 443)
Extending #80000001 circuit for hidden service facebookcorewwwi.onion...
Response status: 200
Writing to file index.html
Stream #1: closing...
Stream #3: closing...
Closing guard connections...
Destroy circuit #80000001
Usage examples
A basic example of how to send some data to a clearnet host or a hidden service:
from torpy import TorClient
hostname = 'ifconfig.me' # It's possible use onion hostname here as well
tor = TorClient()
# Choose random guard node and create 3-hops circuit
with tor.create_circuit(3) as circuit:
# Create tor stream to host
with circuit.create_stream((hostname, 80)) as stream:
# Now we can communicate with host
stream.send(b'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % hostname.encode())
recv = stream.recv(1024)
TorHttpAdapter is a convenient Tor adapter for the requests library. The following example shows the usage of TorHttpAdapter for multi-threaded HTTP requests:
from multiprocessing.pool import ThreadPool
from torpy.http.requests import tor_requests_session
with tor_requests_session() as s: # returns requests.Session() object
links = ['http://nzxj65x32vh2fkhk.onion', 'http://facebookcorewwwi.onion'] * 2
with ThreadPool(3) as pool:
pool.map(s.get, links)
For more examples see test_integration.py
Installation
pip3 install torpy
Contribute
TODO
- Implement v3 hidden services specification
- Refactor Tor cells serialization/deserialization
- More unit tests
- Rewrite the library using asyncio
- Implement onion services
License
Licensed under the Apache License, Version 2.0
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file torpy-1.0.2.tar.gz
.
File metadata
- Download URL: torpy-1.0.2.tar.gz
- Upload date:
- Size: 69.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.9.1 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.5.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 37d8d7227163062060ccfe1c84253d69499782085483a4c3a75342c10f943d79 |
|
MD5 | cfc81c5520406d90faba9c93375f16a2 |
|
BLAKE2b-256 | c3d493d0d858391a49346e7f6571402159cd334b4dcb7c189e825ee7492ffd75 |