コード例 #1
0
ファイル: orstatus.py プロジェクト: toralf/torutils
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--ctrlport',
                        type=int,
                        help='default: 9051',
                        default=9051)
    args = parser.parse_args()

    with Controller.from_port(port=args.ctrlport) as controller:
        controller.authenticate()

        for desc in parse_file('/var/lib/tor/data/cached-consensus'):
            ip = 'v4' if is_valid_ipv4_address(desc.address) else 'v6'
            desc_versions[desc.fingerprint] = [
                desc.address, desc.or_port, ip, desc.version
            ]
        for desc in parse_file('/var/lib/tor/data2/cached-consensus'):
            ip = 'v4' if is_valid_ipv4_address(desc.address) else 'v6'
            desc_versions[desc.fingerprint] = [
                desc.address, desc.or_port, ip, desc.version
            ]

        orconn_listener = functools.partial(orconn_event, controller)
        controller.add_event_listener(orconn_listener, EventType.ORCONN)
        while True:
            try:
                time.sleep(1)
            except KeyboardInterrupt:
                break
コード例 #2
0
ファイル: remote.py プロジェクト: sammyshj/stem
  def from_remote(timeout = 60):
    """
    Reads and parses tor's latest fallback directories `from
    gitweb.torproject.org
    <https://gitweb.torproject.org/tor.git/plain/src/or/fallback_dirs.inc>`_.
    Note that while convenient, this reliance on GitWeb means you should alway
    call with a fallback, such as...

    ::

      try:
        fallback_directories = stem.descriptor.remote.from_remote()
      except IOError:
        fallback_directories = stem.descriptor.remote.from_cache()

    :param int timeout: seconds to wait before timing out the request

    :returns: **dict** of **str** fingerprints to their
      :class:`~stem.descriptor.remote.FallbackDirectory`

    :raises: **IOError** if unable to retrieve the fallback directories
    """

    try:
      fallback_dir_page = str_tools._to_unicode(urllib.urlopen(GITWEB_FALLBACK_DIR_URL, timeout = timeout).read())
    except:
      exc = sys.exc_info()[1]
      raise IOError("Unable to download tor's fallback directories from %s: %s" % (GITWEB_FALLBACK_DIR_URL, exc))

    # Example of an entry...
    #
    #   "5.175.233.86:80 orport=443 id=5525D0429BFE5DC4F1B0E9DE47A4CFA169661E33"
    #   " weight=43680",

    results = {}

    for line in fallback_dir_page.splitlines():
      if line.startswith('"'):
        addr_line_match = re.match('"([\d\.]+):(\d+) orport=(\d+) id=([\dA-F]{40}).*', line)

        if addr_line_match:
          address, dir_port, or_port, fingerprint = addr_line_match.groups()

          if not connection.is_valid_ipv4_address(address):
            raise IOError('%s has an invalid address: %s' % (fingerprint, address))
          elif not connection.is_valid_port(or_port):
            raise IOError('%s has an invalid or_port: %s' % (fingerprint, or_port))
          elif not connection.is_valid_port(dir_port):
            raise IOError('%s has an invalid dir_port: %s' % (fingerprint, dir_port))
          elif not tor_tools.is_valid_fingerprint(fingerprint):
            raise IOError('%s has an invalid fingerprint: %s' % (fingerprint, fingerprint))

          results[fingerprint] = FallbackDirectory(
            address = address,
            or_port = int(or_port),
            dir_port = int(dir_port),
            fingerprint = fingerprint,
          )

    return results
コード例 #3
0
ファイル: orstatus.py プロジェクト: toralf/torutils
def orconn_event(controller, relays, event):
  if event.status == ORStatus.CLOSED:

    fingerprint = event.endpoint_fingerprint

    print ("%-12s %s" % (event.reason, fingerprint), end='')

    relay = controller.get_network_status(fingerprint, None)
    if (relay):
      if is_valid_ipv4_address(relay.address):
        ip = 'v4'
      else:
        ip = 'v6'

      version = relay.version
      if version == None:
        try:
          desc = controller.get_server_descriptor(fingerprint)
          version = desc.tor_version
        except Exception as Exc:
          version = 'error'

      print (" %15s %5i %s %s" % (relay.address, relay.or_port, ip, version))
    else:
      print ('', flush=True)
コード例 #4
0
  def __init__(self, address: str, or_port: Union[int, str], dir_port: Union[int, str], fingerprint: str, nickname: str, orport_v6: Tuple[str, int]) -> None:
    identifier = '%s (%s)' % (fingerprint, nickname) if nickname else fingerprint

    if not connection.is_valid_ipv4_address(address):
      raise ValueError('%s has an invalid IPv4 address: %s' % (identifier, address))
    elif not connection.is_valid_port(or_port):
      raise ValueError('%s has an invalid ORPort: %s' % (identifier, or_port))
    elif not connection.is_valid_port(dir_port):
      raise ValueError('%s has an invalid DirPort: %s' % (identifier, dir_port))
    elif not tor_tools.is_valid_fingerprint(fingerprint):
      raise ValueError('%s has an invalid fingerprint: %s' % (identifier, fingerprint))
    elif nickname and not tor_tools.is_valid_nickname(nickname):
      raise ValueError('%s has an invalid nickname: %s' % (fingerprint, nickname))

    if orport_v6:
      if not isinstance(orport_v6, tuple) or len(orport_v6) != 2:
        raise ValueError('%s orport_v6 should be a two value tuple: %s' % (identifier, str(orport_v6)))
      elif not connection.is_valid_ipv6_address(orport_v6[0]):
        raise ValueError('%s has an invalid IPv6 address: %s' % (identifier, orport_v6[0]))
      elif not connection.is_valid_port(orport_v6[1]):
        raise ValueError('%s has an invalid IPv6 port: %s' % (identifier, orport_v6[1]))

    self.address = address
    self.or_port = int(or_port)
    self.dir_port = int(dir_port)
    self.fingerprint = fingerprint
    self.nickname = nickname
    self.orport_v6 = (orport_v6[0], int(orport_v6[1])) if orport_v6 else None
