I put this example together using this STEM Tutorial. It shows the use of
controller.set_conf('__LeaveStreamsUnattached', '1')
to make your own circuits, attach a stream, and make a request using the requesocks module (which is just the requests module with SOCKS5 support). Hope this helps.
import StringIO
import time
import stem.control
import requesocks
import random
EXIT_FINGERPRINT = '379FB450010D17078B3766C2273303C358C3A442'
SOCKS_PORT = 9150
CONTROL_PORT = 9151
CONNECTION_TIMEOUT = 30 # timeout before we give up on a circuit
def get(url):
"""
Uses pycurl to fetch a site using the proxy on the SOCKS_PORT.
"""
session = requesocks.session()
session.proxies = {
'http': 'socks5://127.0.0.1:%s' % SOCKS_PORT,
'https': 'socks5://127.0.0.1:%s' % SOCKS_PORT,
}
try:
response = session.get(url)
return response
except:
print("Could not connect")
def connect(controller, path, url):
""" Build a custom 2 hop circuit using the path fingerprint
and the hard coded exit node """
circuit_id = controller.new_circuit(path, await_build = True)
def attach_stream(stream):
if stream.status == 'NEW':
controller.attach_stream(stream.id, circuit_id)
controller.add_event_listener(attach_stream, stem.control.EventType.STREAM)
try:
controller.set_conf('__LeaveStreamsUnattached', '1') # leave stream management to us
check_page = get(url)
return check_page
finally:
# Stop listening for attach stream events and stop controlling streams
controller.remove_event_listener(attach_stream)
controller.reset_conf('__LeaveStreamsUnattached')
with stem.control.Controller.from_port(port=CONTROL_PORT) as controller:
controller.authenticate()
relay_fingerprints = [desc.fingerprint for desc in controller.get_network_statuses()]
fingerprint = random.choice(relay_fingerprints)
try:
url = "http://www.torproject.org"
response = connect(controller, [fingerprint, EXIT_FINGERPRINT], url)
if response.status_code == 200:
print("Connection to %s successful using node %s" % (url, fingerprint))
except Exception as exc:
print('%s => %s' % (fingerprint, exc))