On Fri, Jan 24, 2020 at 1:31 AM teor teor@riseup.net wrote:
Hi,
Here is an initial draft of Proposal 311: Relay IPv6 Reachability.
This proposal includes:
- relay IPv6 ORPort extends, and
- relay IPv6 ORPort reachability checks.
This is the first of 3 proposals:
- Proposal 311: Relay IPv6 Reachability
- Proposal 312: Automatic Relay IPv6 Addresses
- Proposal 313: Relay IPv6 Statistics
(I haven't written the others yet!)
I also want to make some minor changes to Proposal 306, so that bridge IPv6 behaviour stays in sync with client IPv6 behaviour.
There are still a few TODO items in the proposal, mostly about Tor's current behaviour. If you know the answers, please let me know.
The full text is included below, and it is also available as a GitHub pull request: https://github.com/torproject/torspec/pull/103
The related tickets are #24404 (proposal) and #24403 (implementation): https://trac.torproject.org/projects/tor/ticket/24404 https://trac.torproject.org/projects/tor/ticket/24403
Please feel free to reply on this list, or via GitHub pull request comments.
Hello, Teor! I hope this reply finds you well.
This proposal seems like a good start: It's solid, readable, and I think it would work. There are few places where I have questions or suggested clarifications, and a few where I think we should consider other designs as well.
I'm going to only quote the parts I'm commenting on.
3.2.1. Making IPv6 ORPort Extend Connections
Relays can make a new connection over IPv6 when: * there is no existing authenticated connection to the requested relay, and * the extend cell contains an IPv6 ORPort.
Also we should probably have the condition, "The relay itself supports IPv6, or thinks that it does"?
If these conditions are satisfied, and the extend cell also contains an IPv4 ORPort, we propose that the relay choose between an IPv4 and an IPv6 connection at random.
If the extend cell does not contain an IPv4 ORPort, we propose that the relay connects over IPv6. (Relays should support IPv6-only extend cells, even though they are not used to test relay reachability in this proposal.)
A successful IPv6 connection also requires that: * the requested relay has an IPv6 ORPort. But extending relays must not check the consensus for other relays' IPv6 information. Consensuses may be out of date, particularly when relays are doing reachability checks for new IPv6 ORPorts.
See section 3.3.2 for other situations where IPv6 information may be incorrect or unavailable.
[...]
3.3. Alternative Extend Designs
We briefly mention some potential extend designs, and the reasons that they were not used in this proposal.
(Some designs may be proposed for future Tor versions, but are not necessary at this time.)
Let me sketch another alternative design here:
Suppose that a relay's extend cell contains the IPv4 address and the IPv6 address in their _preferred order_. So if the party generating the extend cell would prefer an IPv4 connection, it puts the IPv4 addess first; if it would prefer an IPv6 connection, it puts the IPv6 address first.
The relay that receives the extend cell could respond in several ways: * One possibility (similar to your 3.2.1) is to choose at random, with a higher probability given to the first option. * One possibility (similar to your 3.3.1) is to try the first, and then try the second if the first one fails.
I think this scheme has some advantage, in that it lets the self-testing relay say "please try IPv6 if you can" or "please try IPv4 if you can" in a reliable way, and lets us migrate from the current behavior to the 3.3.1 behavior down the road.
[...]
4.3. Refuse to Publish Descriptor if IPv6 ORPort is Unreachable
If an IPv6 ORPort reachability check fails, relays (and bridges) should log a warning.
In addition, if IPv6ORPort reachability checks are reliable, based on the number of relays in the network that support IPv6 extends, relays should refuse to publish their descriptor.
Is this the behavior we want? Another behavior would be to omit our IPv6 orport from our descriptor if it is not reachable. That way, relay operators could configure their relays to just listen on IPv6 unconditionally, and let the relay figure out whether it should advertise IPv6 or not. This behavior seems preferable to me, since it has less chance of breaking a relay that would otherwise "work".
As a third possibility, we could have an option to say whether we should publish a descriptor if some of our addresses are not reachable.
[...]
4.3.2. Add AssumeIPv6Reachable Option
We add an AssumeIPv6Reachable torrc option and consensus parameter.
If IPv6 ORPort checks have bugs that impact the health of the network, they can be disabled by setting AssumeIPv6Reachable=1 in the consensus parameters.
If IPv6 ORPort checks have bugs that impact a particular relay (or bridge), they can be disabled by setting "AssumeIPv6Reachable 1" in the relay's torrc.
This option disables IPv6 ORPort reachability checks, so relays publish their descriptors if their IPv4 ORPort reachability checks succeed.
The default for the torrc option is "auto", which checks the consensus parameter. If the consensus parameter is not set, the default is "0".
"AssumeReachable 1" overrides all values of "AssumeIPv6Reachable", disabling both IPv4 and IPv6 ORPort reachability checks.
Should we have some way to AssumeReachable our IPv4 address only, and not our IPv6 address? Or is that too much?
4.4. Optional Efficiency and Reliability Changes
We propose some optional changes for efficiency and reliability, and describe their impact.
Some of these changes may be more appropriate in future releases, or along with other proposed features.
[...]
4.4.3. Accurately Identifying Test Circuits
The testing relay (or bridge) may confirm that the create cells it is receiving are from its own test circuits, and that test circuits are capable of returning create cells to the origin.
Currently, relays confirm reachability if any create cell is received on any inbound connection (see section 4.1). Relays do not check that the circuit is a reachability test circuit, and they do not wait to receive the return created cell. This behaviour has resulted in difficult to diagnose bugs on some rare relay configurations.
We propose these optional changes, to improve the efficiency of IPv4 and IPv6 ORPort reachability checks:
If we make these changes, I think we should track both whether we are "maybe reachable" (under the current definition of 'reachable') and "definitely reachable" (based on the new definition). We should log different messages depending on whether we are "maybe reachable" but these new tests fail, or whether we are completely unreachable.
Testing relays may: * check that the create cell is received from a test circuit (by comparing the received cell to the cells sent by test circuits), * check that the create cell is received on an inbound connection (this is existing behaviour), * if the create cell from a test circuit is received on an outbound connection, destroy the circuit (rather than returning a created cell), and * check that the created cell is returned to the relay on a test circuit (by comparing the remote address of the final hop on the circuit, to the local IPv4 and IPv6 ORPort addresses).
TODO: work out how to efficiently match inbound create cells to test circuits.
One possibility: we could store a set of our test circuits' extend cells g^X values, and then check incoming cells create cells against that set.
There are probably fancier designs based on EC trickery or tweaks to the ntor protocol, but I think we'd best avoid them.
4.4.4. Allowing More Relay IPv6 Extends
Currently, clients, relays, and bridges do not include IPv6 ORPorts in their extend cells.
In this proposal, we only make relays (and bridges) extend over IPv6 on the final hop of test circuits. This limited use of IPv6 extends means that IPv6 connections will still be uncommon.
We propose these optional changes, to increase the number of IPv6 connections between relays:
To increase the number of IPv6 connections, relays that support IPv6 extends may want to use them for all hops of their own circuits. Relays make their own circuits for reachability tests, bandwidth tests, and ongoing preemptive circuits. (Bridges can not change their behaviour, because they try to imitate clients.)
We propose a torrc option and consensus parameter SendIPv6CircuitExtends, which is only supported on relays (and not bridges or clients). This option makes relays send IPv4 and IPv6 ORPorts in all their extend cells, when supported by the extending and receiving relay. (See section 3.2.1.)
TODO: Is there a shorter name, that isn't easily confused with enabling support for other nodes to perform IPv6 extends via this relay?
I have another concern here: if this option is truly relay-only, it should probably have a name that indicates the fact.
The default value for this option is "auto", which checks the consensus parameter. If the consensus parameter is not set, it defaults to "0" in the initial release.
Once IPv6 extends have had enough testing, we may enable SendIPv6CircuitExtends on the network. The consensus parameter will be set to 1. The default will be changed to "1" (if the consensus parameter is not set).
We defer any client (and bridge) changes to a separate proposal, to be implemented when there are more IPv6 relays in the network. But we note that relay IPv6 extends will provide some cover traffic when clients eventually use IPv6 extends in their circuits.
As a useful side effect, increasing the number of IPv6 connections in the network makes it more likely that an existing connection can be used for the final hop of a relay IPv6 ORPort reachability check.
4.5. Alternate Reachability Designs
We briefly mention some potential reachability designs, and the reasons that they were not used in this proposal.
4.5.1. Removing IPv4 ORPorts from Extend Cells
We avoid designs that only include IPv6 ORPorts in extend cells, and remove IPv4 ORPorts.
Only including the IPv6 ORPort would provide slightly more specific reachability check circuits. However, we don't need IPv6-only designs, because relays continue trying different reachability circuits until they confirm reachability.
IPv6-only designs also make it easy to distinguish relay reachability extend cells from other extend cells. This distinguisher will become more of an issue as IPv6 extends become more common in the network (see sections 4.2.2 and 4.4.4).
Removing the IPv4 ORPort also provides no fallback, if the IPv6 ORPort is actually unreachable. IPv6-only failures do not affect reachability checks, but they will become important in the future, as other circuit types start using IPv6 extends.
IPv6-only reachability designs also increase the number of special cases in the implementation. (And the likelihood of subtle bugs.)
These designs may be appropriate in future, when there are IPv6-only bridges or relays.
As an aside: I think in the long run, the future is for clients to treat relays' link specifiers as completely opaque when they are making extend cells.
That is, if a client is extending to some relay X, it should know "here is a blob that you use as X's link specifiers" -- it can be the authorities' job to decide which IP addresses and which identity keys such a blob needs to contain.
(Of course, a client still needs to know a relay's address when making a connection itself, but that's more in prop306 territory.)
New Relay Subprotocol Version
We reserve Tor subprotocol "Relay=3" for:
- relays that support for IPv6 extends, and
- relays and bridges that support IPv6 ORPort reachability checks,
as described in this proposal.
I don't fully understand; this reads as ambiguous to me. Does "Relay=3" mean "IF I have an IPv6 address, I support IPv6 extends and checks"? Or does it mean "I have an IPv6 address, and I support IPv6 extends and checks"?
I would argue for the former interpretation, since no other subprotocol version is specified to depend on the relay's network configuration.
5.1. Tor Specification Changes
We propose the following changes to the [Tor Specification], once this proposal is implemented.
Adding a new Relay subprotocol version lets testing relays identify other relays that support IPv6 extends. It also allows us to eventually recommend or require support for IPv6 extends on all relays (and bridges).
Append to the Relay version 2 subprotocol specification:
Relay=2 has limited IPv6 support: * Clients do not include IPv6 ORPorts in EXTEND2 cells.
I think that this is saying too much; we should leave it out. Clients on the current Tor network MAY include IPv6 ORPorts, after all: we don't want to retroactively specify that any implementations that _do_ include them are noncompliant with subprotocol v2.
* Relays do not not initiate IPv6 connections in response to EXTEND2 cells containing IPv6 ORPorts.
Is this always true? Would "may not" or "do not always" be more correct?
However, relays accept inbound connections to their IPv6 ORPorts, and will extend circuits via those connections.
"3" -- relays support extending over IPv6 connections in response to an EXTEND2 cell containing an IPv6 ORPort. Relays and bridges perform IPv6 ORPort reachability checks. Client behaviour does not change.
Should this be "self-checks" instead of "checks" for clarity?
Also, I wonder whether having self-checking be part of the relay protocol is correct.
This subprotocol is advertised by all relays and bridges, regardless of their configured ORPorts.
This "all" should probably be removed or clarified. How about "all relays and bridges running software that supports it, whether or not they have IPv6 ORPorts configured."
But relays without a configured IPv6 ORPort may refuse to extend over IPv6. And bridges always refuse to extend over IPv6, because they try to imitate client behaviour.
This last seems like it's saying that bridges SHOULD or MUST refuse to extend over IPv6; it might be better to say that they MAY, so that if client behavior changes, bridges can change too.
A successful IPv6 extend requires: * Relay subprotocol version 3 (or later) and an IPv6 ORPort on the extending relay, * an IPv6 ORPort in the EXTEND2 cell, and * an IPv6 ORPort on the accepting relay. (Because different tor instances can have different views of the network, these checks should be done when the path is selected. Extending relays should only check local IPv6 information, before attempting the extend.) This subprotocol version is described in proposal 311, and implemented in Tor 0.4.4.1-alpha. (TODO: check version after code is merged).
I think that the "pick a random ORPort" behavior should be specified here too, as part of relay subprotocol v3, if we keep it.
yrs,