Package: torpy
TorpyA pure python Tor client implementation of the Tor protocol.
Torpy can be used to communicate with clearnet hosts or hidden services through theTor Network.FeaturesNo Stem or official Tor client requiredSupport v2 hidden services (v2 specification)SupportBasicandStealthauthorization protocolProvide simpleTorHttpAdapterforrequestslibraryProvide simple urllibtor_openerfor making requests without any dependenciesProvide simple Socks5 proxyDonationIf you find this project interesting, you can send someBitcoinsto address:16mF9TYaJKkb9eGbZ5jGuJbodTF3mYvcRFNoteThis product is produced independently from the Tor® anonymity software and carries no guarantee fromThe Tor Projectabout quality, suitability or anything else.Console examplesThere are several console utilities to test the client.A simple HTTP/HTTPS request:$torpy_cli--urlhttps://ifconfig.me--header"User-Agent""curl/7.37.0"LoadingcachedNetworkStatusDocumentfromTorCacheDirStorage:.local/share/torpy/network_status
LoadingcachedDirKeyCertificateListfromTorCacheDirStorage:.local/share/torpy/dir_key_certificates
Connectingtoguardnode141.98.136.79:443(Poseidon;Tor0.4.3.6)...(TorClient)Sending:GEThttps://ifconfig.me
Creatingnewcircuit#80000001 with 141.98.136.79:443 (Poseidon; Tor 0.4.3.6) router......
Building3hopscircuit...
Extendingthecircuit#80000001 with 109.70.100.23:443 (kren; Tor 0.4.4.5)......
Extendingthecircuit#80000001 with 199.249.230.175:443 (Quintex86; Tor 0.4.4.5)......
Stream#4: creating attached to #80000001 circuit...Stream#4: connecting to ('ifconfig.me', 443)Stream#4: connected (remote ip '216.239.36.21')Stream#4: closing (state = Connected)...Stream#4: remote disconnected (reason = DONE)Responsestatus:200Stream#4: closing (state = Closed)...Stream#4: closed alreadyClosingguardconnections(TorClient)...
Destroycircuit#80000001Closingguardconnections(Routerdescriptordownloader)...
Destroycircuit#80000002>199.249.230.175Create Socks5 proxy to relay requests via the Tor Network:$ torpy_socks -p 1050 --hops 3
Loading cached NetworkStatusDocument from TorCacheDirStorage: .local/share/torpy/network_status
Connecting to guard node 89.142.75.60:9001 (spongebobness; Tor 0.3.5.8)...
Creating new circuit #80000001 with 89.142.75.60:9001 (spongebobness; Tor 0.3.5.8) router...
Building 3 hops circuit...
Extending the circuit #80000001 with 185.248.143.42:9001 (torciusv; Tor 0.3.5.8)...
Extending the circuit #80000001 with 158.174.122.199:9005 (che1; Tor 0.4.1.6)...
Start socks proxy at 127.0.0.1:1050
...Torpy module also has a command-line interface:$python3.7-mtorpy--urlhttps://facebookcorewwwi.onion--to-fileindex.html
LoadingcachedNetworkStatusDocumentfromTorCacheDirStorage:.local/share/torpy/network_status
Connectingtoguardnode185.2.31.8:443(cx10TorServer;Tor0.4.0.5)...
Sending:GEThttps://facebookcorewwwi.onion
Creatingnewcircuit#80000001 with 185.2.31.8:443 (cx10TorServer; Tor 0.4.0.5) router...Building3hopscircuit...
Extendingthecircuit#80000001 with 144.172.71.110:8447 (TonyBamanaboni; Tor 0.4.1.5)...Extendingthecircuit#80000001 with 179.43.134.154:9001 (father; Tor 0.4.0.5)...Creatingstream#1 attached to #80000001 circuit...Stream#1: connecting to ('facebookcorewwwi.onion', 443)Extending#80000001 circuit for hidden service facebookcorewwwi.onion...Rendezvousestablished(CellRelayRendezvousEstablished())Iterateoverresponsibledirsofthehiddenservice
Iterateoverintroductionpointsofthehiddenservice
Createcircuitforhsdir
Creatingnewcircuit#80000002 with 185.2.31.8:443 (cx10TorServer; Tor 0.4.0.5) router...Building0hopscircuit...
Extendingthecircuit#80000002 with 132.248.241.5:9001 (toritounam; Tor 0.3.5.8)...Creatingstream#2 attached to #80000002 circuit...Stream#2: connecting to hsdirStream#2: closing...Destroycircuit#80000002Creatingnewcircuit#80000003 with 185.2.31.8:443 (cx10TorServer; Tor 0.4.0.5) router...Building0hopscircuit...
Extendingthecircuit#80000003 with 88.198.17.248:8443 (bauruine31; Tor 0.4.1.5)...Introduced(CellRelayIntroduceAck())Destroycircuit#80000003Creatingstream#3 attached to #80000001 circuit...Stream#3: connecting to ('www.facebookcorewwwi.onion', 443)Extending#80000001 circuit for hidden service facebookcorewwwi.onion...Responsestatus:200Writingtofileindex.html
Stream#1: closing...Stream#3: closing...Closingguardconnections...
Destroycircuit#80000001Usage examplesA basic example of how to send some data to a clearnet host or a hidden service:fromtorpyimportTorClienthostname='ifconfig.me'# It's possible use onion hostname here as wellwithTorClient()astor:# Choose random guard node and create 3-hops circuitwithtor.create_circuit(3)ascircuit:# Create tor stream to hostwithcircuit.create_stream((hostname,80))asstream:# Now we can communicate with hoststream.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 therequests library.
The following example shows the usage of TorHttpAdapter for multi-threaded HTTP requests:frommultiprocessing.poolimportThreadPoolfromtorpy.http.requestsimporttor_requests_sessionwithtor_requests_session()ass:# returns requests.Session() objectlinks=['http://nzxj65x32vh2fkhk.onion','http://facebookcorewwwi.onion']*2withThreadPool(3)aspool:pool.map(s.get,links)For more examples seetest_integration.pyInstallationJustpip3 install torpyOr for using TorHttpAdapter with requests library you need install extras:pip3 install torpy[requests]ContributeUse ItCode review is appreciatedOpenIssue, sendPRTODOImplement v3 hidden servicesspecificationRefactor Tor cells serialization/deserializationMore unit testsRewrite the library using asyncioImplement onion servicesLicenseLicensed under the Apache License, Version 2.0ReferencesOfficialTorclientPycepaTorPylleTinyTorC++ Windows only implementationMini-torNice Java implementationOrchid