Squeezing non-relays at the entry node

Roger Dingledine arma at mit.edu
Mon Dec 14 01:23:14 UTC 2009

Hi folks (Nick in particular),

I've been pondering other performance improvements. One of them is to
rate-limit client connections as they enter the network. Rate limiting
in the Tor client itself would work better, but it's not a very stable
equilibrium -- it encourages people to switch to security disasters
like tortunnel.

So I'm looking at rate-limiting non-relay OR connections. Here's the

diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index aa26bf8..3f984bf 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -333,10 +333,24 @@ connection_or_init_conn_from_address(or_connection_t *conn
   or_options_t *options = get_options();
   routerinfo_t *r = router_get_by_digest(id_digest);
-  conn->bandwidthrate = (int)options->BandwidthRate;
-  conn->read_bucket = conn->bandwidthburst = (int)options->BandwidthBurst;
   connection_or_set_identity_digest(conn, id_digest);

+  if (r || router_get_consensus_status_by_id(id_digest)) {
+    /* It's in the consensus, or we have a descriptor for it meaning it
+     * was probably in a recent consensus. It's a recognized relay:
+     * give it full bandwidth. */
+    conn->bandwidthrate = (int)options->BandwidthRate;
+    conn->read_bucket = conn->bandwidthburst = (int)options->BandwidthBurst;
+  } else { /* Not a recognized relay. Squeeze it down based on the
+            * suggested bandwidth parameters in the consensus. */
+    conn->bandwidthrate =
+      (int)networkstatus_get_param(NULL, "bwconnrate",
+                                   (int)options->BandwidthRate);
+    conn->read_bucket = conn->bandwidthburst =
+      (int)networkstatus_get_param(NULL, "bwconnburst",
+                                   (int)options->BandwidthBurst);
+  }
   conn->_base.port = port;
   tor_addr_copy(&conn->_base.addr, addr);
   tor_addr_copy(&conn->real_addr, addr);

As you can see, I'm making it configurable inside the consensus, so we
can experiment with it rather than rolling it out and then changing our
minds later. I don't have a good sense of whether it will be a good move,
but the only way I can imagine to find out is to try it.

I'm imagining trying it out with a rate of 20KB and a burst of 500KB.

As a nice side effect, we'll also be rolling out the infrastructure for
one defense against Sambuddho's "approximating a global passive adversary"
congestion attack, if the attack ever gets precise enough that we can
try out our defense and compare.

In the distant future, where we've deployed a design where not all relays
get to see the unified networkstatus consensus, we'll have to stop voting
for a modified bwconnrate and bwconnburst, since the relays won't be
able to know (at least this way) if it's a genuine relay. Maybe part
of that design will be to present a signed credential proving you're a
public relay. In any case, we have a way to disable this feature when
that distant future arrives.

We're also squeezing down bridge relays by this feature, since the public
relays can't tell the difference between a bridge and a client. At some
point we should make sure that bridges send their client traffic over
different TCP connections than their own traffic. That's a separate
discussion though.

It shouldn't impact bandwidth bootstrapping tests, since those aim to
spread 500KB of traffic across 4 circuits.

It would impact Mike's bwauthority tests. We'd want to make an exception
for those Tors. I think we'd leave the torperf deployments alone, since
after all their goal is to measure "realistic" client performance.

It could also impact initial directory info bootstrapping -- if you try
to fetch 1MB from a particular dir mirror, it would slow down the second
half of that download. We'd want to keep an eye on how much that changes.

A more thorough solution would be to rate-limit all the OR conns coming
from a particular non-relay into the same bucket, to prevent people
getting around the limits by opening multiple TCP connections. But it's
actually not so easy to open multiple conns to the same destination in
Tor; plus I'm aiming to solve this for the general case where people
are overloading relays and don't even know it's a bad thing.

My main concern here is that I wonder if we are being thorough enough at
detecting "is a relay". It checks the consensus and the descriptor cache
currently. So if the authorities think you're not Running, they won't put
you in the consensus, and no relays will hear about you. If you go up and
down, relays that serve dirport info will have your descriptor cached,
so they'll recognize you so long as you were around in the past day or so.

Relays that don't serve dirport info will stop fetching descriptors,
but they'll continue to fetch the consensus. So they'll still mostly work.

Are there any other cases that are going to be a problem? Are there better
(simple, easy to deploy soon) ways to decide if the peer is a relay?


More information about the tor-dev mailing list