def gen_controller(): connect_method = os.environ.get('connectmethod', 'port') if connect_method == 'port': return Controller.from_port(port=os.environ.get('port', 9051)) elif connect_method == 'socket': return Controller.from_socket_file(path=os.environ.get('socket', '/var/run/tor/control')) else: print("env.connectmethod contains an invalid value. Please specify either 'port' or 'socket'.", file=sys.stderr) sys.exit(-1)
def _on_connect(self): try: self._control = Controller.from_port() except SocketError: try: self._control = Controller.from_socket_file() except SocketError: self._status_icon.set_tooltip_text('Failed to initialize stem') return True self._control.add_status_listener(self._on_status) self._status_icon.set_tooltip_text('Stem: Authenticating') GLib.timeout_add_seconds(1, self._on_auth) return False
def start_hidden_service(port): # come up with a hidden service directory name hidserv_dir_rand = random_string(8) if get_platform() == "Windows": if 'Temp' in os.environ: temp = os.environ['Temp'].replace('\\', '/') else: temp = 'C:/tmp' hidserv_dir = "{0}/onionshare_{1}".format(temp, hidserv_dir_rand) else: hidserv_dir = "/tmp/onionshare_{0}".format(hidserv_dir_rand) # connect to the tor controlport controlports = [9051, 9151] controller = False for controlport in controlports: try: controller = Controller.from_port(port=controlport) except SocketError: pass if not controller: raise NoTor(translated("cant_connect_ctrlport").format(controlports)) controller.authenticate() # set up hidden service controller.set_options([ ('HiddenServiceDir', hidserv_dir), ('HiddenServicePort', '80 127.0.0.1:{0}'.format(port)) ]) # figure out the .onion hostname hostname_file = '{0}/hostname'.format(hidserv_dir) onion_host = open(hostname_file, 'r').read().strip() return onion_host
def _getController(controlAddr="127.0.0.1", controlPort=9051, passphrase=None, incorrectPasswordMsg="", printError=True): """ Custom handler for establishing a stem connection (... needs an overhaul). """ controller = None try: chroot = util.torTools.getConn().getPathPrefix() controller = Controller.from_port(controlAddr, controlPort) try: controller.authenticate(password = passphrase, chroot_path = chroot) except stem.connection.MissingPassword: try: passphrase = getpass.getpass("Controller password: "******"Unable to authenticate: password incorrect": # provide a warning that the provided password didn't work, then try # again prompting for the user to enter it print incorrectPasswordMsg return _getController(controlAddr, controlPort) elif printError: print exc return None
def newId(): global changeID, password with Controller.from_port(port = 9051) as controller: controller.authenticate(password = password) controller.signal(Signal.NEWNYM) time.sleep(3) changeID = 0
def restartTor(self): """Get new tor session""" with Controller.from_port(port=9051) as controller: controller.authenticate("Den135790") controller.signal(Signal.NEWNYM) self.clean() self.logger.debug("success restart tor")
def main(): print 'Opening log file, further output will be there.' # redirect output to file, https://stackoverflow.com/questions/7152762 f = file('TorBrowser/OnioNS/stem.log', 'w') sys.stdout = f # get current time of day now = datetime.datetime.now() try: # open main controller controller = Controller.from_port(port = 9151) except stem.SocketError: sys.exit("[err] The Tor Browser is not running. Cannot continue") controller.authenticate() controller.set_options({ '__LeaveStreamsUnattached': '1' }) print '[%d:%d | notice] Successfully connected to the Tor Browser.' % (now.minute, now.second) sys.stdout.flush() event_handler = functools.partial(handle_event, controller) controller.add_event_listener(event_handler, EventType.STREAM) print '[%d:%d | debug ] Now monitoring stream connections.' % (now.minute, now.second) sys.stdout.flush() try: time.sleep(60 * 60 * 24 * 365) #basically, wait indefinitely except KeyboardInterrupt: print ''
def main(): parser = argparse.ArgumentParser(description= "Parse the log_dir location for tor bw logs and generate graphs.") parser.add_argument("log_dir", help="Location of tor-log-bw.py output logs.") args = parser.parse_args() log_dir = args.log_dir """Create a log file and setup the event handler for BW events""" with Controller.from_port(port = 9051) as controller: controller.authenticate() """ TODO This try except could be eliminated and just straight up call log_bw """ log_file = os.path.join(log_dir, "tor_bw.log") create_timed_rotating_log(log_file) logger = logging.getLogger("Rotating Log") logger.info("Starting BW Event Logging") try: # This makes curses initialize and call draw_bandwidth_graph() with a # reference to the screen, followed by additional arguments (in this # case just the controller). log_bandwidth(controller) except KeyboardInterrupt: pass # the user hit ctrl+c
def renew_connection(): with Controller.from_port(port = 9151) as controller: controller.authenticate(); print (controller.get_newnym_wait()) time.sleep(controller.get_newnym_wait()); controller.signal(Signal.NEWNYM); return;
def get_exit(is_running): """ Get list of exit node from stem """ if is_running: try: with Controller.from_port(port = 6969) as controller: controller.authenticate() exit = {'count': [], 'fingerprint': [], 'nickname': [], 'ipaddress': []} count = -1 for circ in controller.get_circuits(): if circ.status != stem.CircStatus.BUILT: continue exit_fp, exit_nickname = circ.path[-1] exit_desc = controller.get_network_status(exit_fp, None) exit_address = exit_desc.address if exit_desc else 'unknown' count += 1 exit['count'].append(count) exit['fingerprint'].append(exit_fp) exit['nickname'].append(exit_nickname) exit['ipaddress'].append(exit_address) return exit except stem.SocketError as exc: notify("TorTP", "[!] Unable to connect to port 6969 (%s)" % exc) sys.exit(1) else: notify("TorTP", "[!] Tor is not running") sys.exit(0)
def enable_tordns(): """ Use Tor ControlPort for enable TorDNS """ with Controller.from_port(port = 9051) as controller: controller.authenticate() controller.set_options({"DNSPort": "9053", "DNSListenAddress": "127.0.0.1", "AutomapHostsOnResolve": "1", "AutomapHostsSuffixes": ".exit,.onion"})
def handle_timeout(process, onion, identity_lock): # halt the main thread while we grab a new identity identity_lock.clear() # kill the onionscan process try: process.kill() print("[!!!] Killed the onionscan process.") except: pass # Now we switch TOR identities to make sure we have a good connection with Controller.from_port(port=9051) as torcontrol: # authenticate to our local TOR controller torcontrol.authenticate(PASSWD) # send the signal for a new identity torcontrol.signal(Signal.NEWNYM) # wait for the new identity to be initialized time.sleep(torcontrol.get_newnym_wait()) print("[!!!] Switched TOR identities.") # push the onion back on to the list session_onions.append(onion) random.shuffle(session_onions) # allow the main thread to resume executing identity_lock.set() return
def renew(self): '''Signal TOR for a new connection thanks http://stackoverflow.com/questions/30286293/ make-requests-using-python-over-tor and https://gist.github.com/ KhepryQuixote/46cf4f3b999d7f658853''' SLEEPSECS = 1 SESSION = self.Session() old_ip = check_ip(SESSION) # we don't want a CCC because it closes tor process by default :) with Controller.from_port(port=self.CONTROL_PORT) \ as controller: controller.authenticate(password=self.PASSWORD) controller.signal(Signal.NEWNYM) new_ip = check_ip(SESSION) seconds = 0 while old_ip == new_ip: # sleep this thread for the specified duration sleep(SLEEPSECS) # track the elapsed seconds seconds += SLEEPSECS # obtain the current IP address new_ip = check_ip(SESSION) # signal that the program is still awaiting a different IP address print("%d seconds elapsed awaiting a different IP address." % seconds)
def checkTor(): if not controller.isAlive(): print "tor controller was dead, now trying to restart it" try: controller = Controller.from_port() controller.authenticate() except Exception as e: print e print "tor is not letting us authenticate, is it configured correctly and running?" exit() print "successfully opened control connection to tor" #TODO here and elsewhere we should change from the get_conf/set_options #interface to the create_ephemeral_hidden_service/ #remove_ephemeral_hidden_service/list_ephemeral_hidden_services #that way we can also put the key and hostname in config and not have to #worry about setting up /var/lib/tor/hidden_service if controller.get_conf("HiddenServiceDir") is None: print "tor was not configure to provide a hidden service, now configuring" try: controller.set_options([ ("HiddenServiceDir", get_hidden_svc_dir()), ("HiddenServicePort", "80 %s:%s" % (host, str(port))) ]) except Exception as e: print "unable to create hidden service" print e quit()
def launch_tor(country): print(term.format("Starting Tor with exit node in %s:" % (country), term.Attr.BOLD)) try: tor_process = stem.process.launch_tor_with_config( config = { 'SocksPort': str(SOCKS_PORT), 'ControlPort': str(CONTROL_PORT), 'ExitNodes': "{"+country+"}", }, timeout = 30, # init_msg_handler = print_bootstrap_lines, ) # finally: # print("test") except OSError: print("Timeout when trying to find relay....") return 0 # Add listener with Controller.from_port(port = CONTROL_PORT) as controller: controller.authenticate() stream_listener = functools.partial(stream_event, controller) controller.add_event_listener(stream_listener, EventType.STREAM) return tor_process
def change_ipadress(passphrase="your_TORsoftware_password", sleep=1) : with Controller.from_port(port = 9051) as controller: controller.authenticate(passphrase) controller.signal(Signal.NEWNYM) #we wait here but you can eventually skip this part or set it in place to #gain controle over time. time.sleep(sleep)
def __init__(self, control_host = _CONTROL_HOST, control_port = _CONTROL_PORT, sock = None, authenticator = _AUTHENTICATOR): """Initialize the CtlUtil object, connect to Stem.""" self.sock = sock if not sock: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.control_host = control_host self.control_port = control_port self.authenticator = authenticator # Try to connect try: self.sock.connect((self.control_host, self.control_port)) except: errormsg = "Could not connect to Tor control port.\n" + \ "Is Tor running on %s with its control port opened on %s?" %\ (control_host, control_port) logging.error(errormsg) raise self.control = Controller.from_port(port = self.control_port) # Authenticate connection self.control.authenticate(config.authenticator)
def judgeActive(onion_addr): # conn = get_connection() proc = os.getpid() print('{0} doubled to {1} by process id: {2}'.format( onion_addr, '*', proc)) with Controller.from_port(port=9053) as controller: controller.authenticate("111111") try: # cur = conn.cursor()###### hs_descriptor = controller.get_hidden_service_descriptor(onion_addr,await_result = True) # print(hs_descriptor) sql = 'update ONION SET status = 1 WHERE onion_addr = "%s" ' % (onion_addr[:-6]) # print(sql) # cur.execute(sql)####### print(onion_addr + " is alive from process " + str(proc) + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) except stem.DescriptorUnavailable: # print("Descriptor not found, the hidden service may be offline.") sql = 'update ONION SET status = -1 WHERE onion_addr = "%s" ' % (onion_addr[:-6]) # print(sql) # cur.execute(sql)######### print(onion_addr + " is died from process " + str(proc) + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) except Exception,e: print '------------------------------------' print("timeout is found" + onion_addr + str(e) + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) print ("-----------------------------") try:#This place is more important that using the try catch make the timeout come realize and useable,so why controller.close() # conn.commit()####### # cur.close()######### # conn.close()######## except Exception,e: print "excepiton found" + str(e)
def enable_torproxy(): """ Use Tor ControlPort for enable Tor Transparent Proxy """ with Controller.from_port(port = 9051) as controller: controller.authenticate() controller.set_options({"VirtualAddrNetwork": "10.192.0.0/10", "TransPort": "9040", "TransListenAddress": "127.0.0.1","AvoidDiskWrites": "1", "WarnUnsafeSocks": "1"})
def init_tor(socks_port=None, control_port=None): """ Initiates a tor connection. :param socks_port: local port socket where tor will listen to requests (configurable in tor.rc). :type socks_port: int :param control_port: local port where tor will listen to control requests (configurable in tor.rc). :type control_port: int :return: a tor process and a controller of the process. :rtype: process, controller """ if socks_port is None: socks_port = SOCKS_PORT if control_port is None: control_port = CONTROL_PORT process = stem.process.launch_tor_with_config( config={ 'SocksPort': str(socks_port), 'ControlPort': str(control_port) }, init_msg_handler=print_bootstrap_lines, timeout=60, take_ownership=True) controller = Controller.from_port() controller.authenticate() return process, controller
def connect(self): self.connected = False self.dir = os.path.join(settings.config_path, 'tor') connected = False for port in (9831, 9151): try: self.controller = Controller.from_port('127.0.0.1', port) connected = True break except stem.SocketError: pass if not connected: if not self.daemon: logger.debug("start own tor process") self.daemon = TorDaemon() logger.debug("daemon %s", self.daemon) return self.connect() logger.debug("Failed to connect to system or own tor process.") return False try: self.controller.authenticate() except stem.connection.MissingPassword: logger.debug("TOR requires a password") return False except stem.connection.PasswordAuthFailed: logger.debug("invalid tor password") return False self.controller.add_event_listener(self.event_listener) self.controller.add_status_listener(self.status_listener) self.connected = True self.socks_port = int(self.controller.get_conf('SocksPort').split(' ')[0]) self.publish() state.online = self.is_online() return True
def determine_exits(self, state): global can_exit if options.exits is not None: exits = map(lambda l: in_consensus(state, l), options.exits) exits = filter(lambda r: r is not None, exits) else: exits = state.routers_by_hash.values() exits = filter(lambda r: "exit" in r.flags, exits) # get descriptors from stem con = Controller.from_port(port = self.options.control_port) con.authenticate() descriptors = {} for desc in con.get_server_descriptors(): descriptors[desc.fingerprint] = desc con.close() can_exit_func = functools.partial(can_exit, descriptors, warn=not options.num_exits) exits = map(can_exit_func, exits) exits = filter(lambda t: t[0] is not None, exits) if options.num_exits is not None: if options.num_exits > len(exits): print "Not enough exits. Giving you all I've got." else: exits = random.sample(exits, options.num_exits) return exits
def __init__(self, transparent_torification=False): self.transparent_torification = transparent_torification # files and dirs to delete on shutdown self.cleanup_filenames = [] self.service_id = None # connect to the tor controlport found_tor = False self.c = None ports = [9151, 9153, 9051] for port in ports: try: self.c = Controller.from_port(port=port) self.c.authenticate() found_tor = True break except SocketError: pass if not found_tor: raise NoTor(strings._("cant_connect_ctrlport").format(str(ports))) # do the versions of stem and tor that I'm using support ephemeral hidden services? tor_version = self.c.get_version().version_str list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None) self.supports_ephemeral = callable(list_ephemeral_hidden_services) and tor_version >= '0.2.7.1'
def main(): """ The scanner's entry point. """ stats = Statistics() args = parseCmdArgs() logger.debug("Command line arguments: %s" % str(args)) torProc = bootstrapTor() torCtrl = Controller.from_port(port = const.TOR_CONTROL_PORT) stem.connection.authenticate_none(torCtrl) # Redirect Tor's logging to work around the following problem: # https://bugs.torproject.org/9862 logger.debug("Redirecting Tor's logging to /dev/null.") torCtrl.set_conf("Log", "err file /dev/null") # We already have the current consensus, so we don't need additional # descriptors or the streams fetching them. torCtrl.set_conf("FetchServerDescriptors", "0") for moduleName in args.module: runModule(moduleName, args, torCtrl, stats) return 0
def tutorial_example(): from stem.control import Controller with Controller.from_port(control_port = 9051) as controller: controller.authenticate() for desc in controller.get_network_statuses(): print "found relay %s (%s)" % (desc.nickname, desc.fingerprint)
def _register_event_handler(self): self._control = Controller.from_port(address=self.control_address, port=self.control_port) if self.control_password: self._control.authenticate(password=self.control_password) self._control.add_event_listener(lambda e: self._handle_event(e), EventType.BW) self._handler_active = True
def renew_connection(self): with Controller.from_port(port = 9051) as controller: controller.authenticate('natalie') controller.signal(Signal.NEWNYM) self.logger.info('*'*50) self.logger.info('\t'*6+'Renew TOR IP: %s'%self.request(self.ip_url)) self.logger.info('*'*50)
def renew_connection(password): """Renews TOR session :param password: new password """ with Controller.from_port(port=9051) as controller: controller.authenticate(password=password) controller.signal(Signal.NEWNYM)
def newId(): global changeIDInPregress changeIDInPregress = True with Controller.from_port(port = 9051) as controller: controller.authenticate(password = password) controller.signal(Signal.NEWNYM) time.sleep(3) changeIDInPregress = False
def renew(): #will turn off proxy temporarily to renew tor routing -not sure why this is necessary but it wasnt working through the proxy and easier to add here than to use proxy with indiv. requests. #turn off proxy socket.socket = default_socket #reset tor routing with Controller.from_port(port=9051) as controller: controller.authenticate("account") controller.signal(Signal.NEWNYM) #turn proxy back on socket.socket = socks.socksocket
def change_identity(): with Controller.from_port(port=9051) as c: c.authenticate(password=password) c.signal(Signal.NEWNYM)
def connect(self, custom_settings=False, config=False, tor_status_update_func=None, connect_timeout=120): self.common.log('Onion', 'connect') # Either use settings that are passed in, or use them from common if custom_settings: self.settings = custom_settings elif config: self.common.load_settings(config) self.settings = self.common.settings else: self.common.load_settings() self.settings = self.common.settings strings.load_strings(self.common) # The Tor controller self.c = None if self.settings.get('connection_type') == 'bundled': if not self.bundle_tor_supported: raise BundledTorNotSupported(strings._('settings_error_bundled_tor_not_supported')) # Create a torrc for this session self.tor_data_directory = tempfile.TemporaryDirectory(dir=self.common.build_data_dir()) self.common.log('Onion', 'connect', 'tor_data_directory={}'.format(self.tor_data_directory.name)) # Create the torrc with open(self.common.get_resource_path('torrc_template')) as f: torrc_template = f.read() self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie') try: self.tor_socks_port = self.common.get_available_port(1000, 65535) except: raise OSError(strings._('no_available_port')) self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') if self.common.platform == 'Windows' or self.common.platform == "Darwin": # Windows doesn't support unix sockets, so it must use a network port. # macOS can't use unix sockets either because socket filenames are limited to # 100 chars, and the macOS sandbox forces us to put the socket file in a place # with a really long path. torrc_template += 'ControlPort {{control_port}}\n' try: self.tor_control_port = self.common.get_available_port(1000, 65535) except: raise OSError(strings._('no_available_port')) self.tor_control_socket = None else: # Linux and BSD can use unix sockets torrc_template += 'ControlSocket {{control_socket}}\n' self.tor_control_port = None self.tor_control_socket = os.path.join(self.tor_data_directory.name, 'control_socket') torrc_template = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name) torrc_template = torrc_template.replace('{{control_port}}', str(self.tor_control_port)) torrc_template = torrc_template.replace('{{control_socket}}', str(self.tor_control_socket)) torrc_template = torrc_template.replace('{{cookie_auth_file}}', self.tor_cookie_auth_file) torrc_template = torrc_template.replace('{{geo_ip_file}}', self.tor_geo_ip_file_path) torrc_template = torrc_template.replace('{{geo_ipv6_file}}', self.tor_geo_ipv6_file_path) torrc_template = torrc_template.replace('{{socks_port}}', str(self.tor_socks_port)) with open(self.tor_torrc, 'w') as f: f.write(torrc_template) # Bridge support if self.settings.get('tor_bridges_use_obfs4'): f.write('ClientTransportPlugin obfs4 exec {}\n'.format(self.obfs4proxy_file_path)) with open(self.common.get_resource_path('torrc_template-obfs4')) as o: for line in o: f.write(line) elif self.settings.get('tor_bridges_use_meek_lite_azure'): f.write('ClientTransportPlugin meek_lite exec {}\n'.format(self.obfs4proxy_file_path)) with open(self.common.get_resource_path('torrc_template-meek_lite_azure')) as o: for line in o: f.write(line) if self.settings.get('tor_bridges_use_custom_bridges'): if 'obfs4' in self.settings.get('tor_bridges_use_custom_bridges'): f.write('ClientTransportPlugin obfs4 exec {}\n'.format(self.obfs4proxy_file_path)) elif 'meek_lite' in self.settings.get('tor_bridges_use_custom_bridges'): f.write('ClientTransportPlugin meek_lite exec {}\n'.format(self.obfs4proxy_file_path)) f.write(self.settings.get('tor_bridges_use_custom_bridges')) f.write('\nUseBridges 1') # Execute a tor subprocess start_ts = time.time() if self.common.platform == 'Windows': # In Windows, hide console window when opening tor.exe subprocess startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW self.tor_proc = subprocess.Popen([self.tor_path, '-f', self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo) else: self.tor_proc = subprocess.Popen([self.tor_path, '-f', self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Wait for the tor controller to start time.sleep(2) # Connect to the controller try: if self.common.platform == 'Windows' or self.common.platform == "Darwin": self.c = Controller.from_port(port=self.tor_control_port) self.c.authenticate() else: self.c = Controller.from_socket_file(path=self.tor_control_socket) self.c.authenticate() except Exception as e: raise BundledTorBroken(strings._('settings_error_bundled_tor_broken').format(e.args[0])) while True: try: res = self.c.get_info("status/bootstrap-phase") except SocketClosed: raise BundledTorCanceled() res_parts = shlex.split(res) progress = res_parts[2].split('=')[1] summary = res_parts[4].split('=')[1] # "\033[K" clears the rest of the line print("Connecting to the Tor network: {}% - {}{}".format(progress, summary, "\033[K"), end="\r") if callable(tor_status_update_func): if not tor_status_update_func(progress, summary): # If the dialog was canceled, stop connecting to Tor self.common.log('Onion', 'connect', 'tor_status_update_func returned false, canceling connecting to Tor') print() return False if summary == 'Done': print("") break time.sleep(0.2) # If using bridges, it might take a bit longer to connect to Tor if self.settings.get('tor_bridges_use_custom_bridges') or \ self.settings.get('tor_bridges_use_obfs4') or \ self.settings.get('tor_bridges_use_meek_lite_azure'): # Only override timeout if a custom timeout has not been passed in if connect_timeout == 120: connect_timeout = 150 if time.time() - start_ts > connect_timeout: print("") try: self.tor_proc.terminate() raise BundledTorTimeout(strings._('settings_error_bundled_tor_timeout')) except FileNotFoundError: pass elif self.settings.get('connection_type') == 'automatic': # Automatically try to guess the right way to connect to Tor Browser # Try connecting to control port found_tor = False # If the TOR_CONTROL_PORT environment variable is set, use that env_port = os.environ.get('TOR_CONTROL_PORT') if env_port: try: self.c = Controller.from_port(port=int(env_port)) found_tor = True except: pass else: # Otherwise, try default ports for Tor Browser, Tor Messenger, and system tor try: ports = [9151, 9153, 9051] for port in ports: self.c = Controller.from_port(port=port) found_tor = True except: pass # If this still didn't work, try guessing the default socket file path socket_file_path = '' if not found_tor: try: if self.common.platform == 'Darwin': socket_file_path = os.path.expanduser('~/Library/Application Support/TorBrowser-Data/Tor/control.socket') self.c = Controller.from_socket_file(path=socket_file_path) found_tor = True except: pass # If connecting to default control ports failed, so let's try # guessing the socket file name next if not found_tor: try: if self.common.platform == 'Linux' or self.common.platform == 'BSD': socket_file_path = '/run/user/{}/Tor/control.socket'.format(os.geteuid()) elif self.common.platform == 'Darwin': socket_file_path = '/run/user/{}/Tor/control.socket'.format(os.geteuid()) elif self.common.platform == 'Windows': # Windows doesn't support unix sockets raise TorErrorAutomatic(strings._('settings_error_automatic')) self.c = Controller.from_socket_file(path=socket_file_path) except: raise TorErrorAutomatic(strings._('settings_error_automatic')) # Try authenticating try: self.c.authenticate() except: raise TorErrorAutomatic(strings._('settings_error_automatic')) else: # Use specific settings to connect to tor # Try connecting try: if self.settings.get('connection_type') == 'control_port': self.c = Controller.from_port(address=self.settings.get('control_port_address'), port=self.settings.get('control_port_port')) elif self.settings.get('connection_type') == 'socket_file': self.c = Controller.from_socket_file(path=self.settings.get('socket_file_path')) else: raise TorErrorInvalidSetting(strings._("settings_error_unknown")) except: if self.settings.get('connection_type') == 'control_port': raise TorErrorSocketPort(strings._("settings_error_socket_port").format(self.settings.get('control_port_address'), self.settings.get('control_port_port'))) else: raise TorErrorSocketFile(strings._("settings_error_socket_file").format(self.settings.get('socket_file_path'))) # Try authenticating try: if self.settings.get('auth_type') == 'no_auth': self.c.authenticate() elif self.settings.get('auth_type') == 'password': self.c.authenticate(self.settings.get('auth_password')) else: raise TorErrorInvalidSetting(strings._("settings_error_unknown")) except MissingPassword: raise TorErrorMissingPassword(strings._('settings_error_missing_password')) except UnreadableCookieFile: raise TorErrorUnreadableCookieFile(strings._('settings_error_unreadable_cookie_file')) except AuthenticationFailure: raise TorErrorAuthError(strings._('settings_error_auth').format(self.settings.get('control_port_address'), self.settings.get('control_port_port'))) # If we made it this far, we should be connected to Tor self.connected_to_tor = True # Get the tor version self.tor_version = self.c.get_version().version_str self.common.log('Onion', 'connect', 'Connected to tor {}'.format(self.tor_version)) # Do the versions of stem and tor that I'm using support ephemeral onion services? list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None) self.supports_ephemeral = callable(list_ephemeral_hidden_services) and self.tor_version >= '0.2.7.1' # Do the versions of stem and tor that I'm using support stealth onion services? try: res = self.c.create_ephemeral_hidden_service({1:1}, basic_auth={'onionshare':None}, await_publication=False) tmp_service_id = res.service_id self.c.remove_ephemeral_hidden_service(tmp_service_id) self.supports_stealth = True except: # ephemeral stealth onion services are not supported self.supports_stealth = False # Does this version of Tor support next-gen ('v3') onions? # Note, this is the version of Tor where this bug was fixed: # https://trac.torproject.org/projects/tor/ticket/28619 self.supports_v3_onions = self.tor_version >= Version('0.3.5.7')
def main(): """ Entry point when invoked over the command line. """ setproctitle('onionbalance') args = parse_cmd_args().parse_args() config_file_options = settings.parse_config_file(args.config) # Update global configuration with options specified in the config file for setting in dir(config): if setting.isupper() and config_file_options.get(setting): setattr(config, setting, config_file_options.get(setting)) # Override the log level if specified on the command line. if args.verbosity: config.LOG_LEVEL = args.verbosity.upper() # Write log file if configured in environment variable or config file if config.LOG_LOCATION: log.setup_file_logger(config.LOG_LOCATION) logger.setLevel(logging.__dict__[config.LOG_LEVEL.upper()]) # Create a connection to the Tor unix domain control socket or control port try: tor_socket = (args.socket or config.TOR_CONTROL_SOCKET) tor_address = (args.ip or config.TOR_ADDRESS) tor_port = (args.port or config.TOR_PORT) try: controller = Controller.from_socket_file(path=tor_socket) logger.debug( "Successfully connected to the Tor control socket " "%s.", tor_socket) except stem.SocketError: logger.debug("Unable to connect to the Tor control socket %s.", tor_socket) controller = Controller.from_port(address=tor_address, port=tor_port) logger.debug("Successfully connected to the Tor control port.") except stem.SocketError as exc: logger.error("Unable to connect to Tor control socket or port: %s", exc) sys.exit(1) try: controller.authenticate(password=config.TOR_CONTROL_PASSWORD) except stem.connection.AuthenticationFailure as exc: logger.error( "Unable to authenticate on the Tor control connection: " "%s", exc) sys.exit(1) else: logger.debug("Successfully authenticated on the Tor control " "connection.") status_socket = status.StatusSocket(config.STATUS_SOCKET_LOCATION) eventhandler.SignalHandler(controller, status_socket) # Disable no-member due to bug with "Instance of 'Enum' has no * member" # pylint: disable=no-member # Check that the Tor client supports the HSPOST control port command if not controller.get_version() >= stem.version.Requirement.HSPOST: logger.error( "A Tor version >= %s is required. You may need to " "compile Tor from source or install a package from " "the experimental Tor repository.", stem.version.Requirement.HSPOST) sys.exit(1) # Load the keys and config for each onion service settings.initialize_services(controller, config_file_options.get('services')) # Finished parsing all the config file. handler = eventhandler.EventHandler() controller.add_event_listener(handler.new_status, EventType.STATUS_GENERAL) controller.add_event_listener(handler.new_desc, EventType.HS_DESC) controller.add_event_listener(handler.new_desc_content, EventType.HS_DESC_CONTENT) # Schedule descriptor fetch and upload events scheduler.add_job(config.REFRESH_INTERVAL, fetch_instance_descriptors, controller) scheduler.add_job(config.PUBLISH_CHECK_INTERVAL, publish_all_descriptors) # Run initial fetch of HS instance descriptors scheduler.run_all(delay_seconds=config.INITIAL_DELAY) # Begin main loop to poll for HS descriptors scheduler.run_forever() return 0
class TestControl(unittest.TestCase): def setUp(self): socket = stem.socket.ControlSocket() with patch('stem.control.Controller.add_event_listener', Mock()): self.controller = Controller(socket) @patch('stem.control.Controller.get_info') def test_get_version(self, get_info_mock): """ Exercises the get_version() method. """ try: # Use one version for first check. version_2_1 = '0.2.1.32' version_2_1_object = stem.version.Version(version_2_1) get_info_mock.return_value = version_2_1 # Return a version with a cold cache. self.assertEqual(version_2_1_object, self.controller.get_version()) # Use a different version for second check. version_2_2 = '0.2.2.39' version_2_2_object = stem.version.Version(version_2_2) get_info_mock.return_value = version_2_2 # Return a version with a hot cache, so it will be the old version. self.assertEqual(version_2_1_object, self.controller.get_version()) # Turn off caching. self.controller._is_caching_enabled = False # Return a version without caching, so it will be the new version. self.assertEqual(version_2_2_object, self.controller.get_version()) # Raise an exception in the get_info() call. get_info_mock.side_effect = InvalidArguments # Get a default value when the call fails. self.assertEqual( 'default returned', self.controller.get_version(default = 'default returned') ) # No default value, accept the error. self.assertRaises(InvalidArguments, self.controller.get_version) # Give a bad version. The stem.version.Version ValueError should bubble up. version_A_42 = '0.A.42.spam' get_info_mock.return_value = version_A_42 get_info_mock.side_effect = None self.assertRaises(ValueError, self.controller.get_version) finally: # Turn caching back on before we leave. self.controller._is_caching_enabled = True @patch('stem.control.Controller.get_info') @patch('stem.control.Controller.get_conf') def test_get_exit_policy(self, get_conf_mock, get_info_mock): """ Exercises the get_exit_policy() method. """ get_conf_mock.side_effect = lambda param, **kwargs: { 'ExitPolicyRejectPrivate': '1', 'ExitPolicy': ['accept *:80, accept *:443', 'accept 43.5.5.5,reject *:22'], }[param] get_info_mock.side_effect = lambda param, default = None: { 'address': '123.45.67.89', 'exit-policy/default': 'reject *:25,reject *:119,reject *:135-139,reject *:445,reject *:563,reject *:1214,reject *:4661-4666,reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*', }[param] expected = ExitPolicy( 'reject 0.0.0.0/8:*', # private entries 'reject 169.254.0.0/16:*', 'reject 127.0.0.0/8:*', 'reject 192.168.0.0/16:*', 'reject 10.0.0.0/8:*', 'reject 172.16.0.0/12:*', 'reject 123.45.67.89:*', # relay's public address 'accept *:80', # finally we get to our ExitPolicy 'accept *:443', 'accept 43.5.5.5:*', 'reject *:22', 'reject *:25', # default policy 'reject *:119', 'reject *:135-139', 'reject *:445', 'reject *:563', 'reject *:1214', 'reject *:4661-4666', 'reject *:6346-6429', 'reject *:6699', 'reject *:6881-6999', 'accept *:*', ) self.assertEqual(expected, self.controller.get_exit_policy()) @patch('stem.control.Controller.get_info') @patch('stem.control.Controller.get_conf') def test_get_ports(self, get_conf_mock, get_info_mock): """ Exercises the get_ports() and get_listeners() methods. """ # Exercise as an old version of tor that doesn't support the 'GETINFO # net/listeners/*' options. get_info_mock.side_effect = InvalidArguments get_conf_mock.side_effect = lambda param, **kwargs: { 'ControlPort': '9050', 'ControlListenAddress': ['127.0.0.1'], }[param] self.assertEqual([('127.0.0.1', 9050)], self.controller.get_listeners(Listener.CONTROL)) self.assertEqual([9050], self.controller.get_ports(Listener.CONTROL)) # non-local addresss get_conf_mock.side_effect = lambda param, **kwargs: { 'ControlPort': '9050', 'ControlListenAddress': ['27.4.4.1'], }[param] self.assertEqual([('27.4.4.1', 9050)], self.controller.get_listeners(Listener.CONTROL)) self.assertEqual([], self.controller.get_ports(Listener.CONTROL)) # Exercise via the GETINFO option. get_info_mock.side_effect = None get_info_mock.return_value = '"127.0.0.1:1112" "127.0.0.1:1114"' self.assertEqual( [('127.0.0.1', 1112), ('127.0.0.1', 1114)], self.controller.get_listeners(Listener.CONTROL) ) self.assertEqual([1112, 1114], self.controller.get_ports(Listener.CONTROL)) # unix socket file get_info_mock.return_value = '"unix:/tmp/tor/socket"' self.assertEqual([], self.controller.get_listeners(Listener.CONTROL)) self.assertEqual([], self.controller.get_ports(Listener.CONTROL)) @patch('stem.control.Controller.get_info') @patch('stem.control.Controller.get_conf') def test_get_socks_listeners_old(self, get_conf_mock, get_info_mock): """ Exercises the get_socks_listeners() method as though talking to an old tor instance. """ # An old tor raises stem.InvalidArguments for get_info about socks, but # get_socks_listeners should work anyway. get_info_mock.side_effect = InvalidArguments get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '9050', 'SocksListenAddress': ['127.0.0.1'], }[param] self.assertEqual([('127.0.0.1', 9050)], self.controller.get_socks_listeners()) # Again, an old tor, but SocksListenAddress overrides the port number. get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '9050', 'SocksListenAddress': ['127.0.0.1:1112'], }[param] self.assertEqual([('127.0.0.1', 1112)], self.controller.get_socks_listeners()) # Again, an old tor, but multiple listeners get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '9050', 'SocksListenAddress': ['127.0.0.1:1112', '127.0.0.1:1114'], }[param] self.assertEqual([('127.0.0.1', 1112), ('127.0.0.1', 1114)], self.controller.get_socks_listeners()) # Again, an old tor, but no SOCKS listeners get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '0', 'SocksListenAddress': [], }[param] self.assertEqual([], self.controller.get_socks_listeners()) # Where tor provides invalid ports or addresses get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': 'blarg', 'SocksListenAddress': ['127.0.0.1'], }[param] self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '0', 'SocksListenAddress': ['127.0.0.1:abc'], }[param] self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) get_conf_mock.side_effect = lambda param, **kwargs: { 'SocksPort': '40', 'SocksListenAddress': ['500.0.0.1'], }[param] self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) @patch('stem.control.Controller.get_info') def test_get_socks_listeners_new(self, get_info_mock): """ Exercises the get_socks_listeners() method as if talking to a newer tor instance. """ # multiple SOCKS listeners get_info_mock.return_value = '"127.0.0.1:1112" "127.0.0.1:1114"' self.assertEqual( [('127.0.0.1', 1112), ('127.0.0.1', 1114)], self.controller.get_socks_listeners() ) # no SOCKS listeners get_info_mock.return_value = '' self.assertEqual([], self.controller.get_socks_listeners()) # check where GETINFO provides malformed content invalid_responses = ( '"127.0.0.1"', # address only '"1112"', # port only '"5127.0.0.1:1112"', # invlaid address '"127.0.0.1:991112"', # invalid port ) for response in invalid_responses: get_info_mock.return_value = response self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) @patch('stem.connection.get_protocolinfo') def test_get_protocolinfo(self, get_protocolinfo_mock): """ Exercises the get_protocolinfo() method. """ # use the handy mocked protocolinfo response get_protocolinfo_mock.return_value = mocking.get_protocolinfo_response() # compare the str representation of these object, because the class # does not have, nor need, a direct comparison operator self.assertEqual( str(mocking.get_protocolinfo_response()), str(self.controller.get_protocolinfo()) ) # raise an exception in the stem.connection.get_protocolinfo() call get_protocolinfo_mock.side_effect = ProtocolError # get a default value when the call fails self.assertEqual( 'default returned', self.controller.get_protocolinfo(default = 'default returned') ) # no default value, accept the error self.assertRaises(ProtocolError, self.controller.get_protocolinfo) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = False)) def test_get_user_remote(self): """ Exercise the get_user() method for a non-local socket. """ self.assertRaises(ValueError, self.controller.get_user) self.assertEqual(123, self.controller.get_user(123)) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = True)) @patch('stem.control.Controller.get_info', Mock(return_value = 'atagar')) def test_get_user_by_getinfo(self): """ Exercise the get_user() resolution via its getinfo option. """ self.assertEqual('atagar', self.controller.get_user()) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = True)) @patch('stem.util.system.get_pid_by_name', Mock(return_value = 432)) @patch('stem.util.system.get_user', Mock(return_value = 'atagar')) def test_get_user_by_system(self): """ Exercise the get_user() resolution via the system module. """ self.assertEqual('atagar', self.controller.get_user()) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = False)) def test_get_pid_remote(self): """ Exercise the get_pid() method for a non-local socket. """ self.assertRaises(ValueError, self.controller.get_pid) self.assertEqual(123, self.controller.get_pid(123)) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = True)) @patch('stem.control.Controller.get_info', Mock(return_value = '321')) def test_get_pid_by_getinfo(self): """ Exercise the get_pid() resolution via its getinfo option. """ self.assertEqual(321, self.controller.get_pid()) @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = True)) @patch('stem.control.Controller.get_conf') @patch('stem.control.open', create = True) def test_get_pid_by_pid_file(self, open_mock, get_conf_mock): """ Exercise the get_pid() resolution via a PidFile. """ get_conf_mock.return_value = '/tmp/pid_file' open_mock.return_value = io.BytesIO(b'432') self.assertEqual(432, self.controller.get_pid()) open_mock.assert_called_once_with('/tmp/pid_file') @patch('stem.socket.ControlSocket.is_localhost', Mock(return_value = True)) @patch('stem.util.system.get_pid_by_name', Mock(return_value = 432)) def test_get_pid_by_name(self): """ Exercise the get_pid() resolution via the process name. """ self.assertEqual(432, self.controller.get_pid()) @patch('stem.control.Controller.get_info') def test_get_network_status(self, get_info_mock): """ Exercises the get_network_status() method. """ # build a single router status entry nickname = 'Beaver' fingerprint = '/96bKo4soysolMgKn5Hex2nyFSY' desc = 'r %s %s u5lTXJKGsLKufRLnSyVqT7TdGYw 2012-12-30 22:02:49 77.223.43.54 9001 0\ns Fast Named Running Stable Valid\nw Bandwidth=75' % (nickname, fingerprint) router = stem.descriptor.router_status_entry.RouterStatusEntryV3(desc) # always return the same router status entry get_info_mock.return_value = desc # pretend to get the router status entry with its name self.assertEqual(router, self.controller.get_network_status(nickname)) # pretend to get the router status entry with its fingerprint hex_fingerprint = stem.descriptor.router_status_entry._base64_to_hex(fingerprint, False) self.assertEqual(router, self.controller.get_network_status(hex_fingerprint)) # mangle hex fingerprint and try again hex_fingerprint = hex_fingerprint[2:] self.assertRaises(ValueError, self.controller.get_network_status, hex_fingerprint) # raise an exception in the get_info() call get_info_mock.side_effect = InvalidArguments # get a default value when the call fails self.assertEqual( 'default returned', self.controller.get_network_status(nickname, default = 'default returned') ) # no default value, accept the error self.assertRaises(InvalidArguments, self.controller.get_network_status, nickname) @patch('stem.control.Controller.is_authenticated', Mock(return_value = True)) @patch('stem.control.Controller._attach_listeners', Mock(return_value = ([], []))) @patch('stem.control.Controller.get_version') def test_event_listening(self, get_version_mock): """ Exercises the add_event_listener and remove_event_listener methods. """ # set up for failure to create any events get_version_mock.return_value = stem.version.Version('0.1.0.14') self.assertRaises(InvalidRequest, self.controller.add_event_listener, Mock(), EventType.BW) # set up to only fail newer events get_version_mock.return_value = stem.version.Version('0.2.0.35') # EventType.BW is one of the earliest events self.controller.add_event_listener(Mock(), EventType.BW) # EventType.SIGNAL was added in tor version 0.2.3.1-alpha self.assertRaises(InvalidRequest, self.controller.add_event_listener, Mock(), EventType.SIGNAL) def test_get_streams(self): """ Exercises the get_streams() method. """ # get a list of fake, but good looking, streams valid_streams = ( ('1', 'NEW', '4', '10.10.10.1:80'), ('2', 'SUCCEEDED', '4', '10.10.10.1:80'), ('3', 'SUCCEEDED', '4', '10.10.10.1:80') ) response = ''.join(['%s\r\n' % ' '.join(entry) for entry in valid_streams]) with patch('stem.control.Controller.get_info', Mock(return_value = response)): streams = self.controller.get_streams() self.assertEqual(len(valid_streams), len(streams)) for index, stream in enumerate(streams): self.assertEqual(valid_streams[index][0], stream.id) self.assertEqual(valid_streams[index][1], stream.status) self.assertEqual(valid_streams[index][2], stream.circ_id) self.assertEqual(valid_streams[index][3], stream.target) def test_attach_stream(self): """ Exercises the attach_stream() method. """ # Response when the stream is in a state where it can't be attached (for # instance, it's already open). response = stem.response.ControlMessage.from_str('555 Connection is not managed by controller.\r\n') with patch('stem.control.Controller.msg', Mock(return_value = response)): self.assertRaises(UnsatisfiableRequest, self.controller.attach_stream, 'stream_id', 'circ_id') def test_parse_circ_path(self): """ Exercises the _parse_circ_path() helper function. """ # empty input self.assertEqual([], _parse_circ_path(None)) self.assertEqual([], _parse_circ_path('')) # check the pydoc examples pydoc_examples = { '$999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz': [('999A226EBED397F331B612FE1E4CFAE5C1F201BA', 'piyaz')], '$E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone,PrivacyRepublic14': [ ('E57A476CD4DFBD99B4EE52A100A58610AD6E80B9', None), (None, 'hamburgerphone'), (None, 'PrivacyRepublic14'), ], } for test_input, expected in pydoc_examples.items(): self.assertEqual(expected, _parse_circ_path(test_input)) # exercise with some invalid inputs malformed_inputs = [ '=piyaz', # no fingerprint '999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz', # fingerprint missing prefix '$999A226EBED397F331B612FE1E4CFAE5C1F201BAA=piyaz', # fingerprint too long '$999A226EBED397F331B612FE1E4CFAE5C1F201B=piyaz', # fingerprint too short '$999A226EBED397F331B612FE1E4CFAE5C1F201Bz=piyaz', # invalid character in fingerprint '$999A226EBED397F331B612FE1E4CFAE5C1F201BA=', # no nickname ] for test_input in malformed_inputs: self.assertRaises(ProtocolError, _parse_circ_path, test_input) @patch('stem.control.Controller.get_version') def test_drop_guards(self, get_version_mock): """ Exercises the drop_guards() method. """ get_version_mock.return_value = stem.version.Version('0.1.0.14') self.assertRaises(UnsatisfiableRequest, self.controller.drop_guards) with patch('stem.control.Controller.msg', Mock(return_value = None)): get_version_mock.return_value = stem.version.Version('0.2.5.2') self.controller.drop_guards()
def change_tor_ip(): with Controller.from_port(port=9051) as controller: controller.authenticate(password=tor_password) controller.signal(Signal.NEWNYM)
from random import randint from random import shuffle from time import sleep from urllib.request import Request from urllib.request import urlopen from fake_useragent import UserAgent import os import sqlite3 from fake_useragent import UserAgent import shutil from stem import Signal from stem.control import Controller import socket import socks controller = Controller.from_port(port=9051) controller.authenticate() def connectTor(): socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 , "127.0.0.1", 9050) socket.socket = socks.socksocket def renew_tor(): controller.signal(Signal.NEWNYM) def showmyip(): url = "http://www.showmyip.gr/" r = requests.Session() page = r.get(url) soup = BeautifulSoup(page.content, "lxml") try:
def changeEndpoint(): with Controller.from_port(port=9051) as controller: controller.authenticate() controller.signal(Signal.NEWNYM)
def renew_connection(): with Controller.from_port(port=9051) as controller: controller.authenticate(password='******') controller.signal(Signal.NEWNYM) controller.close()
def connect( self, custom_settings=None, config=None, tor_status_update_func=None, connect_timeout=120, local_only=False, ): if local_only: self.common.log("Onion", "connect", "--local-only, so skip trying to connect") return self.common.log("Onion", "connect") # Either use settings that are passed in, or use them from common if custom_settings: self.settings = custom_settings elif config: self.common.load_settings(config) self.settings = self.common.settings else: self.common.load_settings() self.settings = self.common.settings # The Tor controller self.c = None if self.settings.get("connection_type") == "bundled": # Create a torrc for this session if self.use_tmp_dir: self.tor_data_directory = tempfile.TemporaryDirectory( dir=self.common.build_tmp_dir()) self.tor_data_directory_name = self.tor_data_directory.name else: self.tor_data_directory_name = self.common.build_tor_dir() self.common.log( "Onion", "connect", f"tor_data_directory_name={self.tor_data_directory_name}", ) # Create the torrc with open(self.common.get_resource_path("torrc_template")) as f: torrc_template = f.read() self.tor_cookie_auth_file = os.path.join( self.tor_data_directory_name, "cookie") try: self.tor_socks_port = self.common.get_available_port( 1000, 65535) except: print("OnionShare port not available") raise PortNotAvailable() self.tor_torrc = os.path.join(self.tor_data_directory_name, "torrc") # If there is an existing OnionShare tor process, kill it for proc in psutil.process_iter(["pid", "name", "username"]): try: cmdline = proc.cmdline() if (cmdline[0] == self.tor_path and cmdline[1] == "-f" and cmdline[2] == self.tor_torrc): self.common.log( "Onion", "connect", "found a stale tor process, killing it", ) proc.terminate() proc.wait() break except: pass if self.common.platform == "Windows" or self.common.platform == "Darwin": # Windows doesn't support unix sockets, so it must use a network port. # macOS can't use unix sockets either because socket filenames are limited to # 100 chars, and the macOS sandbox forces us to put the socket file in a place # with a really long path. torrc_template += "ControlPort {{control_port}}\n" try: self.tor_control_port = self.common.get_available_port( 1000, 65535) except: print("OnionShare port not available") raise PortNotAvailable() self.tor_control_socket = None else: # Linux and BSD can use unix sockets torrc_template += "ControlSocket {{control_socket}}\n" self.tor_control_port = None self.tor_control_socket = os.path.join( self.tor_data_directory_name, "control_socket") torrc_template = torrc_template.replace( "{{data_directory}}", self.tor_data_directory_name) torrc_template = torrc_template.replace("{{control_port}}", str(self.tor_control_port)) torrc_template = torrc_template.replace( "{{control_socket}}", str(self.tor_control_socket)) torrc_template = torrc_template.replace("{{cookie_auth_file}}", self.tor_cookie_auth_file) torrc_template = torrc_template.replace("{{geo_ip_file}}", self.tor_geo_ip_file_path) torrc_template = torrc_template.replace( "{{geo_ipv6_file}}", self.tor_geo_ipv6_file_path) torrc_template = torrc_template.replace("{{socks_port}}", str(self.tor_socks_port)) with open(self.tor_torrc, "w") as f: f.write(torrc_template) # Bridge support if self.settings.get("tor_bridges_use_obfs4"): f.write( f"ClientTransportPlugin obfs4 exec {self.obfs4proxy_file_path}\n" ) with open( self.common.get_resource_path( "torrc_template-obfs4")) as o: for line in o: f.write(line) elif self.settings.get("tor_bridges_use_meek_lite_azure"): f.write( f"ClientTransportPlugin meek_lite exec {self.obfs4proxy_file_path}\n" ) with open( self.common.get_resource_path( "torrc_template-meek_lite_azure")) as o: for line in o: f.write(line) if self.settings.get("tor_bridges_use_custom_bridges"): if "obfs4" in self.settings.get( "tor_bridges_use_custom_bridges"): f.write( f"ClientTransportPlugin obfs4 exec {self.obfs4proxy_file_path}\n" ) elif "meek_lite" in self.settings.get( "tor_bridges_use_custom_bridges"): f.write( f"ClientTransportPlugin meek_lite exec {self.obfs4proxy_file_path}\n" ) f.write( self.settings.get("tor_bridges_use_custom_bridges")) f.write("\nUseBridges 1") # Execute a tor subprocess start_ts = time.time() if self.common.platform == "Windows": # In Windows, hide console window when opening tor.exe subprocess startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW self.tor_proc = subprocess.Popen( [self.tor_path, "-f", self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo, ) else: self.tor_proc = subprocess.Popen( [self.tor_path, "-f", self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Wait for the tor controller to start time.sleep(2) # Connect to the controller try: if (self.common.platform == "Windows" or self.common.platform == "Darwin"): self.c = Controller.from_port(port=self.tor_control_port) self.c.authenticate() else: self.c = Controller.from_socket_file( path=self.tor_control_socket) self.c.authenticate() except Exception as e: print("OnionShare could not connect to Tor:\n{}".format( e.args[0])) raise BundledTorBroken(e.args[0]) while True: try: res = self.c.get_info("status/bootstrap-phase") except SocketClosed: raise BundledTorCanceled() res_parts = shlex.split(res) progress = res_parts[2].split("=")[1] summary = res_parts[4].split("=")[1] # "\033[K" clears the rest of the line print( f"\rConnecting to the Tor network: {progress}% - {summary}\033[K", end="", ) if callable(tor_status_update_func): if not tor_status_update_func(progress, summary): # If the dialog was canceled, stop connecting to Tor self.common.log( "Onion", "connect", "tor_status_update_func returned false, canceling connecting to Tor", ) print() return False if summary == "Done": print("") break time.sleep(0.2) # If using bridges, it might take a bit longer to connect to Tor if (self.settings.get("tor_bridges_use_custom_bridges") or self.settings.get("tor_bridges_use_obfs4") or self.settings.get("tor_bridges_use_meek_lite_azure")): # Only override timeout if a custom timeout has not been passed in if connect_timeout == 120: connect_timeout = 150 if time.time() - start_ts > connect_timeout: print("") try: self.tor_proc.terminate() print( "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?" ) raise BundledTorTimeout() except FileNotFoundError: pass elif self.settings.get("connection_type") == "automatic": # Automatically try to guess the right way to connect to Tor Browser automatic_error = "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" # Try connecting to control port found_tor = False # If the TOR_CONTROL_PORT environment variable is set, use that env_port = os.environ.get("TOR_CONTROL_PORT") if env_port: try: self.c = Controller.from_port(port=int(env_port)) found_tor = True except: pass else: # Otherwise, try default ports for Tor Browser, Tor Messenger, and system tor try: ports = [9151, 9153, 9051] for port in ports: self.c = Controller.from_port(port=port) found_tor = True except: pass # If this still didn't work, try guessing the default socket file path socket_file_path = "" if not found_tor: try: if self.common.platform == "Darwin": socket_file_path = os.path.expanduser( "~/Library/Application Support/TorBrowser-Data/Tor/control.socket" ) self.c = Controller.from_socket_file( path=socket_file_path) found_tor = True except: pass # If connecting to default control ports failed, so let's try # guessing the socket file name next if not found_tor: try: if self.common.platform == "Linux" or self.common.platform == "BSD": socket_file_path = ( f"/run/user/{os.geteuid()}/Tor/control.socket") elif self.common.platform == "Darwin": socket_file_path = ( f"/run/user/{os.geteuid()}/Tor/control.socket") elif self.common.platform == "Windows": # Windows doesn't support unix sockets print(automatic_error) raise TorErrorAutomatic() self.c = Controller.from_socket_file(path=socket_file_path) except: print(automatic_error) raise TorErrorAutomatic() # Try authenticating try: self.c.authenticate() except: print(automatic_error) raise TorErrorAutomatic() else: # Use specific settings to connect to tor invalid_settings_error = "Can't connect to Tor controller because your settings don't make sense." # Try connecting try: if self.settings.get("connection_type") == "control_port": self.c = Controller.from_port( address=self.settings.get("control_port_address"), port=self.settings.get("control_port_port"), ) elif self.settings.get("connection_type") == "socket_file": self.c = Controller.from_socket_file( path=self.settings.get("socket_file_path")) else: print(invalid_settings_error) raise TorErrorInvalidSetting() except: if self.settings.get("connection_type") == "control_port": print( "Can't connect to the Tor controller at {}:{}.".format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), )) raise TorErrorSocketPort( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) else: print( "Can't connect to the Tor controller using socket file {}." .format(self.settings.get("socket_file_path"))) raise TorErrorSocketFile( self.settings.get("socket_file_path")) # Try authenticating try: if self.settings.get("auth_type") == "no_auth": self.c.authenticate() elif self.settings.get("auth_type") == "password": self.c.authenticate(self.settings.get("auth_password")) else: print(invalid_settings_error) raise TorErrorInvalidSetting() except MissingPassword: print( "Connected to Tor controller, but it requires a password to authenticate." ) raise TorErrorMissingPassword() except UnreadableCookieFile: print( "Connected to the Tor controller, but password may be wrong, or your user is not permitted to read the cookie file." ) raise TorErrorUnreadableCookieFile() except AuthenticationFailure: print( "Connected to {}:{}, but can't authenticate. Maybe this isn't a Tor controller?" .format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), )) raise TorErrorAuthError( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) # If we made it this far, we should be connected to Tor self.connected_to_tor = True # Get the tor version self.tor_version = self.c.get_version().version_str self.common.log("Onion", "connect", f"Connected to tor {self.tor_version}") # Do the versions of stem and tor that I'm using support ephemeral onion services? list_ephemeral_hidden_services = getattr( self.c, "list_ephemeral_hidden_services", None) self.supports_ephemeral = (callable(list_ephemeral_hidden_services) and self.tor_version >= "0.2.7.1") # Do the versions of stem and tor that I'm using support stealth onion services? try: res = self.c.create_ephemeral_hidden_service( {1: 1}, basic_auth={"onionshare": None}, await_publication=False, key_type="NEW", key_content="RSA1024", ) tmp_service_id = res.service_id self.c.remove_ephemeral_hidden_service(tmp_service_id) self.supports_stealth = True except: # ephemeral stealth onion services are not supported self.supports_stealth = False # Does this version of Tor support next-gen ('v3') onions? # Note, this is the version of Tor where this bug was fixed: # https://trac.torproject.org/projects/tor/ticket/28619 self.supports_v3_onions = self.tor_version >= Version("0.3.5.7")
def setUp(self): socket = stem.socket.ControlSocket() mocking.mock_method(Controller, "add_event_listener", mocking.no_op()) self.controller = Controller(socket, enable_caching=True) mocking.revert_mocking()
import sys if __name__ == '__main__': from stem.control import Controller with Controller.from_port(port=9051) as controller: controller.authenticate() # controller.authenticate("yourpassphrase") bytes_read = controller.get_info("traffic/read") bytes_written = controller.get_info("traffic/written") print("My Tor relay has read %s bytes and written %s." % (bytes_read, bytes_written)) if not controller: sys.exit(1) # unable to get a connection print("Connection is Working Properly") controller.close()
class TestControl(unittest.TestCase): def setUp(self): socket = stem.socket.ControlSocket() mocking.mock_method(Controller, "add_event_listener", mocking.no_op()) self.controller = Controller(socket, enable_caching=True) mocking.revert_mocking() def tearDown(self): mocking.revert_mocking() def test_get_version(self): """ Exercises the get_version() method. """ try: # Use one version for first check. version_2_1 = "0.2.1.32" version_2_1_object = stem.version.Version(version_2_1) mocking.mock_method(Controller, "get_info", mocking.return_value(version_2_1)) # Return a version with a cold cache. self.assertEqual(version_2_1_object, self.controller.get_version()) # Use a different version for second check. version_2_2 = "0.2.2.39" version_2_2_object = stem.version.Version(version_2_2) mocking.mock_method(Controller, "get_info", mocking.return_value(version_2_2)) # Return a version with a hot cache, so it will be the old version. self.assertEqual(version_2_1_object, self.controller.get_version()) # Turn off caching. self.controller._is_caching_enabled = False # Return a version without caching, so it will be the new version. self.assertEqual(version_2_2_object, self.controller.get_version()) # Raise an exception in the get_info() call. mocking.mock_method(Controller, "get_info", mocking.raise_exception(InvalidArguments)) # Get a default value when the call fails. self.assertEqual( "default returned", self.controller.get_version(default="default returned")) # No default value, accept the error. self.assertRaises(InvalidArguments, self.controller.get_version) # Give a bad version. The stem.version.Version ValueError should bubble up. version_A_42 = "0.A.42.spam" mocking.mock_method(Controller, "get_info", mocking.return_value(version_A_42)) self.assertRaises(ValueError, self.controller.get_version) finally: # Turn caching back on before we leave. self.controller._is_caching_enabled = True def test_get_exit_policy(self): """ Exercises the get_exit_policy() method. """ mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("ExitPolicyRejectPrivate", ): "1", ("ExitPolicy", "multiple=True"): [ "accept *:80, accept *:443", "accept 43.5.5.5,reject *:22" ] }, is_method=True)) mocking.mock_method( Controller, "get_info", mocking.return_for_args( { ("address", None): "123.45.67.89", ("exit-policy/default", ): "reject *:25,reject *:119,reject *:135-139,reject *:445,reject *:563,reject *:1214,reject *:4661-4666,reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*" }, is_method=True)) expected = ExitPolicy( 'reject 0.0.0.0/8:*', # private entries 'reject 169.254.0.0/16:*', 'reject 127.0.0.0/8:*', 'reject 192.168.0.0/16:*', 'reject 10.0.0.0/8:*', 'reject 172.16.0.0/12:*', 'reject 123.45.67.89:*', # relay's public address 'accept *:80', # finally we get to our ExitPolicy 'accept *:443', 'accept 43.5.5.5:*', 'reject *:22', 'reject *:25', # default policy 'reject *:119', 'reject *:135-139', 'reject *:445', 'reject *:563', 'reject *:1214', 'reject *:4661-4666', 'reject *:6346-6429', 'reject *:6699', 'reject *:6881-6999', 'accept *:*', ) self.assertEqual(expected, self.controller.get_exit_policy()) def test_get_socks_listeners_old(self): """ Exercises the get_socks_listeners() method as though talking to an old tor instance. """ # An old tor raises stem.InvalidArguments for get_info about socks, but # get_socks_listeners should work anyway. mocking.mock_method(Controller, "get_info", mocking.raise_exception(InvalidArguments)) mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "9050", ("SocksListenAddress", "multiple=True"): ["127.0.0.1"] }, is_method=True)) self.assertEqual([('127.0.0.1', 9050)], self.controller.get_socks_listeners()) # Again, an old tor, but SocksListenAddress overrides the port number. mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "9050", ("SocksListenAddress", "multiple=True"): ["127.0.0.1:1112"] }, is_method=True)) self.assertEqual([('127.0.0.1', 1112)], self.controller.get_socks_listeners()) # Again, an old tor, but multiple listeners mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "9050", ("SocksListenAddress", "multiple=True"): ["127.0.0.1:1112", "127.0.0.1:1114"] }, is_method=True)) self.assertEqual([('127.0.0.1', 1112), ('127.0.0.1', 1114)], self.controller.get_socks_listeners()) # Again, an old tor, but no SOCKS listeners mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "0", ("SocksListenAddress", "multiple=True"): [] }, is_method=True)) self.assertEqual([], self.controller.get_socks_listeners()) # Where tor provides invalid ports or addresses mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "blarg", ("SocksListenAddress", "multiple=True"): ["127.0.0.1"] }, is_method=True)) self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "0", ("SocksListenAddress", "multiple=True"): ["127.0.0.1:abc"] }, is_method=True)) self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) mocking.mock_method( Controller, "get_conf", mocking.return_for_args( { ("SocksPort", ): "40", ("SocksListenAddress", "multiple=True"): ["500.0.0.1"] }, is_method=True)) self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) def test_get_socks_listeners_new(self): """ Exercises the get_socks_listeners() method as if talking to a newer tor instance. """ # multiple SOCKS listeners mocking.mock_method( Controller, "get_info", mocking.return_value('"127.0.0.1:1112" "127.0.0.1:1114"')) self.assertEqual([('127.0.0.1', 1112), ('127.0.0.1', 1114)], self.controller.get_socks_listeners()) # no SOCKS listeners mocking.mock_method(Controller, "get_info", mocking.return_value("")) self.assertEqual([], self.controller.get_socks_listeners()) # check where GETINFO provides malformed content invalid_responses = ( '"127.0.0.1"', # address only '"1112"', # port only '"5127.0.0.1:1112"', # invlaid address '"127.0.0.1:991112"', # invalid port ) for response in invalid_responses: mocking.mock_method(Controller, "get_info", mocking.return_value(response)) self.assertRaises(stem.ProtocolError, self.controller.get_socks_listeners) def test_get_protocolinfo(self): """ Exercises the get_protocolinfo() method. """ # Use the handy mocked protocolinfo response. mocking.mock(stem.connection.get_protocolinfo, mocking.return_value(mocking.get_protocolinfo_response())) # Compare the str representation of these object, because the class # does not have, nor need, a direct comparison operator. self.assertEqual(str(mocking.get_protocolinfo_response()), str(self.controller.get_protocolinfo())) # Raise an exception in the stem.connection.get_protocolinfo() call. mocking.mock(stem.connection.get_protocolinfo, mocking.raise_exception(ProtocolError)) # Get a default value when the call fails. self.assertEqual( "default returned", self.controller.get_protocolinfo(default="default returned")) # No default value, accept the error. self.assertRaises(ProtocolError, self.controller.get_protocolinfo) def test_get_network_status(self): """ Exercises the get_network_status() method. """ # Build a single router status entry. nickname = "Beaver" fingerprint = "/96bKo4soysolMgKn5Hex2nyFSY" desc = "r %s %s u5lTXJKGsLKufRLnSyVqT7TdGYw 2012-12-30 22:02:49 77.223.43.54 9001 0\ns Fast Named Running Stable Valid\nw Bandwidth=75" % ( nickname, fingerprint) router = stem.descriptor.router_status_entry.RouterStatusEntryV2(desc) # Always return the same router status entry. mocking.mock_method(Controller, "get_info", mocking.return_value(desc)) # Pretend to get the router status entry with its name. self.assertEqual(router, self.controller.get_network_status(nickname)) # Pretend to get the router status entry with its fingerprint. hex_fingerprint = stem.descriptor.router_status_entry._decode_fingerprint( fingerprint, False) self.assertEqual(router, self.controller.get_network_status(hex_fingerprint)) # Mangle hex fingerprint and try again. hex_fingerprint = hex_fingerprint[2:] self.assertRaises(ValueError, self.controller.get_network_status, hex_fingerprint) # Raise an exception in the get_info() call. mocking.mock_method(Controller, "get_info", mocking.raise_exception(InvalidArguments)) # Get a default value when the call fails. self.assertEqual( "default returned", self.controller.get_network_status(nickname, default="default returned")) # No default value, accept the error. self.assertRaises(InvalidArguments, self.controller.get_network_status, nickname) def test_event_listening(self): """ Exercises the add_event_listener and remove_event_listener methods. """ # set up for failure to create any events mocking.mock_method(Controller, "is_authenticated", mocking.return_true()) mocking.mock_method(Controller, "_attach_listeners", mocking.return_value(([], []))) mocking.mock_method( Controller, "get_version", mocking.return_value(stem.version.Version('0.1.0.14'))) self.assertRaises(InvalidRequest, self.controller.add_event_listener, mocking.no_op(), EventType.BW) # set up to only fail newer events mocking.mock_method( Controller, "get_version", mocking.return_value(stem.version.Version('0.2.0.35'))) # EventType.BW is one of the earliest events self.controller.add_event_listener(mocking.no_op(), EventType.BW) # EventType.SIGNAL was added in tor version 0.2.3.1-alpha self.assertRaises(InvalidRequest, self.controller.add_event_listener, mocking.no_op(), EventType.SIGNAL) def test_get_streams(self): """ Exercises the get_streams() method. """ # get a list of fake, but good looking, streams valid_streams = (("1", "NEW", "4", "10.10.10.1:80"), ("2", "SUCCEEDED", "4", "10.10.10.1:80"), ("3", "SUCCEEDED", "4", "10.10.10.1:80")) responses = ["%s\r\n" % " ".join(entry) for entry in valid_streams] mocking.mock_method(Controller, "get_info", mocking.return_value("".join(responses))) streams = self.controller.get_streams() self.assertEqual(len(valid_streams), len(streams)) for index, stream in enumerate(streams): self.assertEqual(valid_streams[index][0], stream.id) self.assertEqual(valid_streams[index][1], stream.status) self.assertEqual(valid_streams[index][2], stream.circ_id) self.assertEqual(valid_streams[index][3], stream.target) def test_parse_circ_path(self): """ Exercises the _parse_circ_path() helper function. """ # empty input self.assertEqual([], _parse_circ_path(None)) self.assertEqual([], _parse_circ_path('')) # check the pydoc examples pydoc_examples = { '$999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz': [('999A226EBED397F331B612FE1E4CFAE5C1F201BA', 'piyaz')], '$E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone,PrivacyRepublic14': [ ('E57A476CD4DFBD99B4EE52A100A58610AD6E80B9', None), (None, 'hamburgerphone'), (None, 'PrivacyRepublic14'), ], } for test_input, expected in pydoc_examples.items(): self.assertEqual(expected, _parse_circ_path(test_input)) # exercise with some invalid inputs malformed_inputs = [ '=piyaz', # no fingerprint '999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz', # fingerprint missing prefix '$999A226EBED397F331B612FE1E4CFAE5C1F201BAA=piyaz', # fingerprint too long '$999A226EBED397F331B612FE1E4CFAE5C1F201B=piyaz', # fingerprint too short '$999A226EBED397F331B612FE1E4CFAE5C1F201Bz=piyaz', # invalid character in fingerprint '$999A226EBED397F331B612FE1E4CFAE5C1F201BA=', # no nickname ] for test_input in malformed_inputs: self.assertRaises(ProtocolError, _parse_circ_path, test_input)
def renew_tor_ip(): with Controller.from_port(port=9051) as controller: controller.authenticate( password='******') controller.signal(Signal.NEWNYM)
def create_new_tor_ip(): with Controller.from_port(port=9051) as controller: controller.authenticate(password=environ["TOR_PASS"]) controller.signal(Signal.NEWNYM)
def update_tor_ip(self): with Controller.from_port(port=self.PORT_FOR_TOR) as controller: controller.authenticate(self.PASS_FOR_TOR) controller.signal(Signal.NEWNYM) sleep(8) self.session = self.get_session()
def renew_connection(): with Controller.from_port(port=9051) as controller: controller.authenticate(password="******") controller.signal(Signal.NEWNYM)
#!/usr/bin/env python from stem import Signal from stem.control import Controller import miniupnpc import socket import sys u = miniupnpc.UPnP() u.discoverdelay = 200 forward_dir = True with Controller.from_port(port=int(sys.argv[1])) as controller: controller.authenticate() try: lor = int( controller.get_info("net/listeners/or").strip('\"').split(':')[1]) except IndexError: print( "Error when parsing response of GETINFO net/listeners/or. Relaying is likely disabled." ) exit(1) try: ldir = int( controller.get_info("net/listeners/dir").strip('\"').split(':')[1]) except IndexError: forward_dir = False u.discover() u.selectigd() print("Forwarding ORPort " + str(lor))
def switchIP(): with Controller.from_port(port=9051) as controller: controller.authenticate() controller.signal(Signal.NEWNYM)
def renew_connection(): with Controller.from_port(port = 9051) as controller: controller.authenticate(password='') ## PUT YOUR PASSWORD HERE! controller.signal(Signal.NEWNYM)
def run(self, do_onion=True, do_inet=True, tgen_model=None, tgen_client_conf=None, tgen_server_conf=None): ''' only `tgen_server_conf.listen_port` are "public" and need to be opened on the firewall. if `tgen_client_conf.connect_port` != `tgen_server_conf.listen_port`, then you should have installed a forwarding rule in the firewall. all ports need to be unique though, and unique among multiple onionperf instances. here are some sane defaults: tgen_client_conf.listen_port=58888, tgen_client_conf.connect_port=8080, tgen_client_conf.tor_ctl_port=59050, tgen_client_conf.tor_socks_port=59000, tgen_server_conf.listen_port=8080, tgen_server_conf.tor_ctl_port=59051, tgen_server_conf.tor_socks_port=59001 ''' self.threads = [] self.done_event = threading.Event() if tgen_client_conf is None: tgen_client_conf = TGenConf(listen_port=58888, connect_ip='0.0.0.0', connect_port=8080, tor_ctl_port=59050, tor_socks_port=59000) if tgen_server_conf is None: tgen_server_conf = TGenConf(listen_port=8080, tor_ctl_port=59051, tor_socks_port=59001) # if ctrl-c is pressed, shutdown child processes properly try: # make sure stem and Tor supports ephemeral HS (version >= 0.2.7.1-alpha) # and also the NEWNYM mode that clears descriptor cache (version >= 0.2.7.3-rc) if do_onion: try: tor_version = get_system_tor_version(self.tor_bin_path) if tor_version < Requirement.ADD_ONION or tor_version < Version('0.2.7.3-rc'): # ADD_ONION is a stem 1.4.0 feature logging.warning("OnionPerf in onion mode requires Tor version >= 0.2.7.3-rc, you have {0}, aborting".format(tor_version)) return except: logging.warning("OnionPerf in onion mode requires stem version >= 1.4.0, you have {0}, aborting".format(stem_version)) return logging.info("Bootstrapping started...") logging.info("Log files for the client and server processes will be placed in {0}".format(self.datadir_path)) general_writables = [] tgen_client_writable, torctl_client_writable = None, None if do_onion or do_inet: tgen_model.port = tgen_server_conf.listen_port general_writables.append(self.__start_tgen_server(tgen_model)) if do_onion: logging.info("Onion Service private keys will be placed in {0}".format(self.privatedir_path)) # one must not have an open socks port when running a single # onion service. see tor's man page for more information. if self.single_onion: tgen_server_conf.tor_socks_port = 0 tor_writable, torctl_writable = self.__start_tor_server(tgen_server_conf.tor_ctl_port, tgen_server_conf.tor_socks_port, {tgen_client_conf.connect_port:tgen_server_conf.listen_port}) general_writables.append(tor_writable) general_writables.append(torctl_writable) if do_onion or do_inet: tor_writable, torctl_client_writable = self.__start_tor_client(tgen_client_conf.tor_ctl_port, tgen_client_conf.tor_socks_port) general_writables.append(tor_writable) server_urls = [] if do_onion and self.hs_v3_service_id is not None: server_urls.append("{0}.onion:{1}".format(self.hs_v3_service_id, tgen_client_conf.connect_port)) if do_inet: connect_ip = tgen_client_conf.connect_ip if tgen_client_conf.connect_ip != '0.0.0.0' else util.get_ip_address() server_urls.append("{0}:{1}".format(connect_ip, tgen_client_conf.connect_port)) tgen_model.servers = server_urls if do_onion or do_inet: assert len(server_urls) > 0 tgen_model.port = tgen_client_conf.listen_port tgen_model.socks_port = tgen_client_conf.tor_socks_port tgen_client_writable = self.__start_tgen_client(tgen_model) self.__start_log_processors(general_writables, tgen_client_writable, torctl_client_writable) logging.info("Bootstrapping finished, entering heartbeat loop") time.sleep(1) while True: if tgen_model.num_transfers: # This function blocks until our TGen client process # terminated on its own. self.__wait_for_tgen_client() break if self.__is_alive(): logging.info("All helper processes seem to be alive :)") else: logging.warning("Some parallel components failed too many times or have died :(") logging.info("We are in a broken state, giving up and exiting now") break logging.info("Next main process heartbeat is in 1 hour (helper processes run on their own schedule)") logging.info("press CTRL-C for graceful shutdown...") time.sleep(3600) else: logging.info("No measurement mode set, nothing to do") except KeyboardInterrupt: logging.info("Interrupt received, please wait for graceful shutdown") self.__is_alive() finally: logging.info("Cleaning up child processes now...") if self.hs_v3_service_id is not None: try: with Controller.from_port(port=self.hs_v3_control_port) as torctl: torctl.authenticate() torctl.remove_ephemeral_hidden_service(self.hs_v3_service_id) except: pass # this fails to authenticate if tor proc is dead # logging.disable(logging.INFO) self.done_event.set() for t in self.threads: logging.info("Joining {0} thread...".format(t.getName())) t.join() time.sleep(1) # logging.disable(logging.NOTSET) logging.info("Child processes terminated") logging.info("Child process cleanup complete!") logging.info("Exiting")
def setUp(self): socket = stem.socket.ControlSocket() with patch('stem.control.Controller.add_event_listener', Mock()): self.controller = Controller(socket)
import shutil from stem.control import Controller from flask import Flask app = Flask(__name__) @app.route('/') def index(): return "<h1>Hi Grandma!</h1>" print(' * Connecting to tor') with Controller.from_port() as controller: controller.authenticate() # All hidden services have a directory on disk. Lets put ours in tor's data # directory. hidden_service_dir = os.path.join(controller.get_conf('DataDirectory', '/tmp'), 'hello_world') # Create a hidden service where visitors of port 80 get redirected to local # port 5000 (this is where Flask runs by default). print(" * Creating our hidden service in %s" % hidden_service_dir) result = controller.create_hidden_service(hidden_service_dir, 80, target_port = 5000) # The hostname is only available when we can read the hidden service # directory. This requires us to be running with the same user as tor.
def _setTorController(self): """Initialize a Controller with the control port.""" try: self.tor_controller = Controller.from_port(port=self.ctrl_port) except Exception as err: raise EnvironmentError(err)
def __init__(self, peer, address, core_inst=None): if core_inst is None: self.core_inst = core.Core() else: self.core_inst = core_inst if not core_inst._utils.validatePubKey(peer): raise ValueError('Peer must be valid base32 ed25519 public key') socks = core_inst.config.get( 'tor.socksport') # Load config for Tor socks port for proxy service_app = Flask(__name__) # Setup Flask app for server. service_port = getOpenPort() service_ip = api.setBindIP() http_server = WSGIServer(('127.0.0.1', service_port), service_app, log=None) core_inst.onionrInst.communicatorInst.service_greenlets.append( http_server) # TODO define basic endpoints useful for direct connections like stats httpapi.load_plugin_blueprints(service_app, blueprint='direct_blueprint') @service_app.route('/ping') def get_ping(): return "pong!" @service_app.route('/close') def shutdown_server(): core_inst.onionrInst.communicatorInst.service_greenlets.remove( http_server) http_server.stop() return Response('goodbye') @service_app.after_request def afterReq(resp): # Security headers resp = httpheaders.set_default_onionr_http_headers(resp) return resp with Controller.from_port( port=core_inst.config.get('tor.controlPort')) as controller: # Connect to the Tor process for Onionr controller.authenticate( core_inst.config.get('tor.controlpassword')) # Create the v3 onion service for the peer to connect to response = controller.create_ephemeral_hidden_service( {80: service_port}, await_publication=True, key_type='NEW', key_content='ED25519-V3') try: for x in range(3): attempt = self.core_inst._utils.doPostRequest( 'http://' + address + '/bs/' + response.service_id, port=socks) if attempt == 'success': break else: raise ConnectionError except ConnectionError: # Re-raise raise ConnectionError( 'Could not reach %s bootstrap address %s' % (peer, address)) else: # If no connection error, create the service and save it to local global key store self.core_inst.keyStore.put( 'dc-' + response.service_id, self.core_inst._utils.bytesToStr(peer)) logger.info('hosting on %s with %s' % (response.service_id, peer)) http_server.serve_forever() http_server.stop() self.core_inst.keyStore.delete('dc-' + response.service_id)
def renew_tor_ip(): with Controller.from_port(port=9051) as controller: # controller.authenticate(password="******") controller.authenticate() controller.signal(Signal.NEWNYM) controller.close()
finally: f.close() filehash = sha1.hexdigest() filesize = os.path.getsize(filename) # choose a port port = randint(1025, 65535) # connect to the tor controlport print 'Connecting to Tor ControlPort to set up hidden service on port {0}'.format( port) controlports = [9051, 9151] controller = False for controlport in controlports: try: controller = Controller.from_port(port=controlport) except SocketError: pass if not controller: sys.exit( 'Cannot connect to Tor ControlPorts on ports {0}. Is Tor running?'. format(controlports)) controller.authenticate() # set up hidden service controller.set_options([ ('HiddenServiceDir', '/tmp/onionshare_hidden_service_{0}/'.format(port)), ('HiddenServicePort', '80 127.0.0.1:{0}'.format(port)) ]) onion_host = open(
def set_new_ip(): """Change IP using TOR""" with Controller.from_port(port=9051) as controller: controller.authenticate(password='******') controller.signal(Signal.NEWNYM)
def reset_identity(): with Controller.from_port(port = CONTROL_PORT) as controller: controller.authenticate() controller.signal(Signal.NEWNYM)
def renew_connection(port=tor_ctrl_port): # for use with Tor with Controller.from_port(port=port) as controller: controller.authenticate(password='******') controller.signal(Signal.NEWNYM) controller.close()
def new_identity(): with Controller.from_port(port=9051) as controller: controller.authenticate() controller.signal(Signal.NEWNYM) controller.close()