[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [ooni-probe/master] Implement censorship detection for fingerprint
commit d249c7ff695b0efdb4dd23a0a4bc6756024f7f19
Author: Arturo Filastò <hellais@xxxxxxxxxxxxxx>
Date: Wed Jul 11 12:37:23 2012 +0200
Implement censorship detection for fingerprint
* Move part of b0wser to a ooni protocol
---
ooni/protocols/b0wser.py | 104 ++++++++++++++++++++++++++++++++++++++++
oonib/b0wser.py | 118 ++++++++++++----------------------------------
2 files changed, 134 insertions(+), 88 deletions(-)
diff --git a/ooni/protocols/b0wser.py b/ooni/protocols/b0wser.py
new file mode 100644
index 0000000..ae6b002
--- /dev/null
+++ b/ooni/protocols/b0wser.py
@@ -0,0 +1,104 @@
+from ooni.utils import log
+
+class Mutator:
+ idx = 0
+ step = 0
+
+ waiting = False
+ waiting_step = 0
+
+ def __init__(self, steps):
+ """
+ @param steps: array of dicts containing as keys data and wait. Data is
+ the content of the ith packet to be sent and wait is how
+ much we should wait before mutating the packet of the
+ next step.
+ """
+ self.steps = steps
+
+ def _mutate(self, data, idx):
+ """
+ Mutate the idx bytes by increasing it's value by one
+
+ @param data: the data to be mutated.
+
+ @param idx: what byte should be mutated.
+ """
+ print "idx: %s, data: %s" % (idx, data)
+ ret = data[:idx]
+ ret += chr(ord(data[idx]) + 1)
+ ret += data[idx+1:]
+ return ret
+
+ def state(self):
+ """
+ Return the current mutation state. As in what bytes are being mutated.
+
+ Returns a dict containg the packet index and the step number.
+ """
+ return {'idx': self.idx, 'step': self.step}
+
+ def next_mutation(self):
+ """
+ Increases by one the mutation state.
+
+ ex. (* is the mutation state, i.e. the byte to be mutated)
+ before [___*] [____]
+ step1 step2
+ after [____] [*___]
+
+ Should be called every time you need to proceed onto the next mutation.
+ It changes the internal state of the mutator to that of the next
+ mutatation.
+
+ returns True if another mutation is available.
+ returns False if all the possible mutations have been done.
+ """
+ if self.step > len(self.steps):
+ self.waiting = True
+ return False
+
+ self.idx += 1
+ current_idx = self.idx
+ current_step = self.step
+ current_data = self.steps[current_step]['data']
+ data_to_receive = self.steps[current_step]['wait']
+
+ if self.waiting and self.waiting_step == data_to_receive:
+ log.debug("I am no longer waiting.")
+ self.waiting = False
+ self.waiting_step = 0
+ self.idx = 0
+
+ elif self.waiting:
+ log.debug("Waiting some more.")
+ self.waiting_step += 1
+
+ elif current_idx >= len(current_data):
+ log.debug("Entering waiting mode.")
+ self.step += 1
+ self.idx = 0
+ self.waiting = True
+ log.debug("current index %s" % current_idx)
+ log.debug("current data %s" % len(current_data))
+ return True
+
+ def get_mutation(self, step):
+ """
+ Returns the current packet to be sent to the wire.
+ If no mutation is necessary it will return the plain data.
+ Should be called when you are interested in obtaining the data to be
+ sent for the selected state.
+
+ @param step: the current step you want the mutation for
+
+ returns the mutated packet for the specified step.
+ """
+ if step != self.step or self.waiting:
+ log.debug("I am not going to do anything :)")
+ return self.steps[step]['data']
+
+ data = self.steps[step]['data']
+ print "Mutating %s with idx %s" % (data, self.idx)
+ return self._mutate(data, self.idx)
+
diff --git a/oonib/b0wser.py b/oonib/b0wser.py
index 186c9a4..6da1997 100644
--- a/oonib/b0wser.py
+++ b/oonib/b0wser.py
@@ -1,100 +1,19 @@
from twisted.internet import protocol
+from twisted.internet.error import ConnectionDone
-class Mutator:
- idx = 0
- step = 0
-
- waiting = False
- waiting_step = 0
-
- def __init__(self, steps):
- self.steps = steps
-
- def _mutate(self, data, idx):
- """
- Mutate the idx bytes by increasing it's value by one
-
- @param data: the data to be mutated.
-
- @param idx: what byte should be mutated.
- """
- print "idx: %s, data: %s" % (idx, data)
- ret = data[:idx]
- ret += chr(ord(data[idx]) + 1)
- ret += data[idx+1:]
- return ret
-
- def next_mutation(self):
- """
- Increases by one the mutation state.
-
- ex. (* is the mutation state, i.e. the byte to be mutated)
- before [___*] [____]
- step1 step2
- after [____] [*___]
-
- Should be called every time you need to proceed onto the next mutation.
- It changes the internal state of the mutator to that of the next
- mutatation.
-
- returns True if another mutation is available.
- returns False if all the possible mutations have been done.
- """
- if self.step > len(self.steps):
- self.waiting = True
- return False
-
- self.idx += 1
- current_idx = self.idx
- current_step = self.step
- current_data = self.steps[current_step]['data']
- data_to_receive = self.steps[current_step]['wait']
-
- if self.waiting and self.waiting_step == data_to_receive:
- print "I am no longer waiting..."
- self.waiting = False
- self.waiting_step = 0
- self.idx = 0
-
- elif self.waiting:
- print "Waiting some more..."
- self.waiting_step += 1
-
- elif current_idx >= len(current_data):
- print "Entering waiting mode..."
- self.step += 1
- self.idx = 0
- self.waiting = True
- print "current index %s current data %s" % (current_idx, len(current_data))
- return True
-
- def get_mutation(self, state):
- """
- Returns the current packet to be sent to the wire.
- If no mutation is necessary it will return the plain data.
- Should be called when you are interested in obtaining the data to be
- sent for the selected state.
-
- @param step: the current step you want the mutation for
-
- returns the mutated packet for the specified step.
- """
- if step != self.step or self.waiting:
- print "I am not going to do anything :)"
- return self.steps[step]['data']
-
- data = self.steps[step]['data']
- print "Mutating %s with idx %s" % (data, self.idx)
- return self._mutate(data, self.idx)
+from ooni.plugoo import reports
+from ooni.protocols.b0wser import Mutator
class B0wserProtocol(protocol.Protocol):
steps = [{'data': "STEP1", 'wait': 4},
{'data': "STEP2", 'wait': 4},
{'data': "STEP3", 'wait': 4}]
-
mutator = None
+
state = 0
+ total_states = len(steps) - 1
received_data = 0
+ report = reports.Report('b0wser', 'b0wser.yamlooni')
def next_state(self):
data = self.mutator.get_mutation(self.state)
@@ -111,6 +30,28 @@ class B0wserProtocol(protocol.Protocol):
print "Moving to next state %s" % self.state
self.next_state()
+ def censorship_detected(self, report):
+ print "The connection was closed because of %s" % report['reason']
+ print "I may have matched the censorship fingerprint"
+ print "State %s, Mutator %s" % (report['proto_state'],
+ report['mutator_state'])
+ self.report(report)
+
+
+ def connectionLost(self, reason):
+ report = {'reason': reason, 'proto_state': self.state,
+ 'mutator_state': self.mutator.state(), 'trigger': None}
+
+ if self.state < self.total_states:
+ report['trigger'] = 'did not finish state walk'
+ self.censorship_detected(report)
+
+ if reason.check(ConnectionDone):
+ print "Connection closed cleanly"
+ else:
+ report['trigger'] = 'unclean connection closure'
+ self.censorship_detected(report)
+
class B0wserServer(protocol.ServerFactory):
protocol = B0wserProtocol
mutations = {}
@@ -122,7 +63,8 @@ class B0wserServer(protocol.ServerFactory):
self.mutations[addr.host] = Mutator(p.steps)
else:
print "Moving on to next mutation"
- self.mutations[addr.host].next_mutation()
+ if not self.mutations[addr.host].next_mutation():
+ self.mutations.pop(addr.host)
p.mutator = self.mutations[addr.host]
return p
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits