Ejemplo n.º 1
0
    async def _download_from(self, endpoint: stem.Endpoint) -> bytes:
        http_request = '\r\n'.join((
            'GET %s HTTP/1.0' % self.resource,
            'Accept-Encoding: %s' %
            ', '.join(map(lambda c: c.encoding, self.compression)),
            'User-Agent: %s' % stem.USER_AGENT,
        )) + '\r\n\r\n'

        if isinstance(endpoint, stem.ORPort):
            link_protocols = endpoint.link_protocols if endpoint.link_protocols else [
                3
            ]

            async with await stem.client.Relay.connect(
                    endpoint.address, endpoint.port, link_protocols) as relay:
                async with await relay.create_circuit() as circ:
                    return await circ.directory(http_request, stream_id=1)
        elif isinstance(endpoint, stem.DirPort):
            reader, writer = await asyncio.open_connection(
                endpoint.address, endpoint.port)
            writer.write(str_tools._to_bytes(http_request))

            return await reader.read()
        else:
            raise ValueError(
                "BUG: endpoints can only be ORPorts or DirPorts, '%s' was a %s"
                % (endpoint, type(endpoint).__name__))
Ejemplo n.º 2
0
  def __init__(self, circ_id, command, data, digest = 0, stream_id = 0, recognized = 0, unused = b''):
    if 'hash' in str(type(digest)).lower():
      # Unfortunately hashlib generates from a dynamic private class so
      # isinstance() isn't such a great option. With python2/python3 the
      # name is 'hashlib.HASH' whereas PyPy calls it just 'HASH' or 'Hash'.

      digest_packed = digest.digest()[:RELAY_DIGEST_SIZE.size]
      digest = RELAY_DIGEST_SIZE.unpack(digest_packed)
    elif isinstance(digest, (bytes, str)):
      digest_packed = digest[:RELAY_DIGEST_SIZE.size]
      digest = RELAY_DIGEST_SIZE.unpack(digest_packed)
    elif isinstance(digest, int):
      pass
    else:
      raise ValueError('RELAY cell digest must be a hash, string, or int but was a %s' % type(digest).__name__)

    super(RelayCell, self).__init__(circ_id, unused)
    self.command, self.command_int = RelayCommand.get(command)
    self.recognized = recognized
    self.stream_id = stream_id
    self.digest = digest
    self.data = str_tools._to_bytes(data)

    if digest == 0:
      if not stream_id and self.command in STREAM_ID_REQUIRED:
        raise ValueError('%s relay cells require a stream id' % self.command)
      elif stream_id and self.command in STREAM_ID_DISALLOWED:
        raise ValueError('%s relay cells concern the circuit itself and cannot have a stream id' % self.command)
