[tor-commits] [stem/master] Add demo for getting a relay conneciton summary

atagar at torproject.org atagar at torproject.org
Fri Dec 22 20:23:04 UTC 2017


commit 843facd89a35658a750dddfba86d0dfcddd6fe69
Author: Damian Johnson <atagar at torproject.org>
Date:   Fri Dec 22 12:21:35 2017 -0800

    Add demo for getting a relay conneciton summary
    
    Revising a neat stem script by toralf that provides a summary of your relay's
    connections.
---
 docs/_static/example/load_test.py                 |  25 +++++
 docs/_static/example/relay_connections.py         | 129 ++++++++++++++++++++++
 docs/change_log.rst                               |   6 +
 docs/contents.rst                                 |   1 +
 docs/tutorials/double_double_toil_and_trouble.rst |   8 ++
 docs/tutorials/examples/relay_connections.rst     |  48 ++++++++
 6 files changed, 217 insertions(+)

diff --git a/docs/_static/example/load_test.py b/docs/_static/example/load_test.py
new file mode 100644
index 00000000..e98e4c00
--- /dev/null
+++ b/docs/_static/example/load_test.py
@@ -0,0 +1,25 @@
+import os
+import time
+
+import stem.control
+import stem.util.proc
+import stem.util.str_tools
+
+start_time = time.time()
+samplings = []
+last_sample = None
+
+with stem.control.Controller.from_port() as controller:
+  controller.authenticate()
+  controller.add_event_listener(lambda *args: None, 'DEBUG')
+
+  while True:
+    utime, stime = stem.util.proc.stats(os.getpid(), stem.util.proc.Stat.CPU_UTIME, stem.util.proc.Stat.CPU_STIME)
+    total_cpu_time = float(utime) + float(stime)
+
+    if last_sample:
+      samplings.append(total_cpu_time - last_sample)
+      print '%0.1f%% (%s)' % (sum(samplings) / len(samplings) * 100, stem.util.str_tools.time_label(time.time() - start_time))
+
+    last_sample = total_cpu_time
+    time.sleep(1)
diff --git a/docs/_static/example/relay_connections.py b/docs/_static/example/relay_connections.py
new file mode 100755
index 00000000..42c22fa5
--- /dev/null
+++ b/docs/_static/example/relay_connections.py
@@ -0,0 +1,129 @@
+import argparse
+import collections
+import time
+
+import stem.connection
+import stem.util.system
+import stem.util.str_tools
+
+from stem.control import Listener
+from stem.util.connection import get_connections, port_usage, is_valid_ipv4_address
+
+HEADER_LINE = " {version}   uptime: {uptime}   flags: {flags}\n"
+
+DIV = '+%s+%s+%s+' % ('-' * 30, '-' * 6, '-' * 6)
+COLUMN = '| %-28s | %4s | %4s |'
+
+INBOUND_ORPORT = 'Inbound to our ORPort'
+INBOUND_DIRPORT = 'Inbound to our DirPort'
+INBOUND_CONTROLPORT = 'Inbound to our ControlPort'
+
+OUTBOUND_ORPORT = 'Outbound to a relay'
+OUTBOUND_EXIT = 'Outbound exit traffic'
+OUTBOUND_UNKNOWN = 'Outbound uncategorized'
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument("--ctrlport", help="default: 9051 or 9151")
+  parser.add_argument("--resolver", help="default: autodetected")
+  args = parser.parse_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
+
+  connections = 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, []):
+      connections[INBOUND_ORPORT].append(conn)
+    elif conn.local_port in controller.get_ports(Listener.DIR, []):
+      connections[INBOUND_DIRPORT].append(conn)
+    elif conn.local_port in controller.get_ports(Listener.CONTROL, []):
+      connections[INBOUND_CONTROLPORT].append(conn)
+    elif conn.remote_port in relays.get(conn.remote_address, []):
+      connections[OUTBOUND_ORPORT].append(conn)
+    elif policy.can_exit_to(conn.remote_address, conn.remote_port):
+      connections[OUTBOUND_EXIT].append(conn)
+      exit_connections.setdefault(conn.remote_port, []).append(conn)
+    else:
+      connections[OUTBOUND_UNKNOWN].append(conn)
+
+  print(DIV)
+  print(COLUMN % ('Type', 'IPv4', 'IPv6'))
+  print(DIV)
+
+  total_ipv4, total_ipv6 = 0, 0
+
+  for label, connections in connections.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):
+      ipv4_count = len([conn for conn in connections if is_valid_ipv4_address(conn.remote_address)])
+      ipv6_count = len(exit_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('')
+
+
+if __name__ == '__main__':
+  main()
diff --git a/docs/change_log.rst b/docs/change_log.rst
index 13597155..3985dfcb 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -49,6 +49,12 @@ The following are only available within Stem's `git repository
   * Added support for limiting the maximum number of streams to :func:`~stem.control.Controller.create_ephemeral_hidden_service` (:spec:`2fcb1c2`)
   * Stacktrace if :func:`stem.connection.connect` had a string port argument
 
+ * **Website**
+
+  * Added `terminal styling <tutorials/east_of_the_sun.html#terminal-styling>`_ to our utilities tutorial
+  * Added `multiprocessing <tutorials/east_of_the_sun.html#multiprocessing>`_ to our utilities tutorial
+  * Added a `relay connection summary example <tutorials/examples/relay_connections.html>`_
+
 .. _version_1.6:
 
 Version 1.6 (November 5th, 2017)
diff --git a/docs/contents.rst b/docs/contents.rst
index 5cbd5bf2..c9c38ebf 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -17,6 +17,7 @@ Contents
    tutorials/examples/compare_flags
    tutorials/examples/exit_used
    tutorials/examples/list_circuits
+   tutorials/examples/relay_connections
    tutorials/examples/outdated_relays
    tutorials/examples/persisting_a_consensus
    tutorials/examples/votes_by_bandwidth_authorities
diff --git a/docs/tutorials/double_double_toil_and_trouble.rst b/docs/tutorials/double_double_toil_and_trouble.rst
index 111952c6..48d665aa 100644
--- a/docs/tutorials/double_double_toil_and_trouble.rst
+++ b/docs/tutorials/double_double_toil_and_trouble.rst
@@ -99,6 +99,14 @@ Client Usage
 
   Tells you the exit used for each Tor connection.
 
+Relays
+------
+
+* `Connection Summary <examples/relay_connections.html>`_
+
+  Provides a summary of your inbound and outbound connections and exiting
+  usage.
+
 Descriptors
 -----------
 
diff --git a/docs/tutorials/examples/relay_connections.rst b/docs/tutorials/examples/relay_connections.rst
new file mode 100644
index 00000000..c389f9aa
--- /dev/null
+++ b/docs/tutorials/examples/relay_connections.rst
@@ -0,0 +1,48 @@
+Connection Summary
+==================
+
+.. image:: /_static/buttons/back.png
+   :target: ../double_double_toil_and_trouble.html
+
+The following provides a summary of your relay's inbound and outbound
+connections. Couple important notes...
+
+  * To use this you must set **DisableDebuggerAttachment 0** in your torrc.
+    Otherwise connection information will be unavailable.
+
+  * **Be careful about the data you look at.** Inspection of client and exit
+    traffic especially is wiretapping and not only unethical but likely
+    illegal.
+
+    That said, a general overview like this should be fine.
+
+.. literalinclude:: /_static/example/relay_connections.py
+   :language: python
+
+::
+
+  % relay_connections.py --ctrlport 29051
+
+   0.3.2.0-alpha-dev   uptime: 01:20:44   flags: none
+
+  +------------------------------+------+------+
+  | Type                         | IPv4 | IPv6 |
+  +------------------------------+------+------+
+  | Inbound to our ORPort        | 2400 |    3 |
+  | Inbound to our DirPort       |   12 |    0 |
+  | Inbound to our ControlPort   |    2 |    0 |
+  | Outbound to a relay          |  324 |    0 |
+  | Outbound exit traffic        |    3 |    0 |
+  +------------------------------+------+------+
+  | Total                        | 2741 |    3 |
+  +------------------------------+------+------+
+
+  +------------------------------+------+------+
+  | Exit Port                    | IPv4 | IPv6 |
+  +------------------------------+------+------+
+  | 443 (HTTPS)                  |    1 |    0 |
+  | 8443 (PCsync HTTPS)          |    1 |    0 |
+  | 54682                        |    1 |    0 |
+  +------------------------------+------+------+
+  | Total                        |    3 |    0 |
+  +------------------------------+------+------+



More information about the tor-commits mailing list