Exemple #1
0
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)
Exemple #2
0
 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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
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")
Exemple #7
0
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 ''
Exemple #8
0
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
Exemple #9
0
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;    
Exemple #10
0
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)
Exemple #11
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
Exemple #13
0
    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)
Exemple #14
0
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()
Exemple #15
0
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
Exemple #16
0
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)
Exemple #17
0
    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)
Exemple #18
0
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)
Exemple #19
0
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"})
Exemple #20
0
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
Exemple #21
0
 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
Exemple #22
0
    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
Exemple #23
0
    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'
Exemple #24
0
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
Exemple #25
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)
Exemple #26
0
 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
Exemple #27
0
	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)
Exemple #28
0
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)
Exemple #29
0
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
Exemple #31
0
def change_identity():
    with Controller.from_port(port=9051) as c:
        c.authenticate(password=password)
        c.signal(Signal.NEWNYM)
Exemple #32
0
    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')
Exemple #33
0
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
Exemple #34
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)
Exemple #36
0
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)
Exemple #38
0
def renew_connection():
    with Controller.from_port(port=9051) as controller:
        controller.authenticate(password='******')
        controller.signal(Signal.NEWNYM)
        controller.close()
Exemple #39
0
    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")
Exemple #40
0
    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()
Exemple #41
0
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()
Exemple #42
0
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)
Exemple #43
0
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()
Exemple #46
0
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))
Exemple #48
0
def switchIP():
    with Controller.from_port(port=9051) as controller:
        controller.authenticate()
        controller.signal(Signal.NEWNYM)
Exemple #49
0
def renew_connection():
	with Controller.from_port(port = 9051) as controller:
		controller.authenticate(password='') ## PUT YOUR PASSWORD HERE!
		controller.signal(Signal.NEWNYM)
Exemple #50
0
    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")
Exemple #51
0
  def setUp(self):
    socket = stem.socket.ControlSocket()

    with patch('stem.control.Controller.add_event_listener', Mock()):
      self.controller = Controller(socket)
Exemple #52
0
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.
Exemple #53
0
 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)
Exemple #54
0
    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)
Exemple #55
0
def renew_tor_ip():
    with Controller.from_port(port=9051) as controller:
        # controller.authenticate(password="******")
        controller.authenticate()
        controller.signal(Signal.NEWNYM)
        controller.close()
Exemple #56
0
    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)
Exemple #58
0
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()