Ejemplo n.º 3
0
    def __start_tor(self, name, control_port, socks_port, hs_port_mapping=None):
        logging.info("Starting Tor {0} process with ControlPort={1}, SocksPort={2}...".format(name, control_port, socks_port))

        tor_datadir = "{0}/tor-{1}".format(self.datadir_path, name)
        if not os.path.exists(tor_datadir): os.makedirs(tor_datadir)

        tor_config_template = "ORPort 0\nDirPort 0\nControlPort {0}\nSocksPort {1}\nSocksListenAddress 127.0.0.1\nClientOnly 1\n\
WarnUnsafeSocks 0\nSafeLogging 0\nMaxCircuitDirtiness 60 seconds\nUseEntryGuards 0\nDataDirectory {2}\nLog INFO stdout\n"
        tor_config = tor_config_template.format(control_port, socks_port, tor_datadir)

        tor_logpath = "{0}/onionperf.tor.log".format(tor_datadir)
        tor_writable = util.FileWritable(tor_logpath)
        logging.info("Logging Tor {0} process output to {1}".format(name, tor_logpath))

        # from stem.process import launch_tor_with_config
        # tor_subp = launch_tor_with_config(tor_config, tor_cmd=self.tor_bin_path, completion_percent=100, init_msg_handler=None, timeout=None, take_ownership=False)
        tor_cmd = "{0} -f -".format(self.tor_bin_path)
        tor_stdin_bytes = str_tools._to_bytes(tor_config)
        tor_ready_str = "Bootstrapped 100"
        tor_ready_ev = threading.Event()
        tor_args = (tor_cmd, tor_datadir, tor_writable, self.done_event, tor_stdin_bytes, tor_ready_str, tor_ready_ev)
        tor_watchdog = threading.Thread(target=watchdog_thread_task, name="tor_{0}_watchdog".format(name), args=tor_args)
        tor_watchdog.start()
        self.threads.append(tor_watchdog)

        # wait until Tor finishes bootstrapping
        tor_ready_ev.wait()

        torctl_logpath = "{0}/onionperf.torctl.log".format(tor_datadir)
        torctl_writable = util.FileWritable(torctl_logpath)
        logging.info("Logging Tor {0} control port monitor output to {1}".format(name, torctl_logpath))

        # give a few seconds to make sure Tor had time to start listening on the control port
        time.sleep(3)

        torctl_events = [e for e in monitor.get_supported_torctl_events() if e not in ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']]
        newnym_interval_seconds = 300
        torctl_args = (control_port, torctl_writable, torctl_events, newnym_interval_seconds, self.done_event)
        torctl_helper = threading.Thread(target=monitor.tor_monitor_run, name="torctl_{0}_helper".format(name), args=torctl_args)
        torctl_helper.start()
        self.threads.append(torctl_helper)

        if hs_port_mapping is not None:
            logging.info("Creating ephemeral hidden service with v2 onions...")
            with Controller.from_port(port=control_port) as torctl:
                torctl.authenticate()
                response = torctl.create_ephemeral_hidden_service(hs_port_mapping, detached=True, await_publication=True)
                self.hs_service_id = response.service_id
                self.hs_control_port = control_port
                logging.info("Ephemeral hidden service is available at {0}.onion".format(response.service_id))

            logging.info("Creating ephemeral hidden service with v3 onions...")
            with Controller.from_port(port=control_port) as torctl:
                torctl.authenticate()
                response = torctl.create_ephemeral_hidden_service(hs_port_mapping, detached=True, await_publication=True, key_content='ED25519-V3')
                self.hs_v3_service_id = response.service_id
                self.hs_v3_control_port = control_port
                logging.info("Ephemeral hidden service is available at {0}.onion".format(response.service_id))
        return tor_writable, torctl_writable
Ejemplo n.º 4
0
  def _parse(self):
    content = str(self).lstrip("NEWCONSENSUS\n").rstrip("\nOK")

    self.desc = list(stem.descriptor.router_status_entry._parse_file(
      io.BytesIO(str_tools._to_bytes(content)),
      True,
      entry_class = stem.descriptor.router_status_entry.RouterStatusEntryV3,
    ))
Ejemplo n.º 5
0
  def _parse(self):
    content = str(self).lstrip("NEWCONSENSUS\n").rstrip("\nOK")

    self.desc = list(stem.descriptor.router_status_entry._parse_file(
      io.BytesIO(str_tools._to_bytes(content)),
      True,
      entry_class = stem.descriptor.router_status_entry.RouterStatusEntryV3,
    ))
Ejemplo n.º 6
0
  def _parse(self):
    content = str(self).lstrip('NEWCONSENSUS\n').rstrip('\nOK')

    # TODO: For stem 2.0.0 consider changing 'desc' to 'descriptors' to match
    # our other events.

    self.desc = list(stem.descriptor.router_status_entry._parse_file(
      io.BytesIO(str_tools._to_bytes(content)),
      True,
      entry_class = stem.descriptor.router_status_entry.RouterStatusEntryV3,
    ))
Ejemplo n.º 7
0
    def __start_tor(self, name, control_port, socks_port, hs_port_mapping=None):
        logging.info("Starting Tor {0} process with ControlPort={1}, SocksPort={2}...".format(name, control_port, socks_port))

        tor_datadir = "{0}/tor-{1}".format(self.datadir_path, name)
        if not os.path.exists(tor_datadir): os.makedirs(tor_datadir)

        tor_config_template = "ORPort 0\nDirPort 0\nControlPort {0}\nSocksPort {1}\nSocksListenAddress 127.0.0.1\nClientOnly 1\n\
WarnUnsafeSocks 0\nSafeLogging 0\nMaxCircuitDirtiness 60 seconds\nUseEntryGuards 0\nDataDirectory {2}\nLog INFO stdout\n"
        tor_config = tor_config_template.format(control_port, socks_port, tor_datadir)

        tor_logpath = "{0}/onionperf.tor.log".format(tor_datadir)
        tor_writable = util.FileWritable(tor_logpath)
        logging.info("Logging Tor {0} process output to {1}".format(name, tor_logpath))

        # from stem.process import launch_tor_with_config
        # tor_subp = launch_tor_with_config(tor_config, tor_cmd=self.tor_bin_path, completion_percent=100, init_msg_handler=None, timeout=None, take_ownership=False)
        tor_cmd = "{0} -f -".format(self.tor_bin_path)
        tor_stdin_bytes = str_tools._to_bytes(tor_config)
        tor_ready_str = "Bootstrapped 100"
        tor_ready_ev = threading.Event()
        tor_args = (tor_cmd, tor_datadir, tor_writable, self.done_event, tor_stdin_bytes, tor_ready_str, tor_ready_ev)
        tor_watchdog = threading.Thread(target=watchdog_thread_task, name="tor_{0}_watchdog".format(name), args=tor_args)
        tor_watchdog.start()
        self.threads.append(tor_watchdog)

        # wait until Tor finishes bootstrapping
        tor_ready_ev.wait()

        torctl_logpath = "{0}/onionperf.torctl.log".format(tor_datadir)
        torctl_writable = util.FileWritable(torctl_logpath)
        logging.info("Logging Tor {0} control port monitor output to {1}".format(name, torctl_logpath))

        # give a few seconds to make sure Tor had time to start listening on the control port
        time.sleep(3)

        torctl_events = [e for e in monitor.get_supported_torctl_events() if e not in ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']]
        newnym_interval_seconds = 300
        torctl_args = (control_port, torctl_writable, torctl_events, newnym_interval_seconds, self.done_event)
        torctl_helper = threading.Thread(target=monitor.tor_monitor_run, name="torctl_{0}_helper".format(name), args=torctl_args)
        torctl_helper.start()
        self.threads.append(torctl_helper)

        if hs_port_mapping is not None:
            logging.info("Creating ephemeral hidden service...")
            with Controller.from_port(port=control_port) as torctl:
                torctl.authenticate()
                response = torctl.create_ephemeral_hidden_service(hs_port_mapping, detached=True, await_publication=True)
                self.hs_service_id = response.service_id
                self.hs_control_port = control_port
                logging.info("Ephemeral hidden service is available at {0}.onion".format(response.service_id))

        return tor_writable, torctl_writable
Ejemplo n.º 8
0
  def test_to_int(self):
    """
    Checks the _to_int() function.
    """

    test_inputs = {
      '': 0,
      'h': 104,
      'hi': 26729,
      'hello': 448378203247,
      str_tools._to_bytes('hello'): 448378203247,
      str_tools._to_unicode('hello'): 448378203247,
    }

    for arg, expected in test_inputs.items():
      self.assertEqual(expected, str_tools._to_int(arg))
Ejemplo n.º 9
0
  def test_to_int(self):
    """
    Checks the _to_int() function.
    """

    test_inputs = {
      '': 0,
      'h': 104,
      'hi': 26729,
      'hello': 448378203247,
      str_tools._to_bytes('hello'): 448378203247,
      str_tools._to_unicode('hello'): 448378203247,
    }

    for arg, expected in test_inputs.items():
      self.assertEqual(expected, str_tools._to_int(arg))
Ejemplo n.º 10
0
  def _parse(self):
    if self.address == 'UNKNOWN':
      self.address = None

    self.directory_fingerprint = None
    self.directory_nickname = None

    try:
      self.directory_fingerprint, self.directory_nickname = \
        stem.control._parse_circ_entry(self.directory)
    except stem.ProtocolError:
      raise stem.ProtocolError("HS_DESC_CONTENT's directory doesn't match a ServerSpec: %s" % self)

    self.descriptor = list(stem.descriptor.hidden_service_descriptor._parse_file(
      io.BytesIO(str_tools._to_bytes('\n'.join(str(self).splitlines()[1:]))),
    ))[0]
Ejemplo n.º 11
0
    def __start_tor(self, name, control_port, socks_port, hs_port_mapping=None):
        logging.info("Starting Tor {0} process with ControlPort={1}, SocksPort={2}...".format(name, control_port, socks_port))
        tor_datadir = "{0}/tor-{1}".format(self.datadir_path, name)
        key_path_v3 = "{0}/os_key_v3".format(self.privatedir_path)

        if not os.path.exists(tor_datadir): os.makedirs(tor_datadir)
        tor_config = self.create_tor_config(control_port,socks_port,tor_datadir,name)
        tor_confpath = "{0}/torrc".format(tor_datadir)
        with open(tor_confpath, 'wt') as f:
            f.write(tor_config)

        tor_logpath = "{0}/onionperf.tor.log".format(tor_datadir)
        tor_writable = util.FileWritable(tor_logpath)
        logging.info("Logging Tor {0} process output to {1}".format(name, tor_logpath))

        # from stem.process import launch_tor_with_config
        # tor_subp = launch_tor_with_config(tor_config, tor_cmd=self.tor_bin_path, completion_percent=100, init_msg_handler=None, timeout=None, take_ownership=False)
        tor_cmd = "{0} -f -".format(self.tor_bin_path)
        tor_stdin_bytes = str_tools._to_bytes(tor_config)
        tor_ready_str = "Bootstrapped 100"
        tor_ready_ev = threading.Event()
        tor_args = (tor_cmd, tor_datadir, tor_writable, self.done_event, tor_stdin_bytes, tor_ready_str, tor_ready_ev, False)
        tor_watchdog = threading.Thread(target=watchdog_thread_task, name="tor_{0}_watchdog".format(name), args=tor_args)
        tor_watchdog.start()
        self.threads.append(tor_watchdog)

        # wait until Tor finishes bootstrapping
        tor_ready_ev.wait()

        torctl_logpath = "{0}/onionperf.torctl.log".format(tor_datadir)
        torctl_writable = util.FileWritable(torctl_logpath)
        logging.info("Logging Tor {0} control port monitor output to {1}".format(name, torctl_logpath))

        # give a few seconds to make sure Tor had time to start listening on the control port
        time.sleep(3)

        torctl_events = [e for e in monitor.get_supported_torctl_events() if e not in ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']]
        newnym_interval_seconds = 300
        torctl_args = (control_port, torctl_writable, torctl_events, newnym_interval_seconds, self.drop_guards_interval_hours, self.done_event)
        torctl_helper = threading.Thread(target=monitor.tor_monitor_run, name="torctl_{0}_helper".format(name), args=torctl_args)
        torctl_helper.start()
        self.threads.append(torctl_helper)

        if hs_port_mapping is not None:
            self.start_onion_service(control_port, hs_port_mapping, key_path_v3)

        return tor_writable, torctl_writable
Ejemplo n.º 12
0
  def _parse(self):
    if self.address == 'UNKNOWN':
      self.address = None

    self.directory_fingerprint = None
    self.directory_nickname = None

    try:
      self.directory_fingerprint, self.directory_nickname = \
        stem.control._parse_circ_entry(self.directory)
    except stem.ProtocolError:
      raise stem.ProtocolError("HS_DESC_CONTENT's directory doesn't match a ServerSpec: %s" % self)

    # skip the first line (our positional arguments) and last ('OK')

    desc_content = str_tools._to_bytes('\n'.join(str(self).splitlines()[1:-1]))
    self.descriptor = None

    if desc_content:
      self.descriptor = list(stem.descriptor.hidden_service_descriptor._parse_file(io.BytesIO(desc_content)))[0]