[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