[tor-commits] [flashproxy/master] Parse relay file.

infinity0 at torproject.org infinity0 at torproject.org
Mon Oct 28 14:47:40 UTC 2013


commit 36b615a7a95b292ac09741861512bce019e00d79
Author: George Kadianakis <desnacked at riseup.net>
Date:   Fri Sep 6 17:23:26 2013 +0300

    Parse relay file.
---
 facilitator/facilitator |   84 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 72 insertions(+), 12 deletions(-)

diff --git a/facilitator/facilitator b/facilitator/facilitator
index 869f62d..8d3f835 100755
--- a/facilitator/facilitator
+++ b/facilitator/facilitator
@@ -33,16 +33,33 @@ class options(object):
     listen_port = DEFAULT_LISTEN_PORT
     log_filename = DEFAULT_LOG_FILENAME
     log_file = sys.stdout
-    relay_spec = None
     daemonize = True
     pid_filename = None
     privdrop_username = None
     safe_logging = True
 
+    # Dictionary containing Tor relays that we can pass to
+    # flashproxies. It looks like this:
+    # {"websocket" : ["1.1.1.1:123"], "obfs3|websocket" : ["3.1.2.3:5555", "1.2.3.4:6666"], "obfs2|websocket" : ["1.2.4.4:5123"]}
+    relays = {}
+
+    @staticmethod
+    def num_relays():
+        """Return the number of registered relays."""
+
+        num_relays = 0
+        for relay_list in options.relays.values():
+            num_relays += len(relay_list)
+
+        return num_relays
+
     @staticmethod
-    def set_relay_spec(spec):
+    def add_relay(transport, spec):
         spec = fac.parse_addr_spec(spec, defport = DEFAULT_RELAY_PORT, resolve = True)
-        options.relay_spec = fac.format_addr(spec)
+        if transport not in options.relays:
+            options.relays[transport] = []
+
+        options.relays[transport].append(fac.format_addr(spec))
 
 def usage(f = sys.stdout):
     print >> f, """\
@@ -57,6 +74,7 @@ again. Listen on 127.0.0.1 and port PORT (by default %(port)d).
       --pidfile FILENAME    write PID to FILENAME after daemonizing.
       --privdrop-user USER  switch UID and GID to those of USER.
   -r, --relay RELAY         send RELAY (host:port) to proxies as the relay to use.
+  -f, --relay-file FILE     learn relays from FILE
       --unsafe-logging      don't scrub IP addresses from logs.\
 """ % {
     "progname": sys.argv[0],
@@ -64,6 +82,14 @@ again. Listen on 127.0.0.1 and port PORT (by default %(port)d).
     "log": DEFAULT_LOG_FILENAME,
 }
 
+def get_outermost_transport(transport):
+    """
+    Given a combined transport name in 'transport', return the name of
+    the outermost transport.
+    e.g. if 'transport' == 'obfs3|websocket' this function returns 'websocket'
+    """
+    return transport.split("|")[-1]
+
 def safe_str(s):
     """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
     if options.safe_logging:
@@ -243,9 +269,9 @@ class Handler(SocketServer.StreamRequestHandler):
             return False
         check_back_in = get_check_back_in_for_proxy(proxy_addr)
         if reg:
-            log(u"proxy gets %s, relay %s (now %d)" %
-                (safe_str(unicode(reg)), options.relay_spec, num_regs()))
-            print >> self.wfile, fac.render_transaction("OK", ("CLIENT", str(reg)), ("RELAY", options.relay_spec), ("CHECK-BACK-IN", str(check_back_in)))
+            log(u"proxy gets %s, num_relays %s (now %d)" %
+                (safe_str(unicode(reg)), options.num_relays(), num_regs()))
+            print >> self.wfile, fac.render_transaction("OK", ("CLIENT", str(reg)), ("RELAY", reg.relay), ("CHECK-BACK-IN", str(check_back_in)))
         else:
             log(u"proxy gets none")
             print >> self.wfile, fac.render_transaction("NONE", ("CHECK-BACK-IN", str(check_back_in)))
@@ -354,9 +380,27 @@ def put_reg(reg):
     REGS = get_regs(af, get_outermost_transport(reg.transport_chain))
     return REGS.add(reg)
 
+def parse_relay_file(fname):
+    """
+    Parse a file containing Tor relays that we can point proxies to.
+    Throws ValueError if the file is not properly formatted.
+    """
+    # File format is:
+    #  <transport> <addrport>
+    # Example:
+    #  obfs2|websocket 1.4.6.1:4123
+    with open(fname) as input:
+        for line in input:
+            words_list = line.split()
+            if len(words_list) != 2:
+                raise ValueError("Wrong line format: %s" % line)
+
+            # XXX Maybe we should validate here
+            options.add_relay(words_list[0], words_list[1])
+
 def main():
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "dhl:p:r:",
-        ["debug", "help", "log=", "port=", "pidfile=", "privdrop-user=", "relay=", "unsafe-logging"])
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "dhl:p:r:f:",
+        ["debug", "help", "log=", "port=", "pidfile=", "privdrop-user=", "relay=", "relay-file=", "unsafe-logging"])
     for o, a in opts:
         if o == "-d" or o == "--debug":
             options.daemonize = False
@@ -374,20 +418,35 @@ def main():
             options.privdrop_username = a
         elif o == "-r" or o == "--relay":
             try:
-                options.set_relay_spec(a)
-            except socket.gaierror, e:
+                options.add_relay("websocket", a)
+            except (ValueError, socket.gaierror) as e:
                 print >> sys.stderr, u"Can't resolve relay %s: %s" % (repr(a), str(e))
                 sys.exit(1)
+        elif o == "-f" or o == "--relay-file":
+            try:
+                parse_relay_file(a)
+            except ValueError as e:
+                print >> sys.stderr, u"Could not parse file '%s': %s" % (repr(a), str(e))
+                sys.exit(1)
         elif o == "--unsafe-logging":
             options.safe_logging = False
 
-    if not options.relay_spec:
+    if not options.relays:
         print >> sys.stderr, """\
 The -r option is required. Give it the relay that will be sent to proxies.
   -r HOST[:PORT]\
     """
         sys.exit(1)
 
+
+    # Create RegSets for our supported transports
+    for transport in options.relays.keys():
+        outermost_transport = get_outermost_transport(transport)
+        if outermost_transport not in REGSETS_IPV4:
+            REGSETS_IPV4[outermost_transport] = RegSet()
+            REGSETS_IPV6[outermost_transport] = RegSet()
+
+    # Setup log file
     if options.log_filename:
         options.log_file = open(options.log_filename, "a")
         # Send error tracebacks to the log.
@@ -400,7 +459,7 @@ The -r option is required. Give it the relay that will be sent to proxies.
     server = Server(addrinfo[4], Handler)
 
     log(u"start on %s" % fac.format_addr(addrinfo[4]))
-    log(u"using relay address %s" % options.relay_spec)
+    log(u"using relays %s" % str(options.relays))
 
     if options.daemonize:
         log(u"daemonizing")
@@ -427,3 +486,4 @@ The -r option is required. Give it the relay that will be sent to proxies.
 
 if __name__ == "__main__":
     main()
+





More information about the tor-commits mailing list