[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [obfsproxy/master] Improve packet morphing algorithm.
commit 0806a87f0183b3b74d20fe99184bdfb361d5f443
Author: Philipp Winter <phw@xxxxxxxxxxxxxx>
Date: Mon Mar 10 18:47:15 2014 +0100
Improve packet morphing algorithm.
We only want to run the packet morphing algorithm when we really need
it -- which is immediately before we send data. Previously, we would morph
immediately upon receiving data which is not optimal.
This should fix <https://bugs.torproject.org/10991>. Thanks to Yawning Angel
who pointed out the problem.
---
obfsproxy/transports/scramblesuit/packetmorpher.py | 37 +++++++++++++++++---
obfsproxy/transports/scramblesuit/scramblesuit.py | 31 +++++++---------
2 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/obfsproxy/transports/scramblesuit/packetmorpher.py b/obfsproxy/transports/scramblesuit/packetmorpher.py
index 4a72f0b..081d7dc 100644
--- a/obfsproxy/transports/scramblesuit/packetmorpher.py
+++ b/obfsproxy/transports/scramblesuit/packetmorpher.py
@@ -8,6 +8,7 @@ morphed network data should then match the probability distribution.
import random
+import message
import probdist
import const
@@ -39,14 +40,37 @@ class PacketMorpher( object ):
self.dist = probdist.new(lambda: random.randint(const.HDR_LENGTH,
const.MTU))
+ def getPadding( self, sendCrypter, sendHMAC, dataLen ):
+ """
+ Based on the burst's size, return a ready-to-send padding blurb.
+ """
+
+ padLen = self.calcPadding(dataLen)
+
+ assert const.HDR_LENGTH <= padLen < (const.MTU + const.HDR_LENGTH), \
+ "Invalid padding length %d." % padLen
+
+ # We have to use two padding messages if the padding is > MTU.
+ if padLen > const.MTU:
+ padMsgs = [message.new("", paddingLen=700 - const.HDR_LENGTH),
+ message.new("", paddingLen=padLen - 700 - \
+ const.HDR_LENGTH)]
+ else:
+ padMsgs = [message.new("", paddingLen=padLen - const.HDR_LENGTH)]
+
+ blurbs = [msg.encryptAndHMAC(sendCrypter, sendHMAC) for msg in padMsgs]
+
+ return "".join(blurbs)
+
def calcPadding( self, dataLen ):
"""
- Based on `dataLen', determines the padding for a network packet.
+ Based on `dataLen', determine and return a burst's padding.
- ScrambleSuit morphs packets which are smaller than the link's MTU.
- This method draws a random sample from the probability distribution
- which is used to determine and return the padding for such packets.
- This effectively gets rid of Tor's 586-byte signature.
+ ScrambleSuit morphs the last packet in a burst, i.e., packets which
+ don't fill the link's MTU. This is done by drawing a random sample
+ from our probability distribution which is used to determine and return
+ the padding for such packets. This effectively gets rid of Tor's
+ 586-byte signature.
"""
# The `is' and `should-be' length of the burst's last packet.
@@ -59,6 +83,9 @@ class PacketMorpher( object ):
else:
padLen = (const.MTU - dataLen) + sampleLen
+ if padLen < const.HDR_LENGTH:
+ padLen += const.MTU
+
log.debug("Morphing the last %d-byte packet to %d bytes by adding %d "
"bytes of padding." %
(dataLen % const.MTU, sampleLen, padLen))
diff --git a/obfsproxy/transports/scramblesuit/scramblesuit.py b/obfsproxy/transports/scramblesuit/scramblesuit.py
index 8e04cc5..43b52b5 100644
--- a/obfsproxy/transports/scramblesuit/scramblesuit.py
+++ b/obfsproxy/transports/scramblesuit/scramblesuit.py
@@ -234,27 +234,12 @@ class ScrambleSuitTransport( base.BaseTransport ):
# Wrap the application's data in ScrambleSuit protocol messages.
messages = message.createProtocolMessages(data, flags=flags)
-
- # Let the packet morpher tell us how much we should pad.
- paddingLen = self.pktMorpher.calcPadding(sum([len(msg) for
- msg in messages]))
-
- # If padding > header length, a single message will do...
- if paddingLen > const.HDR_LENGTH:
- messages.append(message.new("", paddingLen=paddingLen -
- const.HDR_LENGTH))
-
- # ...otherwise, we use two padding-only messages.
- else:
- messages.append(message.new("", paddingLen=const.MPU -
- const.HDR_LENGTH))
- messages.append(message.new("", paddingLen=paddingLen))
-
blurb = "".join([msg.encryptAndHMAC(self.sendCrypter,
self.sendHMAC) for msg in messages])
- # Flush data chunk for chunk to obfuscate inter arrival times.
+ # Flush data chunk for chunk to obfuscate inter-arrival times.
if const.USE_IAT_OBFUSCATION:
+
if len(self.choppingBuf) == 0:
self.choppingBuf.write(blurb)
reactor.callLater(self.iatMorpher.randomSample(),
@@ -262,8 +247,12 @@ class ScrambleSuitTransport( base.BaseTransport ):
else:
# flushPieces() is still busy processing the chopping buffer.
self.choppingBuf.write(blurb)
+
else:
- self.circuit.downstream.write(blurb)
+ padBlurb = self.pktMorpher.getPadding(self.sendCrypter,
+ self.sendHMAC,
+ len(blurb))
+ self.circuit.downstream.write(blurb + padBlurb)
def flushPieces( self ):
"""
@@ -283,7 +272,11 @@ class ScrambleSuitTransport( base.BaseTransport ):
# Drain and send whatever is left in the output buffer.
else:
- self.circuit.downstream.write(self.choppingBuf.read())
+ blurb = self.choppingBuf.read()
+ padBlurb = self.pktMorpher.getPadding(self.sendCrypter,
+ self.sendHMAC,
+ len(blurb))
+ self.circuit.downstream.write(blurb + padBlurb)
return
reactor.callLater(self.iatMorpher.randomSample(), self.flushPieces)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits