[Pkg-privacy-commits] [obfsproxy] 274/353: Add suport for connecting via SOCKS4(a)/SOCKS5 using txsocksx

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 13:02:10 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository obfsproxy.

commit 10cd8870adde32e7f2fa9a2376d8706522f33f88
Author: Yawning Angel <yawning at schwanenlied.me>
Date:   Wed Mar 19 09:45:50 2014 +0000

    Add suport for connecting via SOCKS4(a)/SOCKS5 using txsocksx
    
    Patch originally by Arturo Filasto, with changes by Yawning Angel.  This
    patch depends on pyptlib modifications as it also supports using the
    managed TOR_PT_PROXY enviornment variable.
    
    WARNING: Attempting to use a http proxy will break mysteriously as the
    connect routines are just stubbed out.
---
 ChangeLog                    |  5 ++++
 obfsproxy/common/settings.py |  5 ++++
 obfsproxy/managed/client.py  |  9 +++++++
 obfsproxy/network/network.py | 56 +++++++++++++++++++++++++++++++++++++++++++-
 obfsproxy/network/socks.py   | 20 ++++++++++++++--
 obfsproxy/pyobfsproxy.py     | 11 +++++++++
 setup.py                     |  5 ++--
 7 files changed, 106 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0ef5910..da37aca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Changes in version 0.2.8 - UNRELEASED
+ - Support connecting over SOCKS4(a) and SOCKS5.  Based on the patch by
+   Arturo Filasto with changes by Yawning Angel.  Fixes #8956.
+
+
 Changes in version 0.2.7 - 2014-03-15
  - Support SOCKS5 instead of SOCKS4. Patch by Yawning Angel. Fixes #9221.
  - Fix a scramblesuit bug that makes bridges reject a session
diff --git a/obfsproxy/common/settings.py b/obfsproxy/common/settings.py
new file mode 100644
index 0000000..4f58ce8
--- /dev/null
+++ b/obfsproxy/common/settings.py
@@ -0,0 +1,5 @@
+class Config(object):
+    def __init__(self):
+        self.proxy = None
+
+config = Config()
diff --git a/obfsproxy/managed/client.py b/obfsproxy/managed/client.py
index bce5463..ffcdd49 100644
--- a/obfsproxy/managed/client.py
+++ b/obfsproxy/managed/client.py
@@ -6,6 +6,7 @@ from twisted.internet import reactor, error
 import obfsproxy.network.launch_transport as launch_transport
 import obfsproxy.transports.transports as transports
 import obfsproxy.common.log as logging
+import obfsproxy.common.settings as settings
 import obfsproxy.common.transport_config as transport_config
 
 from pyptlib.client import ClientTransportPlugin
@@ -29,6 +30,14 @@ def do_managed_client():
 
     log.debug("pyptlib gave us the following data:\n'%s'", pprint.pformat(ptclient.getDebugData()))
 
+    # Apply the proxy settings if any
+    proxy = ptclient.config.getProxy()
+    if proxy:
+        if settings.config.proxy:
+            log.warning("Proxy specified via commandline and by managed-proxy protocol, using manage-proxy's")
+        settings.config.proxy = proxy
+        ptclient.reportProxySuccess()
+
     for transport in ptclient.getTransports():
 
         # Will hold configuration parameters for the pluggable transport module.
diff --git a/obfsproxy/network/network.py b/obfsproxy/network/network.py
index 4a8b641..3a8d124 100644
--- a/obfsproxy/network/network.py
+++ b/obfsproxy/network/network.py
@@ -1,6 +1,9 @@
 from twisted.internet import reactor
+from twisted.internet.endpoints import HostnameEndpoint
 from twisted.internet.protocol import Protocol, Factory
 
+from txsocksx.client import SOCKS4ClientEndpoint, SOCKS5ClientEndpoint
+
 import obfsproxy.common.log as logging
 import obfsproxy.common.heartbeat as heartbeat
 
@@ -367,7 +370,58 @@ class StaticDestinationServerFactory(Factory):
 
         # XXX instantiates a new factory for each client
         clientFactory = StaticDestinationClientFactory(circuit, self.mode)
-        reactor.connectTCP(self.remote_host, self.remote_port, clientFactory)
+
+        if settings.config.proxy:
+            create_proxy_client(self.remote_host, self.remote_port,
+                                settings.config.proxy,
+                                klass_instance=clientFactory)
+        else:
+            reactor.connectTCP(self.remote_host, self.remote_port, clientFactory)
 
         return StaticDestinationProtocol(circuit, self.mode, addr)
 
+def create_proxy_client(host, port, proxy_spec, klass=None, klass_args=None):
+    """
+    host:
+    the host of the final destination
+    port:
+    the port number of the final destination
+    proxy_spec:
+    the address of the proxy server as a urlparse.SplitResult
+    klass:
+    is either a class or instance
+    klass_args:
+    if specified klass will be treated as a class and will be passed to the class constructor
+
+    Returns a deferred that will fire when the connection to the SOCKS server has been established.
+    """
+
+    log.debug("Connecting via %s proxy %s:%d" % (proxy_spec.scheme, log.safe_addr_str(proxy_spec.hostname), proxy_spec.port))
+
+    if proxy_spec.scheme in ["socks4a", "socks5"]:
+        TCPPoint = HostnameEndpoint(reactor, proxy_spec.hostname, proxy_spec.port)
+        username = proxy_spec.username
+        password = proxy_spec.password
+        if proxy_spec.scheme == "socks4a":
+            if username:
+                assert(password == None)
+                SOCKSPoint = SOCKS4ClientEndpoint(host, port, TCPPoint, user=username)
+            else:
+                SOCKSPoint = SOCKS4ClientEndpoint(host, port, TCPPoint)
+        elif proxy_spec.scheme == "socks5":
+            if username and password:
+                SOCKSPoint = SOCKS5ClientEndpoint(host, port, TCPPoint,
+                                                  methods={'login': (username, password)})
+            else:
+                assert(username == None and password == None)
+                SOCKSPoint = SOCKS5ClientEndpoint(host, port, TCPPoint)
+        if klass_args:
+            d = SOCKSPoint.connect(klass(klass_args))
+        else:
+            d = SOCKSPoint.connect(klass)
+        return d
+    elif proxy_spec.scheme == "http":
+        pass
+    else:
+        # Should *NEVER* happen
+        raise RuntimeError("Invalid proxy scheme %s" % proxy_spec.scheme)
diff --git a/obfsproxy/network/socks.py b/obfsproxy/network/socks.py
index 842e4a5..16b93bf 100644
--- a/obfsproxy/network/socks.py
+++ b/obfsproxy/network/socks.py
@@ -6,6 +6,7 @@ import obfsproxy.common.log as logging
 import obfsproxy.network.network as network
 import obfsproxy.network.socks5 as socks5
 import obfsproxy.transports.base as base
+from obfsproxy.common import settings
 
 
 log = logging.get_obfslogger()
@@ -65,6 +66,16 @@ class OBFSSOCKSv5Outgoing(socks5.SOCKSv5Outgoing, network.GenericProtocol):
         self.buffer.write(data)
         self.circuit.dataReceived(self.buffer, self)
 
+class OBFSSOCKSv5OutgoingFactory(protocol.Factory):
+    """
+    A OBFSSOCKSv5OutgoingFactory, used only when connecting via a proxy
+    """
+
+    def __init__(self, socksProtocol):
+        self.socks = socksProtocol
+
+    def buildProtocol(self, addr):
+        return OBFSSOCKSv5Outgoing(self.socks)
 
 class OBFSSOCKSv5Protocol(socks5.SOCKSv5Protocol, network.GenericProtocol):
     """
@@ -130,10 +141,15 @@ class OBFSSOCKSv5Protocol(socks5.SOCKSv5Protocol, network.GenericProtocol):
         """
         Instantiate the outgoing connection.
 
-        This is overriden so that our sub-classed SOCKSv5Outgoing gets created.
+        This is overriden so that our sub-classed SOCKSv5Outgoing gets created,
+        and a proxy is optionally used for the outgoing connection.
         """
 
-        return protocol.ClientCreator(reactor, OBFSSOCKSv5Outgoing, self).connectTCP(addr, port)
+        if settings.config.proxy:
+            instance = OBFSSOCKSv5OutgoingFactory(self)
+            return network.create_proxy_client(addr, port, settings.config.proxy, klass=instance)
+        else:
+            return protocol.ClientCreator(reactor, OBFSSOCKSv5Outgoing, self).connectTCP(addr, port)
 
     def set_up_circuit(self, otherConn):
         self.circuit.setDownstreamConnection(otherConn)
diff --git a/obfsproxy/pyobfsproxy.py b/obfsproxy/pyobfsproxy.py
index 4227c2f..ce813b0 100755
--- a/obfsproxy/pyobfsproxy.py
+++ b/obfsproxy/pyobfsproxy.py
@@ -18,8 +18,10 @@ import obfsproxy.common.transport_config as transport_config
 import obfsproxy.managed.server as managed_server
 import obfsproxy.managed.client as managed_client
 from obfsproxy import __version__
+from obfsproxy.common import settings
 
 from pyptlib.config import checkClientMode
+from pyptlib.client_config import parseProxyURI
 
 from twisted.internet import task # for LoopingCall
 
@@ -47,6 +49,9 @@ def set_up_cli_parsing():
     parser.add_argument('--data-dir', help='where persistent information should be stored.',
                         default=None)
 
+    parser.add_argument('--proxy', action='store', dest='proxy',
+                        help='Outgoing proxy (<proxy_type>://[<user_name>][:<password>][@]<ip>:<port>)')
+
     # Managed mode is a subparser for now because there are no
     # optional subparsers: bugs.python.org/issue9253
     subparsers.add_parser("managed", help="managed mode")
@@ -104,6 +109,12 @@ def consider_cli_args(args):
         log.disable_logs()
     if args.no_safe_logging:
         log.set_no_safe_logging()
+    if args.proxy:
+        try:
+            settings.config.proxy = parseProxyURI(args.proxy)
+        except Exception as e:
+            log.error("Failed to parse proxy specifier: %s" % e)
+            sys.exit(1)
 
     # validate:
     if (args.name == 'managed') and (not args.log_file) and (args.log_min_severity):
diff --git a/setup.py b/setup.py
index d2d241a..7017e75 100644
--- a/setup.py
+++ b/setup.py
@@ -33,7 +33,8 @@ setup(
         'PyCrypto',
         'Twisted',
         'argparse',
-        'pyptlib >= 0.0.5',
-        'pyyaml'
+        'pyptlib >= 0.0.6',
+        'pyyaml',
+        'txsocksx'
         ],
 )

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/obfsproxy.git



More information about the Pkg-privacy-commits mailing list