コード例 #5
0
    def exits_can_exit_to(self, host, port):
        '''
        Return exits that can MOST LIKELY exit to the given host:port. **host**
        can be a hostname, but be warned that we will resolve it locally and
        use the first (arbitrary/unknown order) result when checking exit
        policies, which is different than what other parts of the code may do
        (leaving it up to the exit to resolve the name).

        An exit can only MOST LIKELY not just because of the above DNS
        disconnect, but also because fundamentally our Tor client is most
        likely using microdescriptors which do not have full information about
        exit policies.
        '''
        c = self._controller
        if not is_valid_ipv4_address(host) and not is_valid_ipv6_address(host):
            # It certainly isn't perfect trying to guess if an exit can connect
            # to an ipv4/6 address based on the DNS result we got locally. But
            # it's the best we can do.
            #
            # Also, only use the first ipv4/6 we get even if there is more than
            # one.
            host = resolve(host)[0]
        assert is_valid_ipv4_address(host) or is_valid_ipv6_address(host)
        exits = []
        for exit in self.exits:
            # If we have the exit policy already, easy
            if exit.exit_policy:
                policy = exit.exit_policy
            else:
                # Otherwise ask Tor for the microdescriptor and assume the exit
                # won't work if the desc isn't available
                try:
                    fp = exit.fingerprint
                    policy = c.get_microdescriptor(fp).exit_policy
                except DescriptorUnavailable as e:
                    log.debug(e)
                    continue
            # There's a weird KeyError we sometimes hit when checking
            # policy.can_exit_to()... so catch that and log about it. Maybe
            # someday it can be fixed?
            try:
                if policy is not None and policy.can_exit_to(port=port):
                    exits.append(exit)
            except KeyError as e:
                log.exception('Got that KeyError in stem again...: %s', e)
                continue
        return exits
コード例 #6
0
ファイル: Connections.py プロジェクト: iamhrg/TrackTor
def connections():
    global controller
    args = StaticInfo.args
    control_port = StaticInfo.control_port
    controller = StaticInfo.controller

    if not (controller.is_alive()):
        return

    desc = controller.get_network_status(default = None)
    pid = StaticInfo.pid


    policy = controller.get_exit_policy()
    relays = {}  # address => [orports...]

    for desc in controller.get_network_statuses():
        relays.setdefault(desc.address, []).append(desc.or_port)

    exit_connections = {}  # port => [connections]

    for conn in get_connections(resolver = args.resolver, process_pid = pid):
        global categories
        if conn.protocol == 'udp':
            continue

        if conn.local_port in controller.get_ports(Listener.OR, []):
          categories['INBOUND_OR'].append(conn)
        elif conn.local_port in controller.get_ports(Listener.DIR, []):
          categories['INBOUND_DIR'].append(conn)
        elif conn.local_port in controller.get_ports(Listener.CONTROL, []):
          categories['INBOUND_CONTROL'].append(conn)
        elif conn.remote_port in relays.get(conn.remote_address, []):
          categories['OUTBOUND'].append(conn)
        elif policy.can_exit_to(conn.remote_address, conn.remote_port):
          categories['EXIT'].append(conn)
          exit_connections.setdefault(conn.remote_port, []).append(conn)
        else:
          categories['OUTBOUND'].append(conn)
    circ = controller.get_circuits([])
    for conn in circ:
        categories['CIRCUIT'].append(conn)


    if exit_connections:
        total_ipv4, total_ipv6 = 0, 0

        for port in sorted(exit_connections):
          connections = exit_connections[port]
          ipv4_count = len([conn for conn in connections if is_valid_ipv4_address(conn.remote_address)])
          ipv6_count = len(connections) - ipv4_count
          total_count = len(connections)
          total_ipv4, total_ipv6 = total_ipv4 + ipv4_count, total_ipv6 + ipv6_count

          usage = port_usage(port)
          label = '%s (%s)' % (port, usage) if usage else port
コード例 #7
0
ファイル: remote.py プロジェクト: patrickod/stem
  def from_cache():
    """
    Provides fallback directory information cached with Stem. Unlike
    :func:`~stem.descriptor.remote.FallbackDirectory.from_remote` this doesn't
    have any system requirements, and is faster too. Only drawback is that
    these fallback directories are only as up to date as the Stem release we're
    using.

    :returns: **dict** of **str** fingerprints to their
      :class:`~stem.descriptor.remote.FallbackDirectory`
    """

    conf = stem.util.conf.Config()
    conf.load(CACHE_PATH)

    results = {}

    for fingerprint in set([key.split('.')[0] for key in conf.keys()]):
      if fingerprint in ('tor_commit', 'stem_commit'):
        continue

      attr = {}

      for attr_name in ('address', 'or_port', 'dir_port', 'orport6_address', 'orport6_port'):
        key = '%s.%s' % (fingerprint, attr_name)
        attr[attr_name] = conf.get(key)

        if not attr[attr_name] and not attr_name.startswith('orport6_'):
          raise IOError("'%s' is missing from %s" % (key, CACHE_PATH))

      if not connection.is_valid_ipv4_address(attr['address']):
        raise IOError("'%s.address' was an invalid IPv4 address (%s)" % (fingerprint, attr['address']))
      elif not connection.is_valid_port(attr['or_port']):
        raise IOError("'%s.or_port' was an invalid port (%s)" % (fingerprint, attr['or_port']))
      elif not connection.is_valid_port(attr['dir_port']):
        raise IOError("'%s.dir_port' was an invalid port (%s)" % (fingerprint, attr['dir_port']))
      elif attr['orport6_address'] and not connection.is_valid_ipv6_address(attr['orport6_address']):
        raise IOError("'%s.orport6_address' was an invalid IPv6 address (%s)" % (fingerprint, attr['orport6_address']))
      elif attr['orport6_port'] and not connection.is_valid_port(attr['orport6_port']):
        raise IOError("'%s.orport6_port' was an invalid port (%s)" % (fingerprint, attr['orport6_port']))

      if attr['orport6_address'] and attr['orport6_port']:
        orport_v6 = (attr['orport6_address'], int(attr['orport6_port']))
      else:
        orport_v6 = None

      results[fingerprint] = FallbackDirectory(
        address = attr['address'],
        or_port = int(attr['or_port']),
        dir_port = int(attr['dir_port']),
        fingerprint = fingerprint,
        orport_v6 = orport_v6,
      )

    return results
