[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [nyx/master] Retrieve connection information despite DisableDebuggerAttachment



commit 53fbe024898e96d9564ba982448f5c048acd0be0
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Sun Jan 31 20:08:40 2016 -0800

    Retrieve connection information despite DisableDebuggerAttachment
    
    For years tor's DisableDebuggerAttachment has been the bane of nyx. The feature
    wasn't intended to effect us, but screws with proc permissions breaking every
    connection resolver we have...
    
      https://trac.torproject.org/projects/tor/ticket/15259
    
    Currently we read /proc/<pid>/fd to get connection inodes, then use that
    determine what from /proc/net/tcp belongs to our process. Tor's
    DisableDebuggerAttachment breaks that by making /proc/<pid>/fd only readable by
    root. However, even without knowing the inodes we can identify tor related
    connections by if they go to a relay or our ORPort/DirPort/ControlPort. This is
    exactly what nyx already does to identify a connection's type.
    
    TL;DR. Connection resolution works all the time now. Only drawbacks are...
    
    * Connection resolution can't work until we have consensus information. This
      can take a few seconds so we don't show connections right away.
    
    * When resolving this way we can't show client or exit connections. Nyx
      already scrubbed these so it's not a big loss, but means we now don't even
      show that they exist.
    
    If the user sets 'DisableDebuggerAttachment 0' in their torrc we still do
    connection resolution via the normal method.
---
 nyx/controller.py    | 33 +++------------------------------
 nyx/util/__init__.py |  4 ++++
 nyx/util/tracker.py  | 37 ++++++++++++++++++++++++++++++++++---
 3 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/nyx/controller.py b/nyx/controller.py
index 7ff6e53..ee647a7 100644
--- a/nyx/controller.py
+++ b/nyx/controller.py
@@ -115,37 +115,10 @@ def init_controller(stdscr, start_time):
   if CONFIG['features.panels.show.connection']:
     page_panels.append([nyx.connection_panel.ConnectionPanel(stdscr)])
 
-    # The DisableDebuggerAttachment will prevent our connection panel from really
-    # functioning. It'll have circuits, but little else. If this is the case then
-    # notify the user and tell them what they can do to fix it.
-
     controller = tor_controller()
-
-    if controller.get_conf('DisableDebuggerAttachment', None) == '1':
-      log.notice("Tor is preventing system utilities like netstat and lsof from working. This means that nyx can't provide you with connection information. You can change this by adding 'DisableDebuggerAttachment 0' to your torrc and restarting tor. For more information see...\nhttps://trac.torproject.org/3313";)
-      nyx.util.tracker.get_connection_tracker().set_paused(True)
-    else:
-      # Configures connection resoultions. This is paused/unpaused according to
-      # if Tor's connected or not.
-
-      controller.add_status_listener(conn_reset_listener)
-
-      tor_pid = controller.get_pid(None)
-
-      if tor_pid:
-        # use the tor pid to help narrow connection results
-        tor_cmd = system.name_by_pid(tor_pid)
-
-        if tor_cmd is None:
-          tor_cmd = 'tor'
-
-        resolver = nyx.util.tracker.get_connection_tracker()
-        log.info('Operating System: %s, Connection Resolvers: %s' % (os.uname()[0], ', '.join(resolver._resolvers)))
-      else:
-        # constructs singleton resolver and, if tor isn't connected, initizes
-        # it to be paused
-
-        nyx.util.tracker.get_connection_tracker().set_paused(not controller.is_alive())
+    controller.add_status_listener(conn_reset_listener)
+    resolver = nyx.util.tracker.get_connection_tracker()
+    log.info('Operating System: %s, Connection Resolvers: %s' % (os.uname()[0], ', '.join(resolver._resolvers)))
 
   # third page: config
 
diff --git a/nyx/util/__init__.py b/nyx/util/__init__.py
index 0f53ab6..a7b2e8d 100644
--- a/nyx/util/__init__.py
+++ b/nyx/util/__init__.py
@@ -31,6 +31,10 @@ TESTING = False
 
 stem.control.CACHEABLE_GETINFO_PARAMS = list(stem.control.CACHEABLE_GETINFO_PARAMS) + ['address']
 
+# disable trace level messages about cache hits
+
+stem.control.LOG_CACHE_FETCHES = False
+
 try:
   uses_settings = stem.util.conf.uses_settings('nyx', os.path.join(BASE_DIR, 'config'), lazy_load = False)
 except IOError as exc:
diff --git a/nyx/util/tracker.py b/nyx/util/tracker.py
index ffd24c9..f218630 100644
--- a/nyx/util/tracker.py
+++ b/nyx/util/tracker.py
@@ -52,7 +52,7 @@ import threading
 
 import stem.control
 
-from stem.util import conf, connection, proc, str_tools, system
+from stem.util import conf, connection, enum, proc, str_tools, system
 
 from nyx.util import log, tor_controller
 
@@ -67,6 +67,10 @@ RESOURCE_TRACKER = None
 PORT_USAGE_TRACKER = None
 CONSENSUS_TRACKER = None
 
+CustomResolver = enum.Enum(
+  ('INFERENCE', 'by inference'),
+)
+
 # Extending stem's Connection tuple with attributes for the uptime of the
 # connection.
 
@@ -476,7 +480,6 @@ class ConnectionTracker(Daemon):
 
     self._connections = []
     self._start_times = {}  # connection => (unix_timestamp, is_legacy)
-    self._resolvers = connection.system_resolvers()
     self._custom_resolver = None
     self._is_first_run = True
 
@@ -486,6 +489,15 @@ class ConnectionTracker(Daemon):
     self._failure_count = 0
     self._rate_too_low_count = 0
 
+    # If 'DisableDebuggerAttachment 0' is set we can do normal connection
+    # resolution. Otherwise connection resolution by inference is the only game
+    # in town.
+
+    if tor_controller().get_conf('DisableDebuggerAttachment', None) == '0':
+      self._resolvers = connection.system_resolvers()
+    else:
+      self._resolvers = [CustomResolver.INFERENCE]
+
   def _task(self, process_pid, process_name):
     if self._custom_resolver:
       resolver = self._custom_resolver
@@ -500,7 +512,26 @@ class ConnectionTracker(Daemon):
       start_time = time.time()
       new_connections, new_start_times = [], {}
 
-      for conn in connection.get_connections(resolver, process_pid = process_pid, process_name = process_name):
+      if resolver == CustomResolver.INFERENCE:
+        # provide connections going to a relay or one of our tor ports
+
+        connections = []
+        controller = tor_controller()
+        consensus_tracker = get_consensus_tracker()
+
+        for conn in proc.connections(user = controller.get_user(None)):
+          if conn.remote_port in consensus_tracker.get_relay_fingerprints(conn.remote_address):
+            connections.append(conn)  # outbound to another relay
+          elif conn.local_port in controller.get_ports(stem.control.Listener.OR, []):
+            connections.append(conn)  # inbound to our ORPort
+          elif conn.local_port in controller.get_ports(stem.control.Listener.DIR, []):
+            connections.append(conn)  # inbound to our DirPort
+          elif conn.local_port in controller.get_ports(stem.control.Listener.CONTROL, []):
+            connections.append(conn)  # controller connection
+      else:
+        connections = connection.get_connections(resolver, process_pid = process_pid, process_name = process_name)
+
+      for conn in connections:
         conn_start_time, is_legacy = self._start_times.get(conn, (start_time, self._is_first_run))
         new_start_times[conn] = (conn_start_time, is_legacy)
         new_connections.append(Connection(conn_start_time, is_legacy, *conn))

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits