[tor-commits] [stem/master] Add SocksPatch to socksify network-using Python code

atagar at torproject.org atagar at torproject.org
Sun Dec 23 00:32:17 UTC 2012


commit 270f173deddd2e3dded794d23306f1f32b78d400
Author: Sean Robinson <seankrobinson at gmail.com>
Date:   Mon Dec 17 20:03:29 2012 -0700

    Add SocksPatch to socksify network-using Python code
    
    A context manager which helps re-direct network socket traffic, from
    existing code, through the tor process.
    
    Signed-off-by: Sean Robinson <seankrobinson at gmail.com>
---
 test/network.py |   39 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/test/network.py b/test/network.py
index 6ab17f5..6f81e9d 100644
--- a/test/network.py
+++ b/test/network.py
@@ -8,13 +8,20 @@ the tor network.
     +- SocksError - Reports problems returned by the SOCKS proxy.
   
   Socks - Communicate through a SOCKS5 proxy with a socket interface
+  
+  SocksPatch - Force socket-using code to use :class: `~test.network.Socks`
 """
 
+import functools
 import socket
 import struct
 
 import stem.util.connection
 
+# Store a reference to the original class so we can find it after
+# monkey patching.
+_socket_socket = socket.socket
+
 SOCKS5_NOAUTH_GREETING = (0x05, 0x01, 0x00)
 SOCKS5_NOAUTH_RESPONSE = (0x05, 0x00)
 SOCKS5_CONN_BY_IPV4 = (0x05, 0x01, 0x00, 0x01)
@@ -52,7 +59,7 @@ class SocksError(ProxyError):
       code = self.code
     return "[%s] %s" % (code, self._ERROR_MESSAGE[code])
 
-class Socks(socket.socket):
+class Socks(_socket_socket):
   """
   A **socket.socket**-like interface through a SOCKS5 proxy connection.
   Tor does not support proxy authentication, so neither does this class.
@@ -181,7 +188,7 @@ class Socks(socket.socket):
     :raises: :class:`test.SocksError` for any errors
     """
     
-    socket.socket.connect(self, (self._proxy_addr[0], self._proxy_addr[1]))
+    _socket_socket.connect(self, (self._proxy_addr[0], self._proxy_addr[1]))
     # ask for non-authenticated connection
     self.sendall(self._ints_to_bytes(SOCKS5_NOAUTH_GREETING))
     response = self._bytes_to_ints(self._recvall(2))
@@ -211,3 +218,31 @@ class Socks(socket.socket):
     
     raise NotImplementedError
 
+class SocksPatch(object):
+  """
+  Monkey-patch **socket.socket** to use :class:`~test.network.Socks`, instead.
+  Classes in the patched context (e.g. urllib.urlopen in the example below)
+  do not use the SOCKS5 proxy for domain name resolution and such information
+  may be leaked.
+  
+  ::
+  
+    import urllib
+    from test.network import SocksPatch
+    
+    with SocksPatch(('127.0.0.1', 9050)):
+      with urllib.urlopen("https://www.torproject.org") as f:
+        for line in f.readline():
+          print line
+  """
+  
+  def __init__(self, *args, **kwargs):
+    self._partial = functools.partial(Socks, *args, **kwargs)
+  
+  def __enter__(self):
+    socket.socket = self._partial
+    return self
+  
+  def __exit__(self, exit_type, value, traceback):
+    socket.socket = _socket_socket
+





More information about the tor-commits mailing list