コード例 #8
0
  def from_cache():
    """
    Provides fallback directory information cached with Stem. Unlike
    :func:`~stem.descriptor.remote.FallbackDirectory.from_remote` this doesn't
    have any system requirements, and is faster too. Only drawback is that
    these fallback directories are only as up to date as the Stem release we're
    using.

    :returns: **dict** of **str** fingerprints to their
      :class:`~stem.descriptor.remote.FallbackDirectory`
    """

    conf = stem.util.conf.Config()
    conf.load(CACHE_PATH)

    results = {}

    for fingerprint in set([key.split('.')[0] for key in conf.keys()]):
      if fingerprint in ('tor_commit', 'stem_commit'):
        continue

      attr = {}

      for attr_name in ('address', 'or_port', 'dir_port', 'orport6_address', 'orport6_port'):
        key = '%s.%s' % (fingerprint, attr_name)
        attr[attr_name] = conf.get(key)

        if not attr[attr_name] and not attr_name.startswith('orport6_'):
          raise IOError("'%s' is missing from %s" % (key, CACHE_PATH))

      if not connection.is_valid_ipv4_address(attr['address']):
        raise IOError("'%s.address' was an invalid IPv4 address (%s)" % (fingerprint, attr['address']))
      elif not connection.is_valid_port(attr['or_port']):
        raise IOError("'%s.or_port' was an invalid port (%s)" % (fingerprint, attr['or_port']))
      elif not connection.is_valid_port(attr['dir_port']):
        raise IOError("'%s.dir_port' was an invalid port (%s)" % (fingerprint, attr['dir_port']))
      elif attr['orport6_address'] and not connection.is_valid_ipv6_address(attr['orport6_address']):
        raise IOError("'%s.orport6_address' was an invalid IPv6 address (%s)" % (fingerprint, attr['orport6_address']))
      elif attr['orport6_port'] and not connection.is_valid_port(attr['orport6_port']):
        raise IOError("'%s.orport6_port' was an invalid port (%s)" % (fingerprint, attr['orport6_port']))

      if attr['orport6_address'] and attr['orport6_port']:
        orport_v6 = (attr['orport6_address'], int(attr['orport6_port']))
      else:
        orport_v6 = None

      results[fingerprint] = FallbackDirectory(
        address = attr['address'],
        or_port = int(attr['or_port']),
        dir_port = int(attr['dir_port']),
        fingerprint = fingerprint,
        orport_v6 = orport_v6,
      )

    return results
コード例 #9
0
ファイル: events.py プロジェクト: patrickod/stem
  def _parse(self):
    if self.type not in ('server', 'client'):
      raise stem.ProtocolError("Transport type should either be 'server' or 'client': %s" % self)

    if not connection.is_valid_ipv4_address(self.address) and \
       not connection.is_valid_ipv6_address(self.address):
      raise stem.ProtocolError("Transport address isn't a valid IPv4 or IPv6 address: %s" % self)

    if not connection.is_valid_port(self.port):
      raise stem.ProtocolError('Transport port is invalid: %s' % self)

    self.port = int(self.port)
コード例 #10
0
 def can_exit_to(self, host, port):
     '''
     Returns if this relay can MOST LIKELY exit to the given host:port.
     **host** can be a hostname, but be warned that we will resolve it
     locally and use the first (arbitrary/unknown order) result when
     checking exit policies, which is different than what other parts of the
     code may do (leaving it up to the exit to resolve the name).
     '''
     if not self.exit_policy:
         return False
     assert isinstance(host, str)
     assert isinstance(port, int)
     if not is_valid_ipv4_address(host) and not is_valid_ipv6_address(host):
         # It certainly isn't perfect trying to guess if an exit can connect
         # to an ipv4/6 address based on the DNS result we got locally. But
         # it's the best we can do.
         #
         # Also, only use the first ipv4/6 we get even if there is more than
         # one.
         host = resolve(host)[0]
     assert is_valid_ipv4_address(host) or is_valid_ipv6_address(host)
     return self.exit_policy.can_exit_to(host, port)
コード例 #11
0
ファイル: events.py プロジェクト: Foxboron/stem
    def _parse(self):
        if self.type not in ('server', 'client'):
            raise stem.ProtocolError(
                "Transport type should either be 'server' or 'client': %s" %
                self)

        if not connection.is_valid_ipv4_address(self.address) and \
           not connection.is_valid_ipv6_address(self.address):
            raise stem.ProtocolError(
                "Transport address isn't a valid IPv4 or IPv6 address: %s" %
                self)

        if not connection.is_valid_port(self.port):
            raise stem.ProtocolError('Transport port is invalid: %s' % self)

        self.port = int(self.port)
