summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Winter <phw@nymity.ch>2019-04-12 11:46:28 -0700
committerPhilipp Winter <phw@nymity.ch>2019-04-12 16:17:45 -0700
commit9af6c71b3b4aeb56c509df9ae6a16650f9b58dd2 (patch)
tree2a0acc0a98982be86f6175652739c3ecab202d65
parentbad0bed11a9018f65555b3c6998b26e2cb06f5b5 (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.py39
-rw-r--r--leekspin/generator.py25
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: