commit 696a55c0e2cdfa00b5297748196b9cea260a3ec5
Author: teor <teor2345(a)gmail.com>
Date: Tue Sep 6 13:49:24 2016 +1000
Add IPv6 client support to chutney
This adds the following flavours:
* client-ipv6-only: test that an IPv6 client can bootstrap and transmit data
* hs-client-ipv6: test that an IPv6 client can connect to an IPv4 HS
* hs-ipv6: test that IPv4 and IPv6 clients can connect to an IPv6 HS
It also adds support for IPv6 hidden services, relays, and authorities.
---
README | 19 ++++++++++++-------
lib/chutney/TorNet.py | 20 ++++++++++++++------
networks/client-ipv6-only | 20 ++++++++++++++++++++
networks/hs-client-ipv6 | 24 ++++++++++++++++++++++++
networks/hs-ipv6 | 25 +++++++++++++++++++++++++
tools/test-network.sh | 10 ++++++++++
torrc_templates/authority-orport-v6-exit.tmpl | 7 +++++++
torrc_templates/authority-orport-v6.tmpl | 7 +++++++
torrc_templates/client-only-v6.i | 10 ++++++++++
torrc_templates/client-only-v6.tmpl | 2 ++
torrc_templates/client-use-v6.i | 3 +++
torrc_templates/client-use-v6.tmpl | 2 ++
torrc_templates/hs-only-v6.tmpl | 3 +++
torrc_templates/hs-use-v6.tmpl | 3 +++
torrc_templates/orport-v6.i | 4 ++++
torrc_templates/relay-orport-v6-exit.tmpl | 10 ++++++++++
torrc_templates/relay-orport-v6-non-exit.tmpl | 4 ++++
17 files changed, 160 insertions(+), 13 deletions(-)
diff --git a/README b/README
index f720a81..1d7fa1d 100644
--- a/README
+++ b/README
@@ -44,6 +44,10 @@ Traffic Options:
--connections CHUTNEY_CONNECTIONS
--hs-multi-client CHUTNEY_HS_MULTI_CLIENT
+Address Options:
+ --ipv4 CHUTNEY_LISTEN_ADDRESS
+ --ipv6 CHUTNEY_LISTEN_ADDRESS_V6
+
Standard Actions:
./chutney configure networks/basic
./chutney start networks/basic
@@ -108,14 +112,15 @@ Waiting for the network:
Changing the network address:
- Chutney defaults to binding to localhost. To change the bind address,
- set the CHUTNEY_LISTEN_ADDRESS environment variable. Setting it to some
- interface's IP address allows us to make the simulated Tor network
- available on the network.
+ Chutney defaults to binding to localhost. To change the IPv4 bind address,
+ set the CHUTNEY_LISTEN_ADDRESS environment variable. Similarly, change
+ CHUTNEY_LISTEN_ADDRESS_V6 for IPv6: it defaults to "no IPv6 address".
+ Setting it to some interface's IP address allows us to make the simulated
+ Tor network available on the network.
- IPv6 support for both Tor and Chutney is a work in progress. If your system
- returns IPv6 ::1 as the (first) address for localhost, you might need to
- set CHUTNEY_LISTEN_ADDRESS="127.0.0.1" for chutney to work.
+ IPv6 support for both Tor and Chutney is a work in progress. Currently,
+ chutney verifies IPv6 client, bridge client, and hidden service
+ connections. It does not use IPv6 SOCKSPort or Exit traffic.
The configuration files:
networks/basic holds the configuration for the network you're configuring
diff --git a/lib/chutney/TorNet.py b/lib/chutney/TorNet.py
index 352e671..6db7ad4 100644
--- a/lib/chutney/TorNet.py
+++ b/lib/chutney/TorNet.py
@@ -206,9 +206,9 @@ class LocalNodeBuilder(NodeBuilder):
# tor_gencert -- path to tor_gencert binary
# tor -- path to tor binary
# auth_cert_lifetime -- lifetime of authority certs, in months.
- # ip -- IP to listen on (used only if authority or bridge)
- # ipv6_addr -- IPv6 address to listen on (used only if ipv6 bridge)
- # orport, dirport -- (used only if authority)
+ # ip -- IP to listen on
+ # ipv6_addr -- IPv6 address to listen on
+ # orport, dirport -- used on authorities, relays, and bridges
# fingerprint -- used only if authority
# dirserver_flags -- used only if authority
# nick -- nickname of this router
@@ -461,8 +461,14 @@ class LocalNodeBuilder(NodeBuilder):
authlines = ""
for authopt in options:
- authlines += "%s %s orport=%s %s %s:%s %s\n" % (
- authopt, self._env['nick'], self._env['orport'],
+ authlines += "%s %s orport=%s" % (
+ authopt, self._env['nick'], self._env['orport'])
+ # It's ok to give an authority's IPv6 address to an IPv4-only
+ # client or relay: it will and must ignore it
+ if self._env['ipv6_addr'] is not None:
+ authlines += " ipv6=%s:%s" % (self._env['ipv6_addr'],
+ self._env['orport'])
+ authlines += " %s %s:%s %s\n" % (
self._env['dirserver_flags'], self._env['ip'],
self._env['dirport'], self._env['fingerprint'])
return authlines
@@ -675,7 +681,9 @@ DEFAULTS = {
'tor-gencert': os.environ.get('CHUTNEY_TOR_GENCERT', None),
'auth_cert_lifetime': 12,
'ip': os.environ.get('CHUTNEY_LISTEN_ADDRESS', '127.0.0.1'),
- 'ipv6_addr': None,
+ # Pre-0.2.8 clients will fail to parse ipv6 auth lines,
+ # so we default to ipv6_addr None
+ 'ipv6_addr': os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6', None),
'dirserver_flags': 'no-v2',
'chutney_dir': '.',
'torrc_fname': '${dir}/torrc',
diff --git a/networks/client-ipv6-only b/networks/client-ipv6-only
new file mode 100644
index 0000000..19e5ad8
--- /dev/null
+++ b/networks/client-ipv6-only
@@ -0,0 +1,20 @@
+import os
+# By default, Authorities are not configured as exits
+Authority6 = Node(tag="a", authority=1, relay=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="authority-orport-v6.tmpl")
+ExitRelay6 = Node(tag="r", relay=1, exit=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="relay-orport-v6-exit.tmpl")
+Client6 = Node(tag="c", torrc="client-only-v6.tmpl")
+
+# Since only 25% of relays get the guard flag,
+# TestingDirAuthVoteGuard * may need to be used in small networks
+
+# The minimum number of authorities/relays/exits is 3, the minimum path length
+# But for some reason, Tor wants 4 "acceptable routers" (Tor bug #20071)
+NODES = Authority6.getN(3) + ExitRelay6.getN(1) + Client6.getN(1)
+
+ConfigureNodes(NODES)
diff --git a/networks/hs-client-ipv6 b/networks/hs-client-ipv6
new file mode 100644
index 0000000..62ffae2
--- /dev/null
+++ b/networks/hs-client-ipv6
@@ -0,0 +1,24 @@
+import os
+# By default, Authorities are not configured as exits
+Authority6 = Node(tag="a", authority=1, relay=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="authority-orport-v6.tmpl")
+NonExitRelay6 = Node(tag="r", relay=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="relay-orport-v6-non-exit.tmpl")
+Client6 = Node(tag="c", torrc="client-only-v6.tmpl")
+HS = Node(tag="h", hs=1, torrc="hs.tmpl")
+
+# Since only 25% of relays get the guard flag,
+# TestingDirAuthVoteGuard * may need to be used in small networks
+
+# A hidden service needs 5 authorities/relays to ensure it can build HS
+# connections:
+# a minimum path length of 3, plus the client-nominated rendezvous point,
+# plus a seperate introduction point
+NODES = Authority6.getN(2) + NonExitRelay6.getN(3) + \
+ Client6.getN(1) + HS.getN(1)
+
+ConfigureNodes(NODES)
diff --git a/networks/hs-ipv6 b/networks/hs-ipv6
new file mode 100644
index 0000000..88223ba
--- /dev/null
+++ b/networks/hs-ipv6
@@ -0,0 +1,25 @@
+import os
+# By default, Authorities are not configured as exits
+Authority6 = Node(tag="a", authority=1, relay=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="authority-orport-v6.tmpl")
+NonExitRelay6 = Node(tag="r", relay=1,
+ ipv6_addr=os.environ.get('CHUTNEY_LISTEN_ADDRESS_V6',
+ '[::1]'),
+ torrc="relay-orport-v6-non-exit.tmpl")
+Client = Node(tag="c", torrc="client.tmpl")
+Client6 = Node(tag="c", torrc="client-only-v6.tmpl")
+HS6 = Node(tag="h", hs=1, torrc="hs.tmpl")
+
+# Since only 25% of relays get the guard flag,
+# TestingDirAuthVoteGuard * may need to be used in small networks
+
+# A hidden service needs 5 authorities/relays to ensure it can build HS
+# connections:
+# a minimum path length of 3, plus the client-nominated rendezvous point,
+# plus a seperate introduction point
+NODES = Authority6.getN(2) + NonExitRelay6.getN(3) + \
+ Client.getN(1) + Client6.getN(1) + HS6.getN(1)
+
+ConfigureNodes(NODES)
diff --git a/tools/test-network.sh b/tools/test-network.sh
index dc8f0dc..beefdc3 100755
--- a/tools/test-network.sh
+++ b/tools/test-network.sh
@@ -73,6 +73,16 @@ do
export CHUTNEY_HS_MULTI_CLIENT="$2"
shift
;;
+ # The IPv4 address to bind to, defaults to 127.0.0.1
+ --ipv4|--v4|-4|--ip)
+ export CHUTNEY_LISTEN_ADDRESS="$2"
+ shift
+ ;;
+ # The IPv6 address to bind to, default is not to bind to an IPv6 address
+ --ipv6|--v6|-6)
+ export CHUTNEY_LISTEN_ADDRESS_V6="$2"
+ shift
+ ;;
--coverage)
export USE_COVERAGE_BINARY=true
;;
diff --git a/torrc_templates/authority-orport-v6-exit.tmpl b/torrc_templates/authority-orport-v6-exit.tmpl
new file mode 100644
index 0000000..326315b
--- /dev/null
+++ b/torrc_templates/authority-orport-v6-exit.tmpl
@@ -0,0 +1,7 @@
+${include:authority-orport-v6.tmpl}
+
+# An authority that's also an exit relay that can exit to IPv4 & IPv6 localhost
+# (newer versions of tor need this to be explicitly configured)
+
+${include:exit-v4.i}
+${include:exit-v6.i}
diff --git a/torrc_templates/authority-orport-v6.tmpl b/torrc_templates/authority-orport-v6.tmpl
new file mode 100644
index 0000000..ecb320b
--- /dev/null
+++ b/torrc_templates/authority-orport-v6.tmpl
@@ -0,0 +1,7 @@
+${include:authority.tmpl}
+
+# An authority that has an IPv6 ORPort
+${include:orport-v6.i}
+
+# And has IPv6 connectivity
+AuthDirHasIPv6Connectivity 1
diff --git a/torrc_templates/client-only-v6.i b/torrc_templates/client-only-v6.i
new file mode 100644
index 0000000..3105c0f
--- /dev/null
+++ b/torrc_templates/client-only-v6.i
@@ -0,0 +1,10 @@
+# A client that only uses IPv6 ORPorts
+ClientUseIPv4 0
+# Due to Tor bug #19608, microdescriptors can't be used by IPv6-only clients
+UseMicrodescriptors 0
+
+# Previous versions of Tor did not support IPv6-only operation
+# But this is how it would have been configured
+#ClientUseIPv6 1
+#ClientPreferIPv6ORPort 1
+#ReachableAddresses reject 0.0.0.0/0, accept [::]/0
diff --git a/torrc_templates/client-only-v6.tmpl b/torrc_templates/client-only-v6.tmpl
new file mode 100644
index 0000000..79bd74b
--- /dev/null
+++ b/torrc_templates/client-only-v6.tmpl
@@ -0,0 +1,2 @@
+${include:client.tmpl}
+${include:client-only-v6.i}
diff --git a/torrc_templates/client-use-v6.i b/torrc_templates/client-use-v6.i
new file mode 100644
index 0000000..8fff310
--- /dev/null
+++ b/torrc_templates/client-use-v6.i
@@ -0,0 +1,3 @@
+# A client that uses and prefers IPv6
+ClientUseIPv6 1
+ClientPreferIPv6ORPort 1
diff --git a/torrc_templates/client-use-v6.tmpl b/torrc_templates/client-use-v6.tmpl
new file mode 100644
index 0000000..1659a39
--- /dev/null
+++ b/torrc_templates/client-use-v6.tmpl
@@ -0,0 +1,2 @@
+${include:client.tmpl}
+${include:client-use-v6.i}
diff --git a/torrc_templates/hs-only-v6.tmpl b/torrc_templates/hs-only-v6.tmpl
new file mode 100644
index 0000000..e72da8f
--- /dev/null
+++ b/torrc_templates/hs-only-v6.tmpl
@@ -0,0 +1,3 @@
+${include:hs.i}
+# Hidden services are just another kind of client
+${include:client-only-v6.i}
diff --git a/torrc_templates/hs-use-v6.tmpl b/torrc_templates/hs-use-v6.tmpl
new file mode 100644
index 0000000..c252854
--- /dev/null
+++ b/torrc_templates/hs-use-v6.tmpl
@@ -0,0 +1,3 @@
+${include:hs.i}
+# Hidden services are just another kind of client
+${include:client-use-v6.i}
diff --git a/torrc_templates/orport-v6.i b/torrc_templates/orport-v6.i
new file mode 100644
index 0000000..d1ad44d
--- /dev/null
+++ b/torrc_templates/orport-v6.i
@@ -0,0 +1,4 @@
+# Tor uses the first IPv6 ORPort address as its IPv6 address
+OrPort ${ipv6_addr}:${orport} IPv6Only
+
+# IPv6 DirPorts are not needed
diff --git a/torrc_templates/relay-orport-v6-exit.tmpl b/torrc_templates/relay-orport-v6-exit.tmpl
new file mode 100644
index 0000000..548c54f
--- /dev/null
+++ b/torrc_templates/relay-orport-v6-exit.tmpl
@@ -0,0 +1,10 @@
+${include:relay.tmpl}
+
+# A relay that has an IPv6 ORPort
+${include:orport-v6.i}
+
+# An exit relay that can exit to IPv4 & IPv6 localhost
+# (newer versions of tor need this to be explicitly configured)
+
+${include:exit-v4.i}
+${include:exit-v6.i}
diff --git a/torrc_templates/relay-orport-v6-non-exit.tmpl b/torrc_templates/relay-orport-v6-non-exit.tmpl
new file mode 100644
index 0000000..5da1ca6
--- /dev/null
+++ b/torrc_templates/relay-orport-v6-non-exit.tmpl
@@ -0,0 +1,4 @@
+${include:relay-non-exit.tmpl}
+
+# A relay that has an IPv6 ORPort
+${include:orport-v6.i}