コード例 #12
0
    def from_remote(timeout=60):
        """
    Reads and parses tor's latest fallback directories `from
    gitweb.torproject.org
    <https://gitweb.torproject.org/tor.git/plain/src/or/fallback_dirs.inc>`_.
    Note that while convenient, this reliance on GitWeb means you should alway
    call with a fallback, such as...

    ::

      try:
        fallback_directories = stem.descriptor.remote.from_remote()
      except IOError:
        fallback_directories = stem.descriptor.remote.from_cache()

    :param int timeout: seconds to wait before timing out the request

    :returns: **dict** of **str** fingerprints to their
      :class:`~stem.descriptor.remote.FallbackDirectory`

    :raises: **IOError** if unable to retrieve the fallback directories
    """

        try:
            fallback_dir_page = str_tools._to_unicode(
                urllib.urlopen(GITWEB_FALLBACK_DIR_URL,
                               timeout=timeout).read())
        except:
            exc = sys.exc_info()[1]
            raise IOError(
                "Unable to download tor's fallback directories from %s: %s" %
                (GITWEB_FALLBACK_DIR_URL, exc))

        # Example of an entry...
        #
        #   "5.175.233.86:80 orport=443 id=5525D0429BFE5DC4F1B0E9DE47A4CFA169661E33"
        #   " ipv6=[2a03:b0c0:0:1010::a4:b001]:9001"
        #   " weight=43680",

        results, attr = {}, {}

        for line in fallback_dir_page.splitlines():
            if line.startswith('"'):
                addr_line_match = re.match(
                    '"([\d\.]+):(\d+) orport=(\d+) id=([\dA-F]{40}).*', line)
                ipv6_line_match = re.match('" ipv6=\[([\da-f:]+)\]:(\d+)"',
                                           line)

                if addr_line_match:
                    address, dir_port, or_port, fingerprint = addr_line_match.groups(
                    )

                    if not connection.is_valid_ipv4_address(address):
                        raise IOError('%s has an invalid IPv4 address: %s' %
                                      (fingerprint, address))
                    elif not connection.is_valid_port(or_port):
                        raise IOError('%s has an invalid or_port: %s' %
                                      (fingerprint, or_port))
                    elif not connection.is_valid_port(dir_port):
                        raise IOError('%s has an invalid dir_port: %s' %
                                      (fingerprint, dir_port))
                    elif not tor_tools.is_valid_fingerprint(fingerprint):
                        raise IOError('%s has an invalid fingerprint: %s' %
                                      (fingerprint, fingerprint))

                    attr = {
                        'address': address,
                        'or_port': int(or_port),
                        'dir_port': int(dir_port),
                        'fingerprint': fingerprint,
                    }
                elif ipv6_line_match:
                    address, port = ipv6_line_match.groups()

                    if not connection.is_valid_ipv6_address(address):
                        raise IOError('%s has an invalid IPv6 address: %s' %
                                      (fingerprint, address))
                    elif not connection.is_valid_port(port):
                        raise IOError(
                            '%s has an invalid ORPort for its IPv6 endpoint: %s'
                            % (fingerprint, port))

                    attr['orport_v6'] = (address, int(port))
                elif line.startswith('" weight=') and 'fingerprint' in attr:
                    results[attr.get('fingerprint')] = FallbackDirectory(
                        address=attr.get('address'),
                        or_port=attr.get('or_port'),
                        dir_port=attr.get('dir_port'),
                        fingerprint=attr.get('fingerprint'),
                        orport_v6=attr.get('orport_v6'),
                    )

                    attr = {}

        return results
