Search code examples
pythonpython-3.xtor

Multiple TOR Exit Nodes - Controller Not Working?


I'm trying to use Multiple TOR exit nodes with Selenium, and I'm trying to create a function that changes the multiple identities. However, it doesn't, and returns no error. I believe there's a problem with my code that I can't quite figure out. Perhaps the controller is failing?

(I have stderr() outputted to a file and I get nothing every time. And I've also killed each process of TOR)

Here's my code:

import socks
import socket
import subprocess
import stem.connection
import stem.socket
from selenium import webdriver
from stem.control import Controller

global requiredTorRelays
global child_pid
global relays
global driver
requiredTorRelays = math.ceil(_.MAX_FBTC_ACCOUNTS_/270)
driver = []
child_pid = []

def initTor(i):
    print("\n[+] TOR NETWORK "+str(i)+" INITIALIZING...")
    print(" - Updating Preferences...")
    ff_prof = webdriver.FirefoxProfile()

    ff_prof.set_preference( "places.history.enabled", False )
    ff_prof.set_preference( "privacy.clearOnShutdown.offlineApps", True )
    ff_prof.set_preference( "privacy.clearOnShutdown.passwords", True )
    ff_prof.set_preference( "privacy.clearOnShutdown.siteSettings", True )
    ff_prof.set_preference( "privacy.sanitize.sanitizeOnShutdown", True )
    ff_prof.set_preference( "signon.rememberSignons", False )
    ff_prof.set_preference( "network.cookie.lifetimePolicy", 2 )
    ff_prof.set_preference( "network.dns.disablePrefetch", True )
    ff_prof.set_preference( "network.http.sendRefererHeader", 0 )

    ff_prof.set_preference( "network.proxy.type", 1 )
    ff_prof.set_preference( "network.proxy.socks_version", 5 )
    ff_prof.set_preference( "network.proxy.socks", '127.0.0.1' )
    ff_prof.set_preference( "network.proxy.socks_port", 9050+i )
    ff_prof.set_preference( "network.proxy.socks_remote_dns", True )
    ff_prof.set_preference( "browser.link.open_newwindow.restriction", 1 )

    ff_prof.set_preference( "javascript.enabled", True )
    ff_prof.update_preferences()
    print(" - Opening Browser...")
    os.environ['DISPLAY'] = ':99'
    driver.extend([webdriver.Firefox(ff_prof)])

    if(i==0):
        j=''
    else:
        j=str(i)

    tor_path = _.TOR_PATH_
    DETACHED_PROCESS = 0x00000008

    print(" - Starting TOR Process...")

    tor_process = subprocess.Popen( '"'+_.TOR_PATH_+'" --RunAsDaemon 1 --CookieAuthentication 1 --HashedControlPassword "'+_.TOR_HASHED_PASS_+'" --ControlPort '+str(9060+i)+' --PidFile tor'+j+'.pid --SocksPort '+str(9050+i)+' --DataDirectory data/tor'+j, creationflags=DETACHED_PROCESS)
    child_pid.extend([tor_process.pid])
    print(" - Starting TOR Controller...")

    C_PORT=int(9060+i)

 ## Function to check how many TOR Configuration Files are present
def checkNoTorFolders():
    torCount = 0
    folders = next(os.walk("data/"))[1]
    for folder in folders:
        if(folder[0:3]=="tor"):
            torCount+=1
    return torCount

## Function to create a new TOR Configuration File
def createNewDataFolder(i):
    if(i==0):
        if(not os.path.exists('data/tor')):
            os.makedirs('data/tor')
    else:
        if(not os.path.exists('data/tor'+str(i))):
            os.makedirs('data/tor'+str(i))


## Function to create new ID
def newID(i):
    with Controller.from_port(port = 9060+int(i)) as controller:
        controller.authenticate(_.TOR_PASS_)
        controller.signal(Signal.NEWNYM)

## Main Process/Call Functions

i=0

if(int(checkNoTorFolders())<requiredTorRelays):
    print("\n[+] CREATING "+str(requiredTorRelays-int(checkNoTorFolders()))+" NEW DATA FOLDERS...")
    while(i<=requiredTorRelays-int(checkNoTorFolders())-1):
        createNewDataFolder(int(checkNoTorFolders()))
        print("- Created Data Folder: "+str(int(checkNoTorFolders())))

for x in range(0,int(checkNoTorFolders())):
    initTor(x)
    driver[x].get("http://wtfismyip.com/text")
    print(' - IP: '+driver[x].find_element_by_tag_name('pre').text)
    ip.extend(driver[x].find_element_by_tag_name('pre').text)

print("\n[+] TESTING NETWORK(S)...")

## Test Identity Changing
for limit in range(0,3):
    for i in range(0,requiredTorRelays):
        print("\n[+] RETRIEVING NEW IDENTITY ["+str(i)+"]...")
        newID(i)
        driver[i].get("http://wtfismyip.com/text")
        print(' - IP: '+driver[i].find_element_by_tag_name('pre').text)

    time.sleep(10)

input()

Solution

  • I have re-written the code, as it seems my code was just awful. I'm not sure what the problem was, however, here's the update for anyone trying to do the same:

    assert str is not bytes
    
    from lib_socks_proxy_2013_10_03 import monkey_patch as socks_proxy_monkey_patch
    
    socks_proxy_monkey_patch.monkey_patch()
    
    import io
    import re
    
    import time
    
    import stem.connection
    import stem.socket
    import stem.process 
    from stem import Signal
    from stem.control import Controller
    from stem.util import term
    
    from urllib import request as req
    from lib_socks_proxy_2013_10_03 import socks_proxy_context
    
    import config
    
    tor_process = []
    _ = config.variables
    
    def startTor(i):
        print(" - Starting TOR Process...")    
    
        tor_process.extend([stem.process.launch_tor_with_config(
            config={
                'SocksPort':str(9050+i),
                'ControlPort':str(9070+i),
                'CookieAuthentication':str(1),
                'HashedControlPassword':str(_.TOR_HASHED_PASS_),
                'DataDirectory':'data/tor'+str(i),
                'PidFile':'tor'+str(i)+'.pid',
                            },
            init_msg_handler = print_bootstrap_lines,
            )])
    
    def print_bootstrap_lines(line):
        if("Bootstrapped " in line):
            print(line)
    
    def checkIP(i):
        print("[+] Checking IP Address...")
        try:
            opener = req.build_opener()
    
            with socks_proxy_context.socks_proxy_context(proxy_address=('127.0.0.1', 9050+i)):
               res = opener.open('https://internet.yandex.com/get_full_info/', timeout=20.0)
    
            data = res.read(10000).decode()
            print(data)
        except:
            print(" - Failed.")
    
    
    def changeIP(i):
        print("[+] Changing IP Address... ["+str(i)+"]")
        with Controller.from_port(port = 9070+i) as controller:
            controller.authenticate(_.TOR_PASS_)
            controller.signal(Signal.NEWNYM)
    
    ## Test 3 nodes.
    
    if(__name__=="__main__"):
        for x in range(0,3):
            startTor(x)
            checkIP(x)
        for x in range(0,3):
            changeIP(x)
        for x in range(0,3):
            checkIP(x)
            tor_process[x].kill() 
    

    For anyone planning on using this: don't cycle the TOR servers too fast/too much as it puts strain on the network.