commit c0423382890576b92bb55121bfbc394ad941cf98 Author: Arturo Filastò hellais@torproject.org Date: Mon May 28 23:40:13 2012 +0200
Implement parts of OONI Backend. * Write an HTTP server that replies with the headers sent by the browser * Write a Proxy DNS server that proxies requests and writes to log --- backend/dnsbackend.py | 16 ++++++++++ backend/httpbackend.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ backend/oonibackend.py | 34 ++++++++++++++++++++++ plugoo/tests.py | 16 ++-------- 4 files changed, 128 insertions(+), 12 deletions(-)
diff --git a/backend/__init__.py b/backend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/dnsbackend.py b/backend/dnsbackend.py new file mode 100644 index 0000000..689d1a4 --- /dev/null +++ b/backend/dnsbackend.py @@ -0,0 +1,16 @@ +from twisted.internet.protocol import Factory, Protocol +from twisted.internet import reactor +from twisted.names import dns +from twisted.names import client, server + +class ProxyDNSServer(server.DNSServerFactory): + def __init__(self, authorities = None, + caches = None, clients = None, + verbose = 0): + resolver = client.Resolver(servers=[('8.8.8.8', 53)]) + server.DNSServerFactory.__init__(self, authorities = authorities, + caches = caches, clients = [resolver], + verbose = verbose) + def handleQuery(self, message, protocol, address): + print message, protocol, address + server.DNSServerFactory.handleQuery(self, message, protocol, address) diff --git a/backend/httpbackend.py b/backend/httpbackend.py new file mode 100644 index 0000000..79a487b --- /dev/null +++ b/backend/httpbackend.py @@ -0,0 +1,74 @@ +import json +import random +import string + +from twisted.application import internet, service +from twisted.internet import protocol, reactor, defer +from twisted.protocols import basic +from twisted.web import resource, server, static +from twisted.web.microdom import escape + +server.version = "Apache" + +class HTTPRandomPage(resource.Resource): + """ + This generates a random page of arbitrary length and containing the string + selected by the user. + The format is the following: + /random/<length>/<keyword> + """ + isLeaf = True + def _gen_random_string(self, length): + return ''.join(random.choice(string.letters) for x in range(length)) + + def genRandomPage(self, length=100, keyword=None): + data = self._gen_random_string(length/2) + if keyword: + data += keyword + data += self._gen_random_string(length - length/2) + data += '\n' + return data + + def render(self, request): + length = 100 + keyword = None + path_parts = request.path.split('/') + if len(path_parts) > 2: + length = int(path_parts[2]) + if length > 100000: + length = 100000 + + if len(path_parts) > 3: + keyword = escape(path_parts[3]) + + return self.genRandomPage(length, keyword) + +class HTTPReturnHeaders(resource.Resource): + """ + This returns the headers being sent by the client in JSON format. + """ + isLeaf = True + def render(self, request): + req_headers = request.getAllHeaders() + return json.dumps(req_headers) + +class HTTPSendHeaders(resource.Resource): + """ + This sends to the client the headers that they send inside of the POST + request encoded in json. + """ + isLeaf = True + def render_POST(self, request): + headers = json.loads(request.content.read()) + for header, value in headers.items(): + request.setHeader(str(header), str(value)) + return '' + +class HTTPBackend(resource.Resource): + def __init__(self): + resource.Resource.__init__(self) + self.putChild('random', HTTPRandomPage()) + self.putChild('returnheaders', HTTPReturnHeaders()) + self.putChild('sendheaders', HTTPSendHeaders()) + + diff --git a/backend/oonibackend.py b/backend/oonibackend.py new file mode 100644 index 0000000..774a9c5 --- /dev/null +++ b/backend/oonibackend.py @@ -0,0 +1,34 @@ +""" + ooni backend + ************ + + This is the backend system responsible for running certain services that + are useful for censorship detection. +""" +import json +import random +import string + +from twisted.application import internet, service +from twisted.internet import protocol, reactor, defer +from twisted.protocols import basic +from twisted.web import resource, server, static +from twisted.web.microdom import escape +from twisted.names import dns + +from backend.httpbackend import HTTPBackend +from backend.dnsbackend import ProxyDNSServer + +# This tells twisted to set the +server.version = "Apache" + +application = service.Application('oonibackend') +serviceCollection = service.IServiceCollection(application) +internet.TCPServer(8000, server.Site(HTTPBackend())).setServiceParent(serviceCollection) + +# Start the DNS Server related services +TCPDNSServer = ProxyDNSServer() +internet.TCPServer(8002, TCPDNSServer).setServiceParent(serviceCollection) +UDPFactory = dns.DNSDatagramProtocol(TCPDNSServer) +internet.UDPServer(5353, UDPFactory).setServiceParent(serviceCollection) + diff --git a/plugoo/tests.py b/plugoo/tests.py index 39adfa2..09363a2 100644 --- a/plugoo/tests.py +++ b/plugoo/tests.py @@ -186,20 +186,16 @@ class TwistedTest(object): result['start_time'] = self.start_time result['end_time'] = self.end_time result['run_time'] = self.end_time - self.start_time - return self.d.callback(result)
def _do_experiment(self): - self.d_experiment = defer.Deferred() - self.d_experiment.addCallback(self._do_control) - self.experiment() + self.d = defer.maybeDeferred(self.experiment) + self.d.addCallback(self.control) + self.d.addCallback(self.finished) return self.d
- def _do_control(self, exp): - self.control(exp) - self.finished(dict()) - def control(self, exp): print "Doing control..." + self.d.callback(result)
def experiment(self): print "Doing experiment" @@ -207,10 +203,6 @@ class TwistedTest(object):
def startTest(self): print "Starting test %s" % repr(self) - self.d = defer.Deferred() - result = {} - #reactor.callLater(2.0, self.finished, result) - # Start experiment return self._do_experiment()
class TwistedTestFactory(object):