コード例 #13
0
ファイル: ps.py プロジェクト: toralf/torutils
def main():
  ctrlport = 9051
  resolver = 'proc'

  parser = argparse.ArgumentParser()
  parser.add_argument("--ctrlport", help="default: " + str(ctrlport))
  parser.add_argument("--resolver", help="default: " + resolver)
  args = parser.parse_args()

  if args.ctrlport:
    ctrlport = int(args.ctrlport)

  if args.resolver:
    resolver= str(args.resolver)

  with Controller.from_port(port=ctrlport) as controller:
    controller.authenticate()

    try:
      ControlPort = int(controller.get_conf("ControlPort"))
      ORPort   = None
      ORPort6  = None
      DirPort  = None
      DirPort6 = None

      for address, port in controller.get_listeners(Listener.OR):
        if is_valid_ipv4_address(address):
          ORPort = port
        else:
          ORPort6 = port

      for address, port in controller.get_listeners(Listener.DIR):
        if is_valid_ipv4_address(address):
          DirPort = port
        else:
          DirPort6 = port

    except Exception as Exc:
      print ("Woops, control ports aren't configured")
      print (Exc)
      return

    # we will ignore changes of relays during the runtime of this script
    #
    relays = {}
    for s in controller.get_network_statuses():
      relays.setdefault(s.address, []).append(s.or_port)

    MaxOpened = {}  # hold the maximum amount of opened  ports
    MaxClosed = {}  # hold the maximum amount of closed  ports
    MaxAll    = {}  # hold the maximum amount of overall ports

    Curr = {}   # the current network connections of Tor

    # avoid useless calculation of mean immediately after start
    #
    first = 1

    while True:
      # read in all allowed exit ports
      #
      exit_ports = []
      for filename in glob.glob("/etc/tor/torrc.d/*") + (glob.glob("/etc/tor/*")):
        if os.path.isfile(filename):
          inputfile = open(filename)
          lines = inputfile.readlines()
          inputfile.close()
          for line in lines:
            if line.startswith("ExitPolicy accept "):
              for word in line.split():
                if '*:' in word:    # do consider classX ports
                  port = int (word.split(':')[1])
                  exit_ports.append(port)

      try:
        t1 = time.time()

        Prev = Curr.copy()
        Curr.clear()

        pid = controller.get_info("process/pid")
        connections = get_connections(resolver=resolver, process_pid=pid,process_name='tor')

        t2 = time.time()

        policy = controller.get_exit_policy()
        for conn in connections:
          laddr, raddr = conn.local_address, conn.remote_address
          lport, rport = conn.local_port,    conn.remote_port

          # ignore incoming connections
          #
          if (lport == ORPort  and laddr == '5.9.158.75') or (lport == ORPort6  and laddr == '2a01:4f8:190:514a::2'):
              continue
          if (lport == DirPort and laddr == '5.9.158.75') or (lport == DirPort6 and laddr == '2a01:4f8:190:514a::2'):
              continue

          if raddr in relays:
            if rport in relays[raddr]:
              continue

          if not policy.can_exit_to(raddr, rport):
            continue

          # store the connections itself instead just counting them here
          # b/c we have to calculate the diff of 2 sets later
          #
          Curr.setdefault(rport, []).append(str(lport)+':'+raddr)

        if first == 1:
          Prev = Curr.copy()

        dt = t2-t1

        os.system('clear')
        print ("  port     # opened closed     max                ( %s:%s, %i conns %.2f sec ) " % (resolver, ctrlport, len(connections), dt))
        lines = 0;
        ports = set(list(Curr.keys()) + list(Prev.keys()) + list(MaxAll.keys()))
        for port in sorted(ports):
          if port in Prev:
            p = set(Prev[port])
          else:
            p = set({})
          if port in Curr:
            c = set(Curr[port])
          else:
            c = set({})

          n_curr = len(c)
          n_opened = len(c-p)
          n_closed = len(p-c)

          MaxAll.setdefault(port, 0)
          MaxOpened.setdefault(port, 0)
          MaxClosed.setdefault(port, 0)

          if first == 0:
            if MaxAll[port] < n_curr:
              MaxAll[port]    = n_curr
            if MaxOpened[port] < n_opened:
              MaxOpened[port] = n_opened
            if MaxClosed[port] < n_closed:
              MaxClosed[port] = n_closed

          stri = " %5i %5i %6i %6i   %6i %6i %6i  (%s)" % (port, n_curr, n_opened, n_closed, MaxAll[port], MaxOpened[port], MaxClosed[port], port_usage(port))
          print (stri.replace(' 0', '  '))

          lines += 1
          if lines % 5 == 0:
            print

        first = 0

      except KeyboardInterrupt:
        break
コード例 #14
0
ファイル: info.py プロジェクト: toralf/torutils
def main():
  ctrlport = 9051
  resolver = 'proc'

  #handler = logging.FileHandler('/tmp/stem_debug')
  #handler.setFormatter(logging.Formatter(
    #fmt = '%(asctime)s [%(levelname)s] %(message)s',
    #datefmt = '%m/%d/%Y %H:%M:%S',
  #))

  #log = stem.util.log.get_logger()
  #log.setLevel(logging.DEBUG)
  #log.addHandler(handler)

  #stem.util.connection.LOG_CONNECTION_RESOLUTION = True

  parser = argparse.ArgumentParser()
  parser.add_argument("--ctrlport", help="default: " + str(ctrlport))
  parser.add_argument("--resolver", help="default: " + resolver)
  args = parser.parse_args()

  if args.ctrlport:
    ctrlport = int(args.ctrlport)

  if args.resolver:
    resolver= str(args.resolver)

  with Controller.from_port(port=ctrlport) as controller:
    controller.authenticate()

    try:
      ControlPort = int(controller.get_conf("ControlPort"))
      ORPort   = None
      ORPort6  = None
      DirPort  = None
      DirPort6 = None

      for address, port in controller.get_listeners(Listener.OR):
        if is_valid_ipv4_address(address):
          ORPort = port
        else:
          ORPort6 = port

      for address, port in controller.get_listeners(Listener.DIR):
        if is_valid_ipv4_address(address):
          DirPort = port
        else:
          DirPort6 = port

    except Exception as Exc:
      print ("Woops, control ports aren't configured")
      return

    # our version, uptime and flags
    #
    version = str(controller.get_version()).split()[0]
    uptime = 0
    flags = ''

    try:
      descriptor = controller.get_server_descriptor()
      uptime = descriptor.uptime
      flags = controller.get_network_status(relay=descriptor.fingerprint).flags
    except Exception as Exc:
      print (Exc)

    print (" %s   %s   %s" % (version, datetime.timedelta(seconds=uptime), "  ".join(flags)))

    policy = controller.get_exit_policy()

    pid = controller.get_info("process/pid")
    connections = get_connections(resolver=resolver,process_pid=pid,process_name='tor')
    print (" resolver=%s  pid=%s  conns=%i" % (resolver, pid, len(connections)))

    relaysOr  = {}
    relaysDir = {}
    for s in controller.get_network_statuses():
      relaysOr.setdefault(s.address, []).append(s.or_port)
      relaysDir.setdefault(s.address, []).append(s.dir_port)

    # classify network connections by port and relationship to the Tor relay
    #
    ports_int = {}
    ports_ext = {}

    def inc_ports (ports, t):
      v4, v6 = ports.get(t,(0,0))
      if conn.is_ipv6:
        ports[t] = (v4, v6+1)
      else:
        ports[t] = (v4+1, v6)

    def inc_ports_int (description):
      t = (description)
      inc_ports (ports_int, t)

    def inc_ports_ext (description):
      t = (description, rport)
      inc_ports (ports_ext, t)

    # classify each connection
    #
    for conn in connections:
      if conn.protocol == 'udp':
          continue

      laddr, raddr = conn.local_address, conn.remote_address
      lport, rport = conn.local_port,    conn.remote_port

      if raddr in relaysOr:
        if (lport == ORPort and not conn.is_ipv6) or (lport == ORPort6 and conn.is_ipv6):
          inc_ports_int('ORPort   <= relay')
        elif (lport == DirPort and not conn.is_ipv6) or (lport == DirPort6 and conn.is_ipv6):
          inc_ports_int('DirPort   <= relay')
        elif rport in relaysOr[raddr]:
          inc_ports_int('=> relay ORPort')
        elif rport in relaysDir[raddr]:
          inc_ports_int('=> relay DirPort')
        else:
          # a system hosts beside a Tor relay another service too
          #
          inc_ports_ext ('=> relay port')

      elif policy.can_exit_to(raddr, rport):
        inc_ports_ext ('=> exit')

      else:
        if (lport == ORPort and not conn.is_ipv6)    or (lport == ORPort6 and conn.is_ipv6):
          inc_ports_int('ORPort   <= outer')
        elif (lport == DirPort and not conn.is_ipv6) or (lport == DirPort6 and conn.is_ipv6):
          inc_ports_int('DirPort  <= outer')
        elif lport == ControlPort:
          inc_ports_int('CtrlPort <= local')
        else:
          inc_ports_ext ('=> non exit port')

    print ()
    print ('  description         port   ipv4  ipv6  servicename')
    print ('  -----------------  -----   ----  ----  -------------')

    sum4 = 0
    sum6 = 0
    for t in sorted(ports_int):
      description = t
      v4, v6 = ports_int[t]
      sum4 += v4
      sum6 += v6
      print ("  %-17s  %5s  %5s %5s" % (description, '', str(v4) if v4 > 0 else '', str(v6) if v6 > 0 else ''))

    print ("")

    exit4 = 0
    exit6 = 0

    for t in sorted(ports_ext):
      description, port = t
      v4, v6 = ports_ext[t]
      sum4 += v4
      sum6 += v6

      if description == '=> exit':
        exit4 += v4
        exit6 += v6

      print ("  %-17s  %5i  %5s %5s  %s" % (description, port, str(v4) if v4 > 0 else '', str(v6) if v6 > 0 else '', port_usage(port)))

    print ("")

    print ("  %17s  %5s  %5i %5i" % ('sum', '', sum4, sum6))
    print ("  %17s  %5s  %5i %5i" % ('exits among them', '', exit4, exit6))
