Filename: 188-bridge-guards.txt
Title: Bridge Guards and other anti-enumeration defenses
Author: Nick Mathewson
Created: 14 Oct 2011
Status: Open
1. Overview
Bridges are useful against censors only so long as the adversary
cannot easily enumerate their addresses. I propose a design to make
it harder for an adversary who controls or observes only a few
nodes to enumerate a large number of bridges.
Briefly: bridges should choose guard nodes, and use the Tor
protocol's "Loose source routing" feature to re-route all extend
requests from clients through an additional layer of guard nodes
chosen by the bridge. This way, only a bridge's guard nodes can
tell that it is a bridge, and the attacker needs to run many more
nodes in order to enumerate a large number of bridges.
I also discuss other ways to avoid enumeration, recommending some.
These ideas are due to a discussion at the 2011 Tor Developers'
Meeting in Waterloo, Ontario. Practically none of the ideas here
are mine; I'm just writing up what I remember.
2. History and Motivation
Under the current bridge design, an attacker who runs a node can
identify bridges by seeing which "clients" make a large number of
connections to it, or which "clients" make connections to it in the
same way clients do. This has been a known attack since early
versions {XXXX check} of the design document; let's try to fix it.
2.1. Related ideas: Guard nodes
The idea of guard nodes isn't new: since 0.1.1, Tor has used guard
nodes (first designed as "Helper" nodes by Wright et al in {XXXX})
to make it harder for an adversary who controls a smaller number of
nodes to eavesdrop on clients. The rationale was: an adversary who
controls or observes only one entry and one exit will have a low
probability of correlating any single circuit, but over time, if
clients choose a random entry and exit for each circuit, such an
adversary will eventually see some circuits from each client with a
probability of 1, thereby building a statistical profile of the
client's activities. Therefore, let each client choose its entry
node only from among a small number of client-selected "guard"
nodes: the client is still correlated with the same probability as
before, but now the client has a nonzero chance of remaining
unprofiled.
2.2. Related idea: Loose source routing
Since the earliest versions of Onion Routing, the protocol has
provided "loose source routing". In strict source routing, the
source of a message chooses every hop on the message's path. But
in loose source routing, the message traverses the selected nodes,
but may also traverse other nodes as well. In other words, the
client selects nodes N_a, N_b, and N_c, but the message may in fact
traverse any sequence of nodes N_1...N_j, so long as N_1=N_a,
N_x=N_b, and N_y=N_c, for 1 < x < y.
Tor has retained this feature, but has not yet made use of it.
3. Design
Every bridge currently chooses a set of guard nodes for its
circuits. Bridges should also re-route client circuits through
these circuits.
Specifically, when a bridge receives a request from a client to
extend a circuit, it should first create a circuit to its guard,
and then relay that extend cell through the guard. The bridge
should add an additional layer of encryption to outgoing cells on
that circuit corresponding to the encryption that the guard will
remove, and remove a layer of encryption on incoming cells on that
circuit corresponding to the encryption that the guard will add.
3.1. An example
This example doesn't add anything to the design above, but has some
interesting inline notes.
- Alice has connected to her bridge Bob, and built a circuit
through Bob, with the negotiated forward and reverse keys KB_f
and KB_r.
- Alice then wants to extend the circuit to node Charlie. She
makes a hybrid-encrypted onionskin, encrypted to Charlie's
public key, containing her chosen g^x value. She puts this in
an extend cell: "Extend (Charlie's address) (Charlie's OR
Port) (Onionskin) (Charlie's ID)". She encrypts this with
KB_f and sends it as a RELAY_EARLY cell to Bob.
- Bob receives the RELAY_EARLY cell, and decrypts it with KB_f.
He then sees that it's an extend cell for him.
So far, this is exactly the same as the current procedure that
Alice and Bob would follow. Now we diverge:
- Instead of connecting to Charlie directly, Bob makes sure that
he is connected to his guard, Guillaume. Bob uses a
CREATE_FAST cell (or a CREATE cell, but see 4.1 below) to open a
circuit to Guillaume. Now Bob and Guillaume share keys KG_f
and KG_b.
- Now Bob encrypts the Extend cell body with KG_f and sends it
as a RELAY_EARLY cell to Guillaume.
- Guillaume receives it, decrypts it with KG_f, and sees:
"Extend (Charlie's address) (Charlie's OR Port) (Onionskin)
(Charlie's ID)". Guillaume acts accordingly: creating a
connection to Charlie if he doesn't have one, ensuring that
the ID is as expected, and then sending the onionskin in a
create cell on that connection.
Note that Guillaume is behaving exactly as a regular node
would upon receiving an Extend cell.
- Now the handshake finishes. Charlie receives the onionskin
and sends Guillaume "CREATED g^y,KH". Guillaume sends Bob
"E(KG_r, EXTENDED g^y KH)". (Charlie and Guillaume are still
running as regular Tor nodes do today).
- With this extend cell, and with all future relay cells
received on this circuit, Bob first decrypts the cell with
KG_r, then re-encrypts it with KB_r, then passes it to Alice.
When Alice receives the cell, it will be just as she would
have received if Bob had extended to Charlie directly.
- With all future outgoing cells that he receives from Alice,
Bob first decrypts the cell with KA_f, and if the cell does
not have Bob as its destination, Bob encrypts it with KG_f
before passing it to Guillaume.
Note that this design does not require that our stream cipher
operations be transitive, even though they are.
Note also that this design requires no change in behavior from any
node other than Bob the bridge.
Finally, observe that even though the circuit is one hop longer
than it would be otherwise, no relay's count of permissible
RELAY_EARLY cells falls lower than it otherwise would. This is
because the extra hop that Bob adds is done with a CREATE_FAST
cell, and so he does not need to send any RELAY_EARLY cells not
originated by Alice.
4. Other ideas and alternative designs
In addition to the design above, there are more ways to try to
prevent enumeration.
4.1. Make it harder to tell clients from bridges
Right now, there are multiple ways for the node after a bridge to
distinguish a circuit extended through the bridge from one
originating at the bridge. (This lets the node after the bridge
tell that a bridge is talking to it.)
One of the giveaways here is that the first hop in a circuit is
created with CREATE_FAST cells, but all subsequent hops are created
with CREATE cells. In the above design, it's no longer quite so
simple to tell, since all of the circuits that extend through a
bridge now reach its guards through CREATE_FAST cells, whether the
bridge originated them or not.
(If we adopt a faster circuit extension algorithm -- for example,
Goldberg, Stebila, and Ustaoglu's design instantiated over
curve25519 -- we could also solve this issue by eliminating
CREATE_FAST/CREATED_FAST entirely, which would also help our
security margin a little.)
The CREATE/CREATE_FAST distinction is not the only way for a
bridge's guard to tell bridges from orginary clients, however.
Most importantly, a busy bridge will open far more circuits than a
client would. More subtly, the timing on response from the client
will be higher and more highly variable that it would be with an
ordinary client. I don't think we can make bridges behave wholly
indistinguishably from clients: that's why we should go with guard
nodes for bridges.
4.2. Client-enforced bridge guards
What if Tor didn't have loose source routing? We could have
bridges tell clients what guards to use by advertising those guard
in their descriptors, and then refusing to extend circuits to any
other nodes. This change would require all clients to upgrade in
order to be able to use the newer bridges, and would quite possibly
cause a fair amount of pain along the way.
Fortunately, we don't need to go down this path. So let's not!
4.3. Separate bridge-guards and client-guards
In the design above, I specify that bridges should use the same
guard nodes for extending client circuits as they use for their own
circuits. It's not immediately clear whether this is a good idea
or not. Having separate sets would seem to make the two kinds of
circuits more easily distinguishable (even though we already assume
they are distinguishable). Having different sets of guards would
also seem like a way to keep the nodes who guard our own traffic
from learning that we're a bridge... but another set of nodes will
learn that anyway, so it's not clear what we'd gain.
5. Other considerations
What fraction of our traffic is bridge traffic? Will this alter
our circuit selection weights?
Are the current guard selection/evaluation/replacement mechanisms
adequate for bridge guards, or do bridges need to get more
sophisticated?