[tor-commits] [stem/master] Add is_user_traffic_allowed() to the Controller

atagar at torproject.org atagar at torproject.org
Sat Jul 4 22:55:15 UTC 2015


commit 842da03cdd0cbe424d8aca6e753accf55923b4c8
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Jul 4 15:24:38 2015 -0700

    Add is_user_traffic_allowed() to the Controller
    
    Simple helper method to help users determine if inbound or outbound connections
    are possibly directly servicing users, and by extension private.
---
 docs/change_log.rst |    1 +
 stem/control.py     |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index a6529fd..5eade67 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -47,6 +47,7 @@ The following are only available within Stem's `git repository
   * Dramatic, `300x performance improvement <https://github.com/DonnchaC/stem/pull/1>`_ for reading from the control port with python 3
   * :func:`~stem.connection.connect` and :func:`~stem.control.Controller.from_port` now connect to both port 9051 (relay's default) and 9151 (Tor Browser's default) (:trac:`16075`)
   * Added `support for NETWORK_LIVENESS events <api/response.html#stem.response.events.NetworkLivenessEvent>`_ (:spec:`44aac63`)
+  * Added :func:`~stem.control.Controller.is_user_traffic_allowed` to the :class:`~stem.control.Controller`
   * IPv6 addresses could trigger errors in :func:`~stem.control.Controller.get_listeners`, :class:`~stem.response.events.ORConnEvent`, and quite a few other things (:trac:`16174`)
   * Don't obscure stacktraces, most notably :class:`~stem.control.Controller` getter methods with default values
 
diff --git a/stem/control.py b/stem/control.py
index f08a455..d9693cc 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -81,6 +81,7 @@ If you're fine with allowing your script to raise exceptions then this can be mo
     |- get_protocolinfo - information about the controller interface
     |- get_user - provides the user tor is running as
     |- get_pid - provides the pid of our tor process
+    |- is_user_traffic_allowed - checks if we send or receive direct user traffic
     |
     |- get_microdescriptor - querying the microdescriptor for a relay
     |- get_microdescriptors - provides all currently available microdescriptors
@@ -380,6 +381,11 @@ AccountingStats = collections.namedtuple('AccountingStats', [
   'write_limit',
 ])
 
+UserTrafficAllowed = collections.namedtuple('UserTrafficAllowed', [
+  'inbound',
+  'outbound',
+])
+
 CreateHiddenServiceOutput = collections.namedtuple('CreateHiddenServiceOutput', [
   'path',
   'hostname',
@@ -1494,6 +1500,46 @@ class Controller(BaseController):
     else:
       raise ValueError("Unable to resolve tor's pid" if self.is_localhost() else "Tor isn't running locally")
 
+  def is_user_traffic_allowed(self):
+    """
+    Checks if we're likely to service direct user traffic. This essentially
+    boils down to...
+
+      * If we're a bridge or guard relay, inbound connections are possibly from
+        users.
+
+      * If our exit policy allows traffic then output connections are possibly
+        from users.
+
+    Note the word 'likely'. These is a decent guess in practice, but not always
+    correct. For instance, information about which flags we have are only
+    fetched periodically.
+
+    This method is intended to help you avoid eavesdropping on user traffic.
+    Monitoring user connections is not only unethical, but likely a violation
+    of wiretapping laws.
+
+    .. versionadded:: 1.5.0
+
+    :returns: **namedtuple** with an **inbound** and **outbound** boolean
+      attribute to indicate if we're likely to have user traffic there
+    """
+
+    inbound_allowed, outbound_allowed = False, False
+
+    if self.get_conf('BridgeRelay', None) == '1':
+      inbound_allowed = True
+
+    if self.get_conf('ORPort', None):
+      if not inbound_allowed:
+        consensus_entry = self.get_network_status(default = None)
+        inbound_allowed = consensus_entry and 'Guard' in consensus_entry.flags
+
+      exit_policy = self.get_exit_policy(None)
+      outbound_allowed = exit_policy and exit_policy.is_exiting_allowed()
+
+    return UserTrafficAllowed(inbound_allowed, outbound_allowed)
+
   @with_default()
   def get_microdescriptor(self, relay = None, default = UNDEFINED):
     """





More information about the tor-commits mailing list