コード例 #15
0
ファイル: ps.py プロジェクト: toralf/torutils
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--ctrlport',
                        type=int,
                        help='default: 9051',
                        default=9051)
    parser.add_argument('--resolver', help='default: autodetect', default='')
    args = parser.parse_args()

    with Controller.from_port(port=args.ctrlport) as controller:
        controller.authenticate()

        try:
            ORPort = None
            ORPort6 = None

            for address, port in controller.get_listeners(Listener.OR):
                if is_valid_ipv4_address(address):
                    ORPort = port
                else:
                    ORPort6 = port

        except Exception as Exc:
            print('Woops, control ports aren\'t configured')
            print(Exc)
            return

        relays = {}  # address => [orports...]
        relays = parse_consensus(relays, '/var/lib/tor/data/cached-consensus')
        relays = parse_consensus(relays, '/var/lib/tor/data2/cached-consensus')

        MaxOpened = {}  # hold the maximum amount of opened  ports
        MaxClosed = {}  # hold the maximum amount of closed  ports
        MaxAll = {}  # hold the maximum amount of overall ports

        Curr = {}  # the current network connections of Tor

        # avoid useless calculation of mean immediately after start
        #
        first = True

        while True:
            # read in all allowed exit ports
            #
            exit_ports = []
            for filename in glob.glob('/etc/tor/torrc.d/*') + (
                    glob.glob('/etc/tor/*')):
                if os.path.isfile(filename):
                    inputfile = open(filename)
                    lines = inputfile.readlines()
                    inputfile.close()
                    for line in lines:
                        if line.startswith('ExitPolicy    *accept '):
                            accept = line.split()[2]
                            if ':' in accept:
                                port = accept.split(':')[1]
                                if '-' in port:
                                    min = port.split('-')[0]
                                    max = port.split('-')[1]
                                    for port in range(int(min), int(max)):
                                        exit_ports.append(port)
                                else:
                                    exit_ports.append(port)

            try:
                t1 = time.time()

                pid = controller.get_info('process/pid')
                connections = get_connections(resolver=args.resolver,
                                              process_pid=pid,
                                              process_name='tor')
                t2 = time.time()
                policy = controller.get_exit_policy()

                if not first:
                    Prev = Curr.copy()
                    Curr.clear()

                my_ipv4 = '5.9.158.75'
                my_ipv6 = ipaddress.IPv6Address(
                    '2a01:4f8:190:514a::2').exploded
                for conn in connections:
                    laddr, raddr = conn.local_address, conn.remote_address
                    lport, rport = conn.local_port, conn.remote_port

                    # ignore incoming connections
                    #
                    if conn.is_ipv6:
                        if lport == ORPort6:
                            if laddr == my_ipv6:
                                continue
                    else:
                        if lport == ORPort:
                            if laddr == my_ipv4:
                                continue

                    if raddr in relays:
                        if rport in relays[raddr]:
                            continue

                    if not policy.can_exit_to(raddr, rport):
                        continue

                    # store the connections itself instead just counting them here
                    # b/c we have to calculate the diff of 2 sets later too
                    #
                    Curr.setdefault(rport, []).append(str(lport) + ':' + raddr)

                dt = t2 - t1

                os.system('clear')
                print(
                    '  port     # opened closed      max                ( %s:%s, %i conns %.2f sec )'
                    % (args.resolver, args.ctrlport, len(connections), dt))

                if first:
                    Prev = Curr.copy()

                ports = sorted(
                    set(
                        list(Curr.keys()) + list(Prev.keys()) +
                        list(MaxAll.keys())))
                for port in ports:
                    c = set({})
                    p = set({})
                    if port in Prev:
                        p = set(Prev[port])
                    if port in Curr:
                        c = set(Curr[port])

                    n_curr = len(c)
                    n_opened = len(c - p)
                    n_closed = len(p - c)

                    MaxAll.setdefault(port, 0)
                    MaxOpened.setdefault(port, 0)
                    MaxClosed.setdefault(port, 0)

                    if not first:
                        if MaxAll[port] < n_curr:
                            MaxAll[port] = n_curr
                        if MaxOpened[port] < n_opened:
                            MaxOpened[port] = n_opened
                        if MaxClosed[port] < n_closed:
                            MaxClosed[port] = n_closed

                    stri = ' %5i %5i %6i %6i   %6i %6i %6i  (%s)' % (
                        port, n_curr, n_opened, n_closed, MaxAll[port],
                        MaxOpened[port], MaxClosed[port], port_usage(port))
                    print(stri.replace(' 0', '  '))

                first = False

            except KeyboardInterrupt:
                break
            except Exception:
                continue
コード例 #16
0
ファイル: remote.py プロジェクト: E3V3A/stem
    def _parse_v2(fallback_dir_page):
        # Example of an entry...
        #
        #   "5.9.110.236:9030 orport=9001 id=0756B7CD4DFC8182BE23143FAC0642F515182CEB"
        #   " ipv6=[2a01:4f8:162:51e2::2]:9001"
        #   /* nickname=rueckgrat */
        #   /* extrainfo=1 */

        results, attr = {}, {}

        for line in fallback_dir_page.splitlines():
            addr_line_match = re.match(
                '"([\d\.]+):(\d+) orport=(\d+) id=([\dA-F]{40}).*', line)
            nickname_match = re.match('/\* nickname=(\S+) \*/', line)
            has_extrainfo_match = re.match('/\* extrainfo=([0-1]) \*/', line)
            ipv6_line_match = re.match('" ipv6=\[([\da-f:]+)\]:(\d+)"', line)

            if addr_line_match:
                address, dir_port, or_port, fingerprint = addr_line_match.groups(
                )

                if not connection.is_valid_ipv4_address(address):
                    raise IOError('%s has an invalid IPv4 address: %s' %
                                  (fingerprint, address))
                elif not connection.is_valid_port(or_port):
                    raise IOError('%s has an invalid or_port: %s' %
                                  (fingerprint, or_port))
                elif not connection.is_valid_port(dir_port):
                    raise IOError('%s has an invalid dir_port: %s' %
                                  (fingerprint, dir_port))
                elif not tor_tools.is_valid_fingerprint(fingerprint):
                    raise IOError('%s has an invalid fingerprint: %s' %
                                  (fingerprint, fingerprint))

                attr = {
                    'address': address,
                    'or_port': int(or_port),
                    'dir_port': int(dir_port),
                    'fingerprint': fingerprint,
                }
            elif ipv6_line_match:
                address, port = ipv6_line_match.groups()

                if not connection.is_valid_ipv6_address(address):
                    raise IOError('%s has an invalid IPv6 address: %s' %
                                  (fingerprint, address))
                elif not connection.is_valid_port(port):
                    raise IOError(
                        '%s has an invalid ORPort for its IPv6 endpoint: %s' %
                        (fingerprint, port))

                attr['orport_v6'] = (address, int(port))
            elif nickname_match:
                nickname = nickname_match.group(1)

                if not tor_tools.is_valid_nickname(nickname):
                    raise IOError('%s has an invalid nickname: %s' %
                                  (fingerprint, nickname))

                attr['nickname'] = nickname
            elif has_extrainfo_match:
                attr['has_extrainfo'] = has_extrainfo_match.group(1) == '1'

                results[attr.get('fingerprint')] = FallbackDirectory(
                    address=attr.get('address'),
                    or_port=attr.get('or_port'),
                    dir_port=attr.get('dir_port'),
                    fingerprint=attr.get('fingerprint'),
                    nickname=attr.get('nickname'),
                    has_extrainfo=attr.get('has_extrainfo', False),
                    orport_v6=attr.get('orport_v6'),
                )

                attr = {}

        return results
コード例 #17
0
ファイル: remote.py プロジェクト: E3V3A/stem
    def _parse_v1(fallback_dir_page):
        # Example of an entry...
        #
        #   "5.175.233.86:80 orport=443 id=5525D0429BFE5DC4F1B0E9DE47A4CFA169661E33"
        #   " ipv6=[2a03:b0c0:0:1010::a4:b001]:9001"
        #   " weight=43680",

        # TODO: this method can be removed once gitweb provides a v2 formatted document

        results, attr = {}, {}

        for line in fallback_dir_page.splitlines():
            if line.startswith('"'):
                addr_line_match = re.match(
                    '"([\d\.]+):(\d+) orport=(\d+) id=([\dA-F]{40}).*', line)
                ipv6_line_match = re.match('" ipv6=\[([\da-f:]+)\]:(\d+)"',
                                           line)

                if addr_line_match:
                    address, dir_port, or_port, fingerprint = addr_line_match.groups(
                    )

                    if not connection.is_valid_ipv4_address(address):
                        raise IOError('%s has an invalid IPv4 address: %s' %
                                      (fingerprint, address))
                    elif not connection.is_valid_port(or_port):
                        raise IOError('%s has an invalid or_port: %s' %
                                      (fingerprint, or_port))
                    elif not connection.is_valid_port(dir_port):
                        raise IOError('%s has an invalid dir_port: %s' %
                                      (fingerprint, dir_port))
                    elif not tor_tools.is_valid_fingerprint(fingerprint):
                        raise IOError('%s has an invalid fingerprint: %s' %
                                      (fingerprint, fingerprint))

                    attr = {
                        'address': address,
                        'or_port': int(or_port),
                        'dir_port': int(dir_port),
                        'fingerprint': fingerprint,
                    }
                elif ipv6_line_match:
                    address, port = ipv6_line_match.groups()

                    if not connection.is_valid_ipv6_address(address):
                        raise IOError('%s has an invalid IPv6 address: %s' %
                                      (fingerprint, address))
                    elif not connection.is_valid_port(port):
                        raise IOError(
                            '%s has an invalid ORPort for its IPv6 endpoint: %s'
                            % (fingerprint, port))

                    attr['orport_v6'] = (address, int(port))
                elif line.startswith('" weight=') and 'fingerprint' in attr:
                    results[attr.get('fingerprint')] = FallbackDirectory(
                        address=attr.get('address'),
                        or_port=attr.get('or_port'),
                        dir_port=attr.get('dir_port'),
                        fingerprint=attr.get('fingerprint'),
                        orport_v6=attr.get('orport_v6'),
                    )

                    attr = {}

        return results
コード例 #18
0
ファイル: relay_connections.py プロジェクト: zmchu/stem
def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('--ctrlport', help='default: 9051 or 9151')
    parser.add_argument('--resolver', help='default: autodetected')
    args = parser.parse_args(args)

    control_port = int(args.ctrlport) if args.ctrlport else 'default'
    controller = stem.connection.connect(control_port=('127.0.0.1',
                                                       control_port))

    if not controller:
        return

    desc = controller.get_network_status(default=None)
    pid = controller.get_pid()

    print(
        HEADER_LINE.format(
            version=str(controller.get_version()).split()[0],
            uptime=stem.util.str_tools.short_time_label(
                time.time() - stem.util.system.start_time(pid)),
            flags=', '.join(desc.flags if desc else ['none']),
        ))

    policy = controller.get_exit_policy()
    relays = {}  # address => [orports...]

    for desc in controller.get_network_statuses():
        relays.setdefault(desc.address, []).append(desc.or_port)

    # categorize our connections

    categories = collections.OrderedDict((
        (INBOUND_ORPORT, []),
        (INBOUND_DIRPORT, []),
        (INBOUND_CONTROLPORT, []),
        (OUTBOUND_ORPORT, []),
        (OUTBOUND_EXIT, []),
        (OUTBOUND_UNKNOWN, []),
    ))

    exit_connections = {}  # port => [connections]

    for conn in get_connections(resolver=args.resolver, process_pid=pid):
        if conn.protocol == 'udp':
            continue

        if conn.local_port in controller.get_ports(Listener.OR, []):
            categories[INBOUND_ORPORT].append(conn)
        elif conn.local_port in controller.get_ports(Listener.DIR, []):
            categories[INBOUND_DIRPORT].append(conn)
        elif conn.local_port in controller.get_ports(Listener.CONTROL, []):
            categories[INBOUND_CONTROLPORT].append(conn)
        elif conn.remote_port in relays.get(conn.remote_address, []):
            categories[OUTBOUND_ORPORT].append(conn)
        elif policy.can_exit_to(conn.remote_address, conn.remote_port):
            categories[OUTBOUND_EXIT].append(conn)
            exit_connections.setdefault(conn.remote_port, []).append(conn)
        else:
            categories[OUTBOUND_UNKNOWN].append(conn)

    print(DIV)
    print(COLUMN % ('Type', 'IPv4', 'IPv6'))
    print(DIV)

    total_ipv4, total_ipv6 = 0, 0

    for label, connections in categories.items():
        if len(connections) == 0:
            continue

        ipv4_count = len([
            conn for conn in connections
            if is_valid_ipv4_address(conn.remote_address)
        ])
        ipv6_count = len(connections) - ipv4_count

        total_ipv4, total_ipv6 = total_ipv4 + ipv4_count, total_ipv6 + ipv6_count
        print(COLUMN % (label, ipv4_count, ipv6_count))

    print(DIV)
    print(COLUMN % ('Total', total_ipv4, total_ipv6))
    print(DIV)
    print('')

    if exit_connections:
        print(DIV)
        print(COLUMN % ('Exit Port', 'IPv4', 'IPv6'))
        print(DIV)

        total_ipv4, total_ipv6 = 0, 0

        for port in sorted(exit_connections):
            connections = exit_connections[port]
            ipv4_count = len([
                conn for conn in connections
                if is_valid_ipv4_address(conn.remote_address)
            ])
            ipv6_count = len(connections) - ipv4_count
            total_ipv4, total_ipv6 = total_ipv4 + ipv4_count, total_ipv6 + ipv6_count

            usage = port_usage(port)
            label = '%s (%s)' % (port, usage) if usage else port

            print(COLUMN % (label, ipv4_count, ipv6_count))

        print(DIV)
        print(COLUMN % ('Total', total_ipv4, total_ipv6))
        print(DIV)
        print('')