mirror of
https://github.com/torproject/torspec.git
synced 2024-12-12 04:35:37 +00:00
121 lines
4.7 KiB
Plaintext
121 lines
4.7 KiB
Plaintext
Filename: 110-avoid-infinite-circuits.txt
|
|
Title: Avoiding infinite length circuits
|
|
Author: Roger Dingledine
|
|
Created: 13-Mar-2007
|
|
Status: Closed
|
|
Target: 0.2.3.x
|
|
Implemented-In: 0.2.1.3-alpha, 0.2.3.11-alpha
|
|
|
|
History:
|
|
|
|
Revised 28 July 2008 by nickm: set K.
|
|
Revised 3 July 2008 by nickm: rename from relay_extend to
|
|
relay_early. Revise to current migration plan. Allow K cells
|
|
over circuit lifetime, not just at start.
|
|
|
|
Overview:
|
|
|
|
Right now, an attacker can add load to the Tor network by extending a
|
|
circuit an arbitrary number of times. Every cell that goes down the
|
|
circuit then adds N times that amount of load in overall bandwidth
|
|
use. This vulnerability arises because servers don't know their position
|
|
on the path, so they can't tell how many nodes there are before them
|
|
on the path.
|
|
|
|
We propose a new set of relay cells that are distinguishable by
|
|
intermediate hops as permitting extend cells. This approach will allow
|
|
us to put an upper bound on circuit length relative to the number of
|
|
colluding adversary nodes; but there are some downsides too.
|
|
|
|
Motivation:
|
|
|
|
The above attack can be used to generally increase load all across the
|
|
network, or it can be used to target specific servers: by building a
|
|
circuit back and forth between two victim servers, even a low-bandwidth
|
|
attacker can soak up all the bandwidth offered by the fastest Tor
|
|
servers.
|
|
|
|
The general attacks could be used as a demonstration that Tor isn't
|
|
perfect (leading to yet more media articles about "breaking" Tor), and
|
|
the targetted attacks will come into play once we have a reputation
|
|
system -- it will be trivial to DoS a server so it can't pass its
|
|
reputation checks, in turn impacting security.
|
|
|
|
Design:
|
|
|
|
We should split RELAY cells into two types: RELAY and RELAY_EARLY.
|
|
|
|
Only K (say, 10) Relay_early cells can be sent across a circuit, and
|
|
only relay_early cells are allowed to contain extend requests. We
|
|
still support obscuring the length of the circuit (if more research
|
|
shows us what to do), because Alice can choose how many of the K to
|
|
mark as relay_early. Note that relay_early cells *can* contain any
|
|
sort of data cell; so in effect it's actually the relay type cells
|
|
that are restricted. By default, she would just send the first K
|
|
data cells over the stream as relay_early cells, regardless of their
|
|
actual type.
|
|
|
|
(Note that a circuit that is out of relay_early cells MUST NOT be
|
|
cannibalized later, since it can't extend. Note also that it's always okay
|
|
to use regular RELAY cells when sending non-EXTEND commands targetted at
|
|
the first hop of a circuit, since there is no intermediate hop to try to
|
|
learn the relay command type.)
|
|
|
|
Each intermediate server would pass on the same type of cell that it
|
|
received (either relay or relay_early), and the cell's destination
|
|
will be able to learn whether it's allowed to contain an Extend request.
|
|
|
|
If an intermediate server receives more than K relay_early cells, or
|
|
if it sees a relay cell that contains an extend request, then it
|
|
tears down the circuit (protocol violation).
|
|
|
|
Security implications:
|
|
|
|
The upside is that this limits the bandwidth amplification factor to
|
|
K: for an individual circuit to become arbitrary-length, the attacker
|
|
would need an adversary-controlled node every K hops, and at that
|
|
point the attack is no worse than if the attacker creates N/K separate
|
|
K-hop circuits.
|
|
|
|
On the other hand, we want to pick a large enough value of K that we
|
|
don't mind the cap.
|
|
|
|
If we ever want to take steps to hide the number of hops in the circuit
|
|
or a node's position in the circuit, this design probably makes that
|
|
more complex.
|
|
|
|
Migration:
|
|
|
|
In 0.2.0, servers speaking v2 or later of the link protocol accept
|
|
RELAY_EARLY cells, and pass them on. If the next OR in the circuit
|
|
is not speaking the v2 link protocol, the server relays the cell as
|
|
a RELAY cell.
|
|
|
|
In 0.2.1.3-alpha, clients begin using RELAY_EARLY cells on v2
|
|
connections. This functionality can be safely backported to
|
|
0.2.0.x. Clients should pick a random number betweeen (say) K and
|
|
K-2 to send.
|
|
|
|
In 0.2.1.3-alpha, servers close any circuit in which more than K
|
|
relay_early cells are sent.
|
|
|
|
Once all versions the do not send RELAY_EARLY cells are obsolete,
|
|
servers can begin to reject any EXTEND requests not sent in a
|
|
RELAY_EARLY cell.
|
|
|
|
Parameters:
|
|
|
|
Let K = 8, for no terribly good reason.
|
|
|
|
Spec:
|
|
|
|
[We can formalize this part once we think the design is a good one.]
|
|
|
|
Acknowledgements:
|
|
|
|
This design has been kicking around since Christian Grothoff and I came
|
|
up with it at PET 2004. (Nathan Evans, Christian Grothoff's student,
|
|
is working on implementing a fix based on this design in the summer
|
|
2007 timeframe.)
|
|
|