[Pkg-privacy-commits] [obfsproxy] 243/353: Use twisted.internet.threads.deferToThread in the obfs3 handshake.

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 13:02:05 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 5e33045abddcc2e825cee2af3691647b33199112
Author: Yawning Angel <yawning at schwanenlied.me>
Date:   Sun Feb 23 03:02:20 2014 +0000

    Use twisted.internet.threads.deferToThread in the obfs3 handshake.
    
    This cuts the amount of time that is spent doing UniformDH related work in the
    context of the main event loop in half.  It is impossible to eliminate it
    entirely as the client and server both send the public keys immediately on
    connection when doing an obfs3 handshake.
    
    Notable changes:
     * self.dh.get_secret() is processed in a Twisted worker thread.
     * Another state is added as part of the handshake process for when the thread
       is running.
     * At each step of the handshake process, if there is data remaining unprocessed
       the next stage is direcly invoked at the tail of each routine.
       * After the handshake is done, if data is pending, self._scan_for_magic()
         is called.
       * After the magic is found, if data is pending, we relay the remaining data
         immediately.
---
 ChangeLog                     |  5 +++++
 obfsproxy/transports/obfs3.py | 48 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9b315af..1f910cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Changes in version 0.2.7 - UNRELEASED
+ - obfs3 now uses twisted.internet.threads.deferToThread to process the key
+   exchange outside of the main event loop.  Patch by Yawning Angel.
+
+
 Changes in version 0.2.6 - 2014-02-03
  - Stop having 'gmpy' as a hard dependency by removing it from setup.py.
    Now gmpy is only used if it was already installed on the system.
diff --git a/obfsproxy/transports/obfs3.py b/obfsproxy/transports/obfs3.py
index 0b6e6e8..6a4df6b 100644
--- a/obfsproxy/transports/obfs3.py
+++ b/obfsproxy/transports/obfs3.py
@@ -14,6 +14,8 @@ import obfsproxy.common.log as logging
 import obfsproxy.common.hmac_sha256 as hmac_sha256
 import obfsproxy.common.rand as rand
 
+from twisted.internet import threads
+
 log = logging.get_obfslogger()
 
 MAX_PADDING = 8194
@@ -23,8 +25,9 @@ KEYLEN = 16  # is the length of the key used by E(K,s) -- that is, 16.
 HASHLEN = 32 # length of output of sha256
 
 ST_WAIT_FOR_KEY = 0 # Waiting for public key from the other party
-ST_SEARCHING_MAGIC = 1 # Waiting for magic strings from the other party
-ST_OPEN = 2 # obfs3 handshake is complete. Sending application data.
+ST_WAIT_FOR_HANDSHAKE = 1 # Waiting for the DH handshake
+ST_SEARCHING_MAGIC = 2 # Waiting for magic strings from the other party
+ST_OPEN = 3 # obfs3 handshake is complete. Sending application data.
 
 class Obfs3Transport(base.BaseTransport):
     """
@@ -107,6 +110,9 @@ class Obfs3Transport(base.BaseTransport):
         if self.state == ST_WAIT_FOR_KEY: # Looking for the other peer's pubkey
             self._read_handshake(data)
 
+        if self.state == ST_WAIT_FOR_HANDSHAKE: # Doing the exp mod
+            return
+
         if self.state == ST_SEARCHING_MAGIC: # Looking for the magic string
             self._scan_for_magic(data)
 
@@ -118,7 +124,7 @@ class Obfs3Transport(base.BaseTransport):
     def _read_handshake(self, data):
         """
         Read handshake message, parse the other peer's public key and
-        set up our crypto.
+        schedule the key exchange for execution outside of the event loop.
         """
 
         log_prefix = "obfs3:_read_handshake()"
@@ -131,10 +137,32 @@ class Obfs3Transport(base.BaseTransport):
         # Get the public key from the handshake message, do the DH and
         # get the shared secret.
         other_pubkey = data.read(PUBKEY_LEN)
-        try:
-            self.shared_secret = self.dh.get_secret(other_pubkey)
-        except ValueError:
-            raise base.PluggableTransportError("obfs3: Corrupted public key '%s'" % repr(other_pubkey))
+
+        # Do the UniformDH handshake asynchronously
+        self.d = threads.deferToThread(self.dh.get_secret, other_pubkey)
+        self.d.addCallback(self._read_handshake_post_dh, other_pubkey, data)
+        self.d.addErrback(self._uniform_dh_errback, other_pubkey)
+
+        self.state = ST_WAIT_FOR_HANDSHAKE
+
+    def _uniform_dh_errback(self, failure, other_pubkey):
+        """
+        Worker routine that does the actual UniformDH key exchange.  We need to
+        call it from a defered so that it does not block the main event loop.
+        """
+
+        self.circuit.close()
+        e = failure.trap(ValueError)
+        log.warning("obfs3: Corrupted public key '%s'" % repr(other_pubkey))
+
+    def _read_handshake_post_dh(self, shared_secret, other_pubkey, data):
+        """
+        Setup the crypto from the calculated shared secret, and complete the
+        obfs3 handshake.
+        """
+
+        self.shared_secret = shared_secret
+        log_prefix = "obfs3:_read_handshake_post_dh()"
         log.debug("Got public key: %s.\nGot shared secret: %s" %
                   (repr(other_pubkey), repr(self.shared_secret)))
 
@@ -156,6 +184,9 @@ class Obfs3Transport(base.BaseTransport):
         self.circuit.downstream.write(message)
 
         self.state = ST_SEARCHING_MAGIC
+        if len(data) > 0:
+             log.debug("%s: Processing %d bytes of handshake data remaining after key." % (log_prefix, len(data)))
+             self._scan_for_magic(data)
 
     def _scan_for_magic(self, data):
         """
@@ -181,6 +212,9 @@ class Obfs3Transport(base.BaseTransport):
         data.drain(index)
 
         self.state = ST_OPEN
+        if len(data) > 0:
+            log.debug("%s: Processing %d bytes of application data remaining after magic." % (log_prefix, len(data)))
+            self.circuit.upstream.write(self.recv_crypto.crypt(data.read()))
 
     def _derive_crypto(self, pad_string):
         """

-- 
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