diff options
| author | Philipp Winter <phw@nymity.ch> | 2019-04-12 11:46:28 -0700 |
|---|---|---|
| committer | Philipp Winter <phw@nymity.ch> | 2019-04-12 16:17:45 -0700 |
| commit | 9af6c71b3b4aeb56c509df9ae6a16650f9b58dd2 (patch) | |
| tree | 2a0acc0a98982be86f6175652739c3ecab202d65 | |
| parent | bad0bed11a9018f65555b3c6998b26e2cb06f5b5 (diff) | |
Diversify the pluggable transport types.
This patch makes leekspin generate descriptors with various combinations
of pluggable transports. This is necessary to keep BridgeDB's unit
tests working after our fix for bug 28655, in which we make active
probing-resistant bridges not give out transports that aren't resistant
to active probing: <https://bugs.torproject.org/28655>
| -rw-r--r-- | leekspin/extrainfo.py | 39 | ||||
| -rw-r--r-- | leekspin/generator.py | 25 |
2 files changed, 41 insertions, 23 deletions
diff --git a/leekspin/extrainfo.py b/leekspin/extrainfo.py index 26aeb6c..e09e840 100644 --- a/leekspin/extrainfo.py +++ b/leekspin/extrainfo.py @@ -12,8 +12,10 @@ import random from leekspin import const from leekspin import util +# The pluggable transports that we support. +PT_NAMES = ['obfs2', 'obfs3', 'obfs4', 'scramblesuit'] -def generateExtraInfo(nickname, fingerprint, ts, ipv4, port, bridge=True): +def generateExtraInfo(nickname, fingerprint, ts, ipv4, port, bridge=PT_NAMES): """Create an OR extra-info document. See ยง2.2 "Extra-info documents" in dir-spec.txt_. @@ -51,22 +53,25 @@ def generateExtraInfo(nickname, fingerprint, ts, ipv4, port, bridge=True): extra.append(b"dirreq-v3-direct-dl complete=0,timeout=0,running=0") extra.append(b"dirreq-v3-tunneled-dl complete=12,timeout=0,running=0") - if bridge: - scramblesuitPassword = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' - - obfs4iatMode = bytes(random.getrandbits(1)) # 0 or 1 - # hexadecimal, 40 chars long: - obfs4nodeID = hashlib.sha1(bytes(random.getrandbits(8))).hexdigest() - # hexadecimal, 64 chars long: - obfs4publicKey = hashlib.sha256(bytes(random.getrandbits(8))).hexdigest() - - extra.append(b"transport obfs3 %s:%d" % (ipv4, port + 1)) - extra.append(b"transport obfs2 %s:%d" % (ipv4, port + 2)) - extra.append(b"transport scramblesuit %s:%d password=%s" % - (ipv4, port + 3, scramblesuitPassword)) - # PT args are comma-separated in the bridge-extrainfo descriptors: - extra.append(b"transport obfs4 %s:%d iat-mode=%s,node-id=%s,public-key=%s" % - (ipv4, port + 4, obfs4iatMode, obfs4nodeID, obfs4publicKey)) + if bridge is not None: + + if 'obfs3' in bridge: + extra.append(b"transport obfs3 %s:%d" % (ipv4, port + 1)) + if 'obfs2' in bridge: + extra.append(b"transport obfs2 %s:%d" % (ipv4, port + 2)) + if 'scramblesuit' in bridge: + scramblesuitPassword = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' + extra.append(b"transport scramblesuit %s:%d password=%s" % + (ipv4, port + 3, scramblesuitPassword)) + if 'obfs4' in bridge: + obfs4iatMode = bytes(random.getrandbits(1)) # 0 or 1 + # hexadecimal, 40 chars long: + obfs4nodeID = hashlib.sha1(bytes(random.getrandbits(8))).hexdigest() + # hexadecimal, 64 chars long: + obfs4publicKey = hashlib.sha256(bytes(random.getrandbits(8))).hexdigest() + # PT args are comma-separated in the bridge-extrainfo descriptors: + extra.append(b"transport obfs4 %s:%d iat-mode=%s,node-id=%s,public-key=%s" % + (ipv4, port + 4, obfs4iatMode, obfs4nodeID, obfs4publicKey)) extra.append(b"bridge-stats-end %s (86400 s)" % ts) extra.append(b"bridge-ips ca=8") extra.append(b"bridge-ip-versions v4=8,v6=0") diff --git a/leekspin/generator.py b/leekspin/generator.py index a28ef7e..ccc616c 100644 --- a/leekspin/generator.py +++ b/leekspin/generator.py @@ -17,6 +17,7 @@ import re import sys import os import traceback +import itertools try: import OpenSSL @@ -44,11 +45,11 @@ from leekspin import util nacl = True if ntor.nacl else False -def generateDescriptors(bridge=True, withoutTAP=False, withoutNTOR=False): +def generateDescriptors(bridge=extrainfo.PT_NAMES, withoutTAP=False, withoutNTOR=False): """Create keys, certs, signatures, documents and descriptors for an OR. - :param bool bridge: If ``True``, generate Bridge descriptors; otherwise, - generate Relay descriptors. + :param list bridge: If not ``None``, generate Bridge descriptors with the + given transport types; otherwise, generate Relay descriptors. :param bool withoutTAP: If ``True``, generate descriptors without support for the TAP handshake, e.g. without RSA keys. :param bool withoutTAP: If ``True``, generate descriptors without @@ -106,12 +107,12 @@ def generateDescriptors(bridge=True, withoutTAP=False, withoutNTOR=False): vers, protocols, uptime, bandwidth, extrainfoDigest, onionKeyLine, signingKeyLine, - publicNTORKey, bridge=bridge) + publicNTORKey, bridge=bridge is not None) (serverDigestBinary, serverDigest, serverDigestPKCS1) = crypto.digestDescriptorContent(serverDoc) - if bridge: + if bridge is not None: serverDoc = b'@purpose bridge\n' + serverDoc serverDesc = crypto.signDescriptorContent(serverDoc, @@ -258,6 +259,17 @@ def createRelayOrBridgeDescriptors(count, bridge=True, **kwargs): if "withoutNTOR" in kwargs: withoutNTOR = kwargs.get("withoutNTOR") + # We generate descriptors with various combinations of pluggable + # transports. This is necessary to keep BridgeDB's unit tests working + # after our fix for bug 28655, in which we make active probing-resistant + # bridges not give out transports that aren't resistant to active probing: + # <https://bugs.torproject.org/28655> + from leekspin import extrainfo + pt_combs = [] + for i in xrange(len(extrainfo.PT_NAMES) + 1): + for comb in itertools.combinations(extrainfo.PT_NAMES, i): + pt_combs.append(comb) + server_descriptors = list() netstatus_consensus = list() extrainfo_descriptors = list() @@ -271,9 +283,10 @@ def createRelayOrBridgeDescriptors(count, bridge=True, **kwargs): for i in xrange(int(count)): try: + pt_names = pt_combs[i % len(pt_combs)] if bridge else None (extrainfo, server, - netstatus) = generateDescriptors(bridge=bridge, + netstatus) = generateDescriptors(bridge=pt_names, withoutTAP=withoutTAP, withoutNTOR=withoutNTOR) except Exception as error: |
