[tor-commits] [torspec/master] Add proposal 289: Authenticating sendme cells to mitigate bandwidth attacks

nickm at torproject.org nickm at torproject.org
Tue Feb 13 13:39:03 UTC 2018

commit 39fde37cfa85149e978620edee9468c58973055e
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Feb 13 08:39:00 2018 -0500

    Add proposal 289: Authenticating sendme cells to mitigate bandwidth attacks
 proposals/000-index.txt                 |   2 +
 proposals/289-authenticated-sendmes.txt | 397 ++++++++++++++++++++++++++++++++
 2 files changed, 399 insertions(+)

diff --git a/proposals/000-index.txt b/proposals/000-index.txt
index 86fab75..503d752 100644
--- a/proposals/000-index.txt
+++ b/proposals/000-index.txt
@@ -209,6 +209,7 @@ Proposals by number:
 286  Controller APIs for hibernation access on mobile [OPEN]
 287  Reduce circuit lifetime without overloading the network [OPEN]
 288  Privacy-Preserving Statistics with Privcount in Tor (Shamir version) [DRAFT]
+289  Authenticating sendme cells to mitigate bandwidth attacks [OPEN]
 Proposals by status:
@@ -267,6 +268,7 @@ Proposals by status:
    285  Directory documents should be standardized as UTF-8
    286  Controller APIs for hibernation access on mobile
    287  Reduce circuit lifetime without overloading the network
+   289  Authenticating sendme cells to mitigate bandwidth attacks
    172  GETINFO controller option for circuit information
    173  GETINFO Option Expansion
diff --git a/proposals/289-authenticated-sendmes.txt b/proposals/289-authenticated-sendmes.txt
new file mode 100644
index 0000000..316bd75
--- /dev/null
+++ b/proposals/289-authenticated-sendmes.txt
@@ -0,0 +1,397 @@
+Filename: 289-authenticated-sendmes.txt
+Title: Authenticating sendme cells to mitigate bandwidth attacks
+Author: Rob Jansen, Roger Dingledine
+Created: 2016-12-01
+Status: Open
+1. Overview and Motivation
+   In Rob's "Sniper attack", a malicious Tor client builds a circuit,
+   fetches a large file from some website, and then refuses to read any
+   of the cells from the entry guard, yet sends "sendme" (flow control
+   acknowledgement) cells down the circuit to encourage the exit relay
+   to keep sending more cells. Eventually enough cells queue at the
+   entry guard that it runs out of memory and exits [0, 1].
+   We resolved the "runs out of memory and exits" part of the attack with
+   our Out-Of-Memory (OOM) manager introduced in Tor But
+   the earlier part remains unresolved: a malicious client can launch
+   an asymmetric bandwidth attack by creating circuits and streams and
+   sending a small number of sendme cells on each to cause the target
+   relay to receive a large number of data cells.
+   This attack could be used for general mischief in the network (e.g.,
+   consume Tor network bandwidth resources or prevent access to relays),
+   and it could probably also be leveraged to harm anonymity a la the
+   "congestion attack" designs [2, 3].
+   This proposal describes a way to verify that the client has seen all
+   of the cells that its sendme cell is acknowledging, based on the
+   authenticated sendmes design from [1].
+2. Sniper Attack Variations
+   There are some variations on the attack involving the number and
+   length of the circuits and the number of Tor clients used. We explain
+   them here to help understand which of them this proposal attempts to
+   defend against.
+   We compare the efficiency of these attacks in terms of the number of
+   cells transferred by the adversary and by the network, where receiving
+   and sending a cell counts as two transfers of that cell.
+2.1 Single Circuit, without Sendmes
+   The simplest attack is where the adversary starts a single Tor client,
+   creates one circuit and two streams to some website, and stops
+   reading from the TCP connection to the entry guard. The adversary
+   gets 1000 "attack" cells "for free" (until the stream and circuit
+   windows close). The attack data cells are both received and sent by the
+   exit and the middle, while being received and queued by the guard.
+   Adversary:
+   6 transfers to create the circuit
+   2 to begin the two exit connections
+   2 to send the two GET requests
+   ---
+   10 total
+   Network:
+   18 transfers to create the circuit
+   22 to begin the two exit connections (assumes two for the exit TCP connect)
+   12 to send the two GET requests to the website
+   5000 for requested data (until the stream and circuit windows close)
+   ---
+   5052 total
+2.2 Single Circuit, with Sendmes
+   A slightly more complex version of the attack in 2.1 is where the
+   adversary continues to send sendme cells to the guard (toward the exit),
+   and then gets another 100 attack data cells sent across the network for every
+   three additional exitward sendme cells that it sends (two stream-level
+   sendmes and one circuit-level sendme). The adversary also gets another
+   three clientward sendme cells sent by the exit for every 100 exitward
+   sendme cells it sends.
+   If the adversary sends N sendmes, then we have:
+   Adversary:
+   10 for circuit and stream setup
+   N for circuit and stream sendmes
+   ---
+   10+N
+   Network:
+   5052 for circuit and stream setup and initial depletion of circuit windows
+   N*100/3*5 for transferring additional data cells from the website
+   N*3/100*4 for transferring sendmes from exit to client
+   ---
+   5052 + N*166.79
+   It is important to note that once the adversary stops reading from the
+   guard, it will no longer get feedback on the speed at which the data
+   cells are able to be transferred through the circuit from the exit
+   to the guard. It needs to approximate when it should send sendmes
+   to the exit; if too many sendmes are sent such that the circuit
+   window would open farther than 1000 cells (500 for streams), then the
+   circuit may be closed by the exit. In practice, the adversary could
+   take measurements during the circuit setup process and use them to
+   estimate a conservative sendme sending rate.
+2.3 Multiple Circuits
+   The adversary could parallelize the above attacks using multiple
+   circuits. Because the adversary needs to stop reading from the TCP
+   connection to the guard, they would need to do a pre-attack setup
+   phase during which they construct the attack circuits. Then, they
+   would stop reading from the guard and send all of the GET requests
+   across all of the circuits they created.
+   The number of cells from 2.1 and 2.2 would then be multiplied by the
+   number of circuits C that the adversary is able to build and sustain
+   during the attack.
+2.4 Multiple Guards
+   The adversary could use the "UseEntryGuards 0" torrc option, or build
+   custom circuits with stem to parallelize the attack across multiple
+   guard nodes. This would slightly increase the bandwidth usage of the
+   adversary, since it would be creating additional TCP connections to
+   guard nodes.
+2.5 Multiple Clients
+   The adversary could run multiple attack clients, each of which would
+   choose its own guard. This would slightly increase the bandwidth
+   usage of the adversary, since it would be creating additional TCP
+   connections to guard nodes and would also be downloading directory
+   info, creating testing circuits, etc.
+2.6 Short Two-hop Circuits
+   If the adversary uses two-hop circuits, there is less overhead
+   involved with the circuit setup process.
+   Adversary:
+   4 transfers to create the circuit
+   2 to begin the two exit connections
+   2 to send the two GET requests
+   ---
+   8
+   Network:
+   8 transfers to create the circuit
+   14 to begin the two exit connections (assumes two for the exit TCP connect)
+   8 to send the two GET requests to the website
+   5000 for requested data (until the stream and circuit windows close)
+   ---
+   5030
+2.7 Long >3-hop Circuits
+   The adversary could use a circuit longer than three hops to cause more
+   bandwidth usage across the network. Let's use an 8 hop circuit as an
+   example.
+   Adversary:
+   16 transfers to create the circuit
+   2 to begin the two exit connections
+   2 to send the two GET requests
+   ---
+   20
+   Network:
+   128 transfers to create the circuit
+   62 to begin the two exit connections (assumes two for the exit TCP connect)
+   32 to send the two GET requests to the website
+   15000 for requested data (until the stream and circuit windows close)
+   ---
+   15222
+   The adversary could also target a specific relay, and use it multiple
+   times as part of the long circuit, e.g., as hop 1, 4, and 7.
+   Target:
+   54 transfers to create the circuit
+   22 to begin the two exit connections (assumes two for the exit TCP connect)
+   12 to send the two GET requests to the website
+   5000 for requested data (until the stream and circuit windows close)
+   ---
+   5088
+3. Design
+   This proposal aims to defend against the versions of the attack that
+   utilize sendme cells without reading. It does not attempt to handle
+   the case of multiple circuits per guard, or try to restrict the number
+   of guards used by a client, or prevent a sybil attack across multiple
+   client instances.
+   The proposal involves three components: first, the client needs to add
+   a token to the sendme payload, to prove that it knows the contents
+   of the cells that it has received. Second, the exit relay needs to
+   verify this token. Third, to resolve the case where the client already
+   knows the contents of the file so it only pretends to read the cells,
+   the exit relay needs to be able to add unexpected randomness to the
+   circuit.
+   (Note: this proposal talks about clients and exit relays, but since
+   sendmes go in both directions, both sides of the circuit should do
+   these changes.)
+3.1. Changing the sendme payload to prove receipt of cells
+   In short: clients put the latest received relay cell digest in the
+   payload of their circuit-level sendme cells.
+   Each relay cell header includes a 4-byte digest which represents
+   the rolling hash of all bytes received on that circuit. So knowledge
+   of that digest is an indication that you've seen the bytes that go
+   into it.
+   We pick circuit-level sendme cells, as opposed to stream-level sendme
+   cells, because we think modifying just circuit-level sendmes is
+   sufficient to accomplish the properties we need, and modifying just
+   stream-level sendmes is not sufficient: a client could send a bunch
+   of begin cells and fake their circuit-level sendmes, but never send
+   any stream-level sendmes, attracting 500*n queued cells to the entry
+   guard for the n streams that it opens.
+   Which digest should the client put in the sendme payload? Right now
+   circuit-level sendmes are sent whenever one window worth of relay cells
+   (100) has arrived. So the client should use the digest from the cell
+   that triggers the sendme.
+   How shall we version the sendme payload so we can change the format of
+   it later? Right now sendme payloads are empty. Here's a simple design:
+   we use five bytes in the payload, where the first byte indicates the
+   sendme payload version (0 in the original design, and 1 once we've
+   implemented this proposal), and the rest of the payload is formatted
+   based on the payload version number: in this case, it's simply the
+   four bytes of digest.
+   Is there a better way to version the payload, e.g. a way that is
+   already standard in other parts of the design, so we aren't adding
+   a new paint color to keep track of on the bike shed?
+3.2. Verifying the sendme payload
+   In the current Tor, the exit relay keeps no memory of the cells it
+   has sent down the circuit, so it won't be in a position to verify
+   the digest that it gets back.
+   But fortunately, the exit relay can count also, so it knows which cell
+   is going to trigger the sendme response. Each circuit can have at most
+   10 sendmes worth of data outstanding. So the exit relay will keep
+   a per-circuit fifo queue of the digests from the appropriate cells,
+   and when a new sendme arrives, it pulls off the next digest in line,
+   and verifies that it matches.
+   If a sendme payload has a payload version of 1 yet its digest
+   doesn't match the expected digest, or if the sendme payload has
+   an unexpected payload version (see below about deployment phases),
+   the exit relay must tear down the circuit. (If we later find that
+   we need to introduce a newer payload version in an incompatible way,
+   we would do that by bumping the circuit protocol version.)
+3.3. Making sure there are enough unpredictable bytes in the circuit
+   So far, the design as described fails to a very simple attacker:
+   the client fetches a file whose contents it already knows, and it
+   uses that knowledge to calculate the correct digests and fake its
+   sendmes just like in the original attack.
+   The fix is that the exit relay needs to be able to add some randomness
+   into its cells. It can add this randomness, in a way that's completely
+   orthogonal to the rest of this design, simply by choosing one relay
+   cell every so often and not using the entire relay cell payload for
+   actual data (i.e. using a Length field of less than 498), and putting
+   some random bytes in the remainder of the payload.
+   How many random bytes should the exit relay use, and how often should
+   it use them? There is a tradeoff between security when under attack,
+   and efficiency when not under attack. We think 1 byte of randomness
+   every 1000 cells is a good starting plan, and we can always improve
+   it later without needing to change any of the rest of this design.
+   (Note that the spec currently says "The remainder of the payload
+   is padded with NUL bytes." We think "is" doesn't mean MUST, so we
+   should just be sure to update that part of the spec to reflect our
+   new plans here.)
+4. Deployment Plan
+   In phase one, both sides begin remembering their expected digests,
+   and they learn how to parse sendme payloads. When they receive a
+   sendme with payload version 1, they verify its digest and tear down
+   the circuit if it's wrong. But they continue to send and accept
+   payload version 0 sendmes.
+   In phase two, we flip a switch in the consensus, and everybody starts
+   sending payload version 1 sendmes. Payload version 0 sendmes are
+   still accepted.
+   In phase three, we flip a different switch in the consensus, and
+   everybody starts refusing payload version 0 sendmes.
+   (It has to be two separate switches, not one unified one, because
+   otherwise we'd have a race where relays learn about the update before
+   clients know to start the new behavior.)
+   We'll want to do a bunch of testing in chutney before flipping the
+   switches in the real network: I've long suspected we still have bugs
+   in our sendme timing, and this proposal might expose some of them.
+   Alas, this deployment plan leaves a pretty large window until relays
+   are protected from attack. It's not all bad news though, since we
+   could flip the switches earlier than intended if we encounter a
+   network-wide attack.
+5. Security Discussion
+   Does our design enable any new adversarial capabilities?
+   An adversarial middle relay could attempt to trick the exit into
+   killing an otherwise valid circuit.
+   An adversarial relay can already kill a circuit, but here it could make
+   it appear that the circuit was killed for a legitimate reason (invalid
+   or missing sendme), and make someone else (the exit) do the killing.
+   There are two ways it might do this: by trying to make a valid sendme
+   appear invalid; and by blocking the delivery of a valid sendme. Both of
+   these depend on the ability for the adversary to guess which exitward
+   cell is a sendme cell, which it could do by counting clientward cells.
+   * Making a valid sendme appear invalid
+   A malicious middle could stomp bits in the exitward sendme so
+   that the exit sendme validation fails. However, bit stomping would
+   be detected at the protocol layer orthogonal to this design, and
+   unrecognized exitward cells would currently cause the circuit to be
+   torn down. Therefore, this attack has the same end result as blocking
+   the delivery of a valid sendme.
+   (Note that, currently, clientward unrecognized cells are dropped but
+   the circuit is not torn down.)
+   * Blocking delivery of a valid sendme
+   A malicious middle could simply drop a exitward sendme, so that
+   the exit is unable to verify the digest in the sendme payload. The
+   following exitward sendme cell would then be misaligned with the
+   sendme that the exit is expecting to verify. The exit would kill the
+   circuit because the client failed to prove it has read all of the
+   clientward cells.
+   The benefits of such an attack over just directly killing the circuit
+   seem low, and we feel that the added benefits of the defense outweigh
+   the risks.
+6. Open problems
+   With the proposed defenses in place, an adversary will be unable to
+   successfully use the "continue sending sendmes" part of these attacks.
+   But this proposal won't resolve the "build up many circuits over time,
+   and then use them to attack all at once" issue, nor will it stop
+   sybil attacks like if an attacker makes many parallel connections to
+   a single target relay, or reaches out to many guards in parallel.
+   We spent a while trying to figure out if we can enforce some
+   upper bound on how many circuits a given connection is allowed
+   to have open at once, to limit every connection's potential for
+   launching a bandwidth attack. But there are plausible situations
+   where well-behaving clients accumulate many circuits over time:
+   Ricochet clients with many friends, popular onion services, or even
+   Tor Browser users with a bunch of tabs open.
+   Even though a per-conn circuit limit would produce many false
+   positives, it might still be useful to have it deployed and available
+   as a consensus parameter, as another tool for combatting a wide-scale
+   attack on the network: a parameter to limit the total number of
+   open circuits per conn (viewing each open circuit as a threat) would
+   complement the current work in #24902 to rate limit circuit creates
+   per client address.
+   But we think the threat of parallel attacks might be best handled by
+   teaching relays to react to actual attacks, like we've done in #24902:
+   we should teach Tor relays to recognize when somebody is *doing* this
+   attack on them, and to squeeze down or outright block the client IP
+   addresses that have tried it recently.
+   An alternative direction would be to await research ideas on how guards
+   might coordinate to defend against attacks while still preserving
+   user privacy.
+   In summary, we think authenticating the sendme cells is a useful
+   building block for these future solutions, and it can be (and should
+   be) done orthogonally to whatever sybil defenses we pick later.
+7. References
+   [0] https://blog.torproject.org/blog/new-tor-denial-service-attacks-and-defenses
+   [1] https://www.freehaven.net/anonbib/#sniper14
+   [2] https://www.freehaven.net/anonbib/#torta05
+   [3] https://www.freehaven.net/anonbib/#congestion-longpaths

More information about the tor-commits mailing list