Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-18 Thread Mike Perry
Roger Dingledine:
> On Wed, Apr 11, 2018 at 11:15:44AM +, Mike Perry wrote:
> > > To be clear, the design I've been considering here is simply allowing
> > > reuse between the guard hop and the final hop, when it can't be avoided. I
> > > don't mean to allow the guard (or its family) to show up as all four
> > > hops in the path. Is that the same as what you meant, or did you mean
> > > something more thorough?
> > 
> > By all path restrictions I mean for the last hop of the circuit and the
> > first (though vanguards would be simpler if we got rid of them for other
> > hops, too).
> 
> Can you lay out for us the things to think about in the Vanguard design?
> Last I checked there were quite a few Vanguard design variants, ranging
> from "two vanguards per guard, tree style" to some sort of mesh.
> 
> In particular, it would be convenient if there is a frontrunner design
> that really would benefit from relaxing many path restrictions, and a
> frontrunner design that is not so tied together to the path restriction
> question.

There are two frontrunner forms. One has no path restrictions, the other
would try to perform restriction checks on each layer to ensure that it
is valid and doesn't leak info about other layers or prevent circuit
creation.

They are otherwise the same. Both are mesh; both are tunable in the
number of guards and rotation times in each layer.

I am leaning towards "no restrictions" for vanguards for 0.3.4 because
it is simpler, and it did not strike me that the arguments in their
favor justified trying to implement them quickly in a way that might
cause reachability or path influence risks.
 
> > But I do mean all restrictions, not just guard node choice.
> > The adversary also gets to force you to use a second network path
> > whenever they want via the /16 and node family restrictions.
> 
> Can you give us a specific example here, for this phrase "network
> path"? When you say "second network path" are you thinking in the
> Vanguard world?

Second path to entry into the Tor network (and a second guard),
regardless of vanguards.
 
> > > I'd like to hear more about the "cleverly crafted exit policy" attack
> > 
> >  another way to do this type of exit rotation attack is to cause
> > a client to look up a DNS name where you control the resolver, and keep
> > timing out on the DNS response. The client will then retry the stream
> > request with a new exit. The same thing can also be done by timing out
> > the TCP handshake to a server you control. Both of these attacks can be
> > done with only the ability to inject an img tag into a page.
> > 
> > You repeat this until an exit is chosen that is in the same /16 or
> > family as the guard, and then the client uses a second network path for
> > an unmultiplexed request at a time you control.
> 
> The three fixes that come to mind are
> 
> (A) "Have two guards": so you can pick any exit you like, and then just
> use the guard that doesn't conflict with the exit you picked.
> 
> (B) "Add a bonus hop when needed": First relax the /16 and family
> restrictions, so the remaining issue is reuse of your guard. Then if
> you find that you just chose your guard as your exit, insert an extra
> hop in the middle of that circuit.
> 
> (C) "Exits can't be Guards": First relax the /16 and family restrictions,
> so the remaining issue is reuse of your guard. Then notice that due
> to exit scarcity, guards aren't actually used in the exit position
> anyway. Then enforce that rule (so they can't be in the future either).
> 
> All three of these choices have downsides. But all three of them look
> like improvements over the current situation -- because of how crappy
> the current situation is.
> 
> (Rejected option (D): "Just start allowing it": Relax the /16 and
> family restrictions, and also relax the rule where relays refuse a
> circuit that goes right back where it came from. Giving the middle node
> that much information about the circuit just wigs me out.)
> 
> Also, notice that I think Mike's proposed design will turn out to be some
> combination of "A" and also something like "B" or "C", because even if
> you start with two guards, if you don't add a new guard right when your
> first guard goes down, you might find yourself in the situation where
> you have one working guard, and you pick it as your exit, and now you
> need to do *something*.

The one-guard-down case does impact things. But even when this does
happen (which should be rare), it should only be true for a small window
of time before the consensus updates.

The "down" guard should either be temporarily overloaded, or fully down
and kicked off the consensus. I think we should only add a new guard
when one falls out of the consensus, or both are unreachable/unusable.

This is why I think it is OK to take an incremental approach and
start with A, and roll out things like B and C and other restriction
relaxations.

During these edge cases, the most important property that we should

Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-18 Thread Roger Dingledine
On Wed, Apr 11, 2018 at 11:15:44AM +, Mike Perry wrote:
> > To be clear, the design I've been considering here is simply allowing
> > reuse between the guard hop and the final hop, when it can't be avoided. I
> > don't mean to allow the guard (or its family) to show up as all four
> > hops in the path. Is that the same as what you meant, or did you mean
> > something more thorough?
> 
> By all path restrictions I mean for the last hop of the circuit and the
> first (though vanguards would be simpler if we got rid of them for other
> hops, too).

Can you lay out for us the things to think about in the Vanguard design?
Last I checked there were quite a few Vanguard design variants, ranging
from "two vanguards per guard, tree style" to some sort of mesh.

In particular, it would be convenient if there is a frontrunner design
that really would benefit from relaxing many path restrictions, and a
frontrunner design that is not so tied together to the path restriction
question.

> But I do mean all restrictions, not just guard node choice.
> The adversary also gets to force you to use a second network path
> whenever they want via the /16 and node family restrictions.

Can you give us a specific example here, for this phrase "network
path"? When you say "second network path" are you thinking in the
Vanguard world?

> We're not using one guard in the current Tor. We're using two, and the
> second one is only used for unmultiplexed activity. That is one property
> I don't like about our "let's pretend to use one guard" status quo.

Right, I agree.

> > I'd like to hear more about the "cleverly crafted exit policy" attack
> 
>  another way to do this type of exit rotation attack is to cause
> a client to look up a DNS name where you control the resolver, and keep
> timing out on the DNS response. The client will then retry the stream
> request with a new exit. The same thing can also be done by timing out
> the TCP handshake to a server you control. Both of these attacks can be
> done with only the ability to inject an img tag into a page.
> 
> You repeat this until an exit is chosen that is in the same /16 or
> family as the guard, and then the client uses a second network path for
> an unmultiplexed request at a time you control.

Hm! Yes, this is a yucky one. (I don't think just an img tag would be
enough, because Tor will try a few circuits and then give up. You'd need
some sort of javascript or refresh chain or the like that generates new
addresses and tries them in succession. But that's totally feasible.)

This one is also yucky because we could also imagine a different way to
pick your path, where when you're selecting your exit, you avoid choosing
exits which would conflict with your guard, and thus you'll never be
pushed off of your guard. But then the destination website can do this
same attack over time and notice which exit you never try to use. So
this is a case where to blend in best, we *need* to be willing to use
all of the potential exits.

But since normal exit circuits are three hops, if we simply relax the
path restrictions, we could be making a circuit of the form "A - B - A",
which would not only stand out as weird to B, but actually right now a
relay in B's position will refuse such a circuit. Bad news all around.

The three fixes that come to mind are

(A) "Have two guards": so you can pick any exit you like, and then just
use the guard that doesn't conflict with the exit you picked.

(B) "Add a bonus hop when needed": First relax the /16 and family
restrictions, so the remaining issue is reuse of your guard. Then if
you find that you just chose your guard as your exit, insert an extra
hop in the middle of that circuit.

(C) "Exits can't be Guards": First relax the /16 and family restrictions,
so the remaining issue is reuse of your guard. Then notice that due
to exit scarcity, guards aren't actually used in the exit position
anyway. Then enforce that rule (so they can't be in the future either).

All three of these choices have downsides. But all three of them look
like improvements over the current situation -- because of how crappy
the current situation is.

(Rejected option (D): "Just start allowing it": Relax the /16 and
family restrictions, and also relax the rule where relays refuse a
circuit that goes right back where it came from. Giving the middle node
that much information about the circuit just wigs me out.)

Also, notice that I think Mike's proposed design will turn out to be some
combination of "A" and also something like "B" or "C", because even if
you start with two guards, if you don't add a new guard right when your
first guard goes down, you might find yourself in the situation where
you have one working guard, and you pick it as your exit, and now you
need to do *something*.

> Our path restrictions also cause normal exiting clients to use a second
> guard for unmultiplexed activity, at adversary controlled times, or just
> at periodically at random.

Just to make 

Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-13 Thread Mike Perry
Roger Dingledine:
> On Sat, Mar 31, 2018 at 06:52:51AM +, Mike Perry wrote:
> > 3.1. Eliminate path restrictions entirely
> > 
> I'm increasingly a fan of this option, the more I read these threads.
> 
> Let's examine the two attacker assumptions behind two of the attacks
> we're worried about.
> 
> Attack one: the client's local ISP collects coarse netflow logs, and these
> logs aren't detailed enough to allow a traffic volume detection attack on
> an existing long-lived TLS flow, so the connection to that first guard
> is safe; but a connection to that second guard will be unusual and not
> multiplexed and at exactly the time of the adversary-controlled circuit
> that triggered it, so that second guard, because it is used so rarely,
> is dangerous to use.
> 
> Attack two: if the client uses its guard as the first hop of its circuit
> and also the adversary-requested fourth hop, then the guard can do
> pairwise traffic correlation attacks on all of its circuits and realize
> that these two circuits it has are really two pieces of the same circuit.
> 
> This second attack seems weird to me. One reason is because in attack
> one we're brushing aside the traffic analysis as hard, whereas in attack
> two we're assuming it's trivial and perfect. But the simpler reason is:
> if your guard is going to participate in a traffic correlation attack
> against you, then it could just as easily team up with some other relay
> that the adversary picked. That is, avoiding reusing your guard on the
> other end of the circuit isn't going to save you if your guard is out
> to get you.

I agree. I am not concerned about attack two. But we're not choosing
between just these two attacks.
 
> To be clear, the design I've been considering here is simply allowing
> reuse between the guard hop and the final hop, when it can't be avoided. I
> don't mean to allow the guard (or its family) to show up as all four
> hops in the path. Is that the same as what you meant, or did you mean
> something more thorough?

By all path restrictions I mean for the last hop of the circuit and the
first (though vanguards would be simpler if we got rid of them for other
hops, too). But I do mean all restrictions, not just guard node choice.
The adversary also gets to force you to use a second network path
whenever they want via the /16 and node family restrictions. And it
happens naturally all the time.

We're not using one guard in the current Tor. We're using two, and the
second one is only used for unmultiplexed activity. That is one property
I don't like about our "let's pretend to use one guard" status quo.

The second thing I don't like is that one guard is fragile, which
enables confirmation attacks when it can be made to go down.

> I think "can't be avoided" means HSDir, IP, RP -- which I note are all
> onion service related circuits.
> 
> I'd like to hear more about the "cleverly crafted exit policy" attack, and
> I wonder if we can't solve that differently. For example, if it's about
> making you do a request to a port that only one exit relay allows, and
> ha ha whoops your guard was on the same /16 as that exit relay... maybe
> it's time for the dir auths to not advertise super rare ports? This was
> one of the topics in the users-get-routed paper too.

Yes that is the one I was talking about.

However, another way to do this type of exit rotation attack is to cause
a client to look up a DNS name where you control the resolver, and keep
timing out on the DNS response. The client will then retry the stream
request with a new exit. The same thing can also be done by timing out
the TCP handshake to a server you control. Both of these attacks can be
done with only the ability to inject an img tag into a page.

You repeat this until an exit is chosen that is in the same /16 or
family as the guard, and then the client uses a second network path for
an unmultiplexed request at a time you control.

> One non-starter idea would be to move onion-service-related Tors to two
> guards, and leave other Tors at one guard. It's a non-starter because of
> course advertising which you are to your local network is no good. But
> that idea gave me a different perspective on this discussion: I wonder
> how much this design decision comes down to making all Tors use two
> guards in order to protect the onion-service-related Tors, which are
> the only ones who actually need it?

Our path restrictions also cause normal exiting clients to use a second
guard for unmultiplexed activity, at adversary controlled times, or just
at periodically at random.
 
> >   However, while removing path restrictions will solve the immediate
> >   problem, it will not address other instances where Tor temporarily opts
> >   use a second guard due to congestion, OOM, or failure of its primary
> >   guard, and we're still running into bugs where this can be adversarially
> >   controlled or just happen randomly[5].
> 
> I continue to think we need to fix these. I'm glad to see 

Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-13 Thread Roger Dingledine
On Sat, Mar 31, 2018 at 06:52:51AM +, Mike Perry wrote:
>   The main argument for switching to two guards is that because of Tor's
>   path restrictions, we're already using two guards, but we're using them
>   in a suboptimal and potentially dangerous way.
> 
>   Tor's path restrictions enforce the condition that the same node cannot
>   appear twice in the same circuit, nor can nodes from the same /16 subnet
>   or node family be used in the same circuit.
> 
>   Tor's paths are also built such that the exit node is chosen first and
>   held fixed during guard node choice, as are the IP, HSDIR, and RPs for
>   onion services. This means that whenever one of these nodes happens to
>   be the guard[4], or be in the same /16 or node family as the guard, Tor
>   will build that circuit using a second "primary" guard, as per proposal
>   271[7].
> 
>   Worse still, the choice of RP, IP, and exit can all be controlled by an
>   adversary (to varying degrees), enabling them to force the use of a
>   second guard at will.

I agree with you that we should do something about this bug, where Tor
clients will switch to a rarely used guard in some situations. Our fix
from ticket #14917 was not a good fix. More on that below in Section 3.1.

>   Not surprisingly,
>   the two guard adversary gets to compromise clients roughly twice as
>   quickly, but the timescales are still rather large even for the 10%
>   adversary: they only have 50% chance of success after 4 rotations, which
>   will take about 14 months with Tor's 3.5 month guard rotation.

Three thoughts here:

(A) You're right, 14 months doesn't sound bad here.

(B) This calculation was ignoring churn, right? That is, guards going
away before you wanted to rotate from them. So another way to phrase that
would be "once eight of your guards have gone away, you're in bad shape"?
Looking at it that way, it seems like two guards is more than twice
as scary as one, since *either* of them going away moves you one step
closer on the path. Not the end of the world, but worth noticing. And
maybe partially solvable by your "when one of your two goes away, stick
to the remaining one" design; more on that below.

(C) Similarly, we should be sure to remember the network adversary
here too. I don't know a simple way to reason about it well. Using more
guards over time could be *less* than twice as scary, because sometimes
the network paths overlap so you don't expose as much new surface area
as you might have. And using more guards over time could be *more*
than twice as scary, if the question is whether your traffic ever goes
over that one bad place, since you have an exponentially low chance to
*never* pick a guard where your traffic to/from that guard travels over
the bad place. It really depends on your location, the guard locations,
the Internet topology, and a bunch of other confusing factors.

>   Furthermore, our use of separate directory guards (and three of them)
>   means that we're not really changing the situation much with the
>   addition of another regular guard. Right now, directory guard use alone
>   is enough to track all Tor users across the entire world.

Shit, you're right. The guard set fingerprint issue remains right now,
because we never solved the directory guard side of it. :(

>   While the directory guard problem could be fixed[12] (and should be
>   fixed), it is still the case that another mechanism should be used for
>   the general problem of guard-vs-location management[9].

The part that freaks me out about all the designs I've seen here is the
attack where the local adversary advertises a series of local wireless
addresses, first to make you keep generating new guard contexts (similar
to forcing quick guard rotation), or second to guess-and-check whether
you've already got a guard context for some wireless address in the next
city over. Maybe it can be solved by proper UI ("we'll just delegate
the decision to the user"), but hoo boy. But that's a separate proposal
fortunately. :)

> 3.1. Eliminate path restrictions entirely
> 
I'm increasingly a fan of this option, the more I read these threads.

Let's examine the two attacker assumptions behind two of the attacks
we're worried about.

Attack one: the client's local ISP collects coarse netflow logs, and these
logs aren't detailed enough to allow a traffic volume detection attack on
an existing long-lived TLS flow, so the connection to that first guard
is safe; but a connection to that second guard will be unusual and not
multiplexed and at exactly the time of the adversary-controlled circuit
that triggered it, so that second guard, because it is used so rarely,
is dangerous to use.

Attack two: if the client uses its guard as the first hop of its circuit
and also the adversary-requested fourth hop, then the guard can do
pairwise traffic correlation attacks on all of its circuits and realize
that these two circuits it has are really two pieces of the same circuit.

This second attack 

Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-12 Thread George Kadianakis
Mike Perry  writes:

> In-line below for ease of comment. Also available at:
> https://gitweb.torproject.org/user/mikeperry/torspec.git/tree/proposals/xxx-two-guard-nodes.txt?h=twoguards
>
> ===
>
> Filename: xxx-two-guard-nodes.txt
> Title: The move to two guard nodes
> Author: Mike Perry
> Created: 2018-03-22
> Supersedes: Proposal 236
>
> 
>
> 3.1. Eliminate path restrictions entirely
>
>   If Tor decided to stop enforcing /16, node family, and also allowed the
>   guard node to be chosen twice in the path, then under normal conditions,
>   it should retain the use of its primary guard.
>
>   This approach is not as extreme as it seems on face. In fact, it is hard
>   to come up with arguments against removing these restrictions. Tor's
>   /16 restriction is of questionable utility against monitoring, and it can
>   be argued that since only good actors use node family, it gives influence
>   over path selection to bad actors in ways that are worse than the benefit
>   it provides to paths through good actors[10,11].
>
>   However, while removing path restrictions will solve the immediate
>   problem, it will not address other instances where Tor temporarily opts
>   use a second guard due to congestion, OOM, or failure of its primary
>   guard, and we're still running into bugs where this can be adversarially
>   controlled or just happen randomly[5].
>

Seems like the above paragraph is our main argument against removing
path restrictions.

Might be worth pointing out that if congestion/OOM attacks are in our
threat model against the current single guard design, then the same
adversary can force prop#291 to open a connection to the *third* guard
by first doing an OOM/congestion attack against one of your first two
guards, and then pushing you to your third guard using a path
restriction attack (#14917).

Thought that I should mention that because it might be an argument for
both moving to two guards and also lifting some path restrictions...
___
tor-dev mailing list
tor-dev@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev


Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-10 Thread George Kadianakis
Mike Perry  writes:

> In-line below for ease of comment. Also available at:
> https://gitweb.torproject.org/user/mikeperry/torspec.git/tree/proposals/xxx-two-guard-nodes.txt?h=twoguards
>
> ===
>
> Filename: xxx-two-guard-nodes.txt
> Title: The move to two guard nodes
> Author: Mike Perry
> Created: 2018-03-22
> Supersedes: Proposal 236
>
> 
>
> 3.1. Eliminate path restrictions entirely
>
>   If Tor decided to stop enforcing /16, node family, and also allowed the
>   guard node to be chosen twice in the path, then under normal conditions,
>   it should retain the use of its primary guard.
>
>   This approach is not as extreme as it seems on face. In fact, it is hard
>   to come up with arguments against removing these restrictions. Tor's
>   /16 restriction is of questionable utility against monitoring, and it can
>   be argued that since only good actors use node family, it gives influence
>   over path selection to bad actors in ways that are worse than the benefit
>   it provides to paths through good actors[10,11].
>
>   However, while removing path restrictions will solve the immediate
>   problem, it will not address other instances where Tor temporarily opts
>   use a second guard due to congestion, OOM, or failure of its primary
>   guard, and we're still running into bugs where this can be adversarially
>   controlled or just happen randomly[5].
>

Hello Mike,

IMO we should not portray removing the above path restrictions as
something extreme, until we have good evidence that those path
restrictions offer something positive in the cases we are
examining. Personally, I see the result of this proposal of making Sybil
attacks two times more quick (section 2.3), as an equally radical
result.

That said, I feel that this proposal is valuable and I'm not trying to
say that I don't like this proposal, or that I don't buy the
arguments. I'm trying to say that I don't know how to weight the
tradeoffs here so that I gain confidence, because I'm not sure how
people are trying to attack Tor clients right now.

The way I see it is that if we adopt this proposal:
+ We are better defended against active attacks like congestion attacks
  and OOM/DoS attacks.
+ We improve network health by reducing congestion to certain guards.
- Sybil attacks can be performed two times more quickly.

IMO, we should not rush this decision for 034, given that it's a
concensus parameter change that can happen instantaneously.  However, we
should do the following soon:

1) Accept that there is no single best guard topology, and fix our
   codebase to work well with either one guard or two guards, so that we
   are ready for when we flip the switch. Perhaps we can fix
   #25753/#25705/etc. in a way that works well both now and in the
   2-guard future?

2) Investigate our current prop#271 codebase and make sure that the
   paragraph below will work as intended if we do this proposal.

3) Involve more peple into this (Roger, NRL, etc.) and have them think
   about this, to gain more confidence.

Do you think this approach is too slow or backwards?

Just to speed it up, I just did (2) below:

>   Note that for this analysis to hold, we have to ensure that nodes that
>   are at RESOURCELIMIT or otherwise temporarily unresponsive do not cause
>   us to consider other primary guards beyond than the two we have chosen.
>   This is accomplished by setting guard-n-primary-guards to 2 (in addition
>   to setting guard-n-primary-guards-to-use to 2). With this parameter
>   set, the proposal 271 algorithm will avoid considering more than our two
>   guards, unless *both* are down at once.
>

OK, the above paragraph is basically the juice of this proposal! I spent
all day today to investigate how this would work! The results are very
positive, but also not 100% straightforward because of the various
intricancies of prop#271.

[First of all, there is no way to simulate the above topology using the
config file because if you set NumEntryGuards=2 in your torrc, Tor will
setup 4 primary guards because of the way get_n_primary_guards()
works. So I hacked my Tor client to *have* 2 primary guards
(guard-n-primary-guards), and *use* 2 primary guards
(guard-n-primary-guards-to-use).]

The good part: This topology works exactly how the proposal wants it to
work. Because of the way primary guards work, you will have 2 primary
guards, and if one of them goes down you will always use the other
primary, instead of falling back to a third guard. That's excellent, but
it's also abusing the primary guard feature in a good way but not in the
way we were intending it to be used.

Here are the side-effects from this abuse:

- By reducing the amount of primaries from three to two, it's more
  likely that all primaries can be down at a given time. Prop#271 was
  written with an inherent assumption that one of the primaries will
  always be reachable, because when all of them are down the code goes
  into an "oh 

Re: [tor-dev] Proposal: The move to two guard nodes

2018-04-03 Thread Nick Mathewson
On Sat, Mar 31, 2018 at 2:52 AM, Mike Perry  wrote:
> In-line below for ease of comment. Also available at:
> https://gitweb.torproject.org/user/mikeperry/torspec.git/tree/proposals/xxx-two-guard-nodes.txt?h=twoguards
>
> ===
>
> Filename: xxx-two-guard-nodes.txt
> Title: The move to two guard nodes
> Author: Mike Perry
> Created: 2018-03-22
> Supersedes: Proposal 236

Added as proposal 291!
___
tor-dev mailing list
tor-dev@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev


[tor-dev] Proposal: The move to two guard nodes

2018-04-02 Thread Mike Perry
In-line below for ease of comment. Also available at:
https://gitweb.torproject.org/user/mikeperry/torspec.git/tree/proposals/xxx-two-guard-nodes.txt?h=twoguards

===

Filename: xxx-two-guard-nodes.txt
Title: The move to two guard nodes
Author: Mike Perry
Created: 2018-03-22
Supersedes: Proposal 236

0. Background

  Back in 2014, Tor moved from three guard nodes to one guard node[1,2,3].

  We made this change primarily to limit points of observability of entry
  into the Tor network for clients and onion services, as well as to
  reduce the ability of an adversary to track clients as they move from
  one internet connection to another by their choice of guards.


1. Proposed changes

1.1. Switch to two guards per client

  When this proposal becomes effective, clients will switch to using
  two guard nodes. The guard node selection algorithms of Proposal 271
  will remain unchanged. Instead of having one primary guard "in use",
  Tor clients will always use two.

  This will be accomplished by setting the guard-n-primary-guards-to-use
  consensus parameter to 2, as well as guard-n-primary-guards to 2.
  (Section 3.1 covers the reason for both parameters). This is equivalent
  to using the torrc option NumEntryGuards=2, which can be used for
  testing behavior prior to the consensus update.

1.2. Enforce Tor's path restrictions across this guard layer

  In order to ensure that Tor can always build circuits using two guards
  without resorting to a third, they must be chosen such that Tor's path
  restrictions could still build a path with at least one of them,
  regardless of the other nodes in the path.

  In other words, we must ensure that both guards are not chosen from the
  same /16 or the same node family. In this way, Tor will always be able to
  build a path using these guards, preventing the use of a third guard.


2. Discussion

2.1. Why two guards?

  The main argument for switching to two guards is that because of Tor's
  path restrictions, we're already using two guards, but we're using them
  in a suboptimal and potentially dangerous way.

  Tor's path restrictions enforce the condition that the same node cannot
  appear twice in the same circuit, nor can nodes from the same /16 subnet
  or node family be used in the same circuit.

  Tor's paths are also built such that the exit node is chosen first and
  held fixed during guard node choice, as are the IP, HSDIR, and RPs for
  onion services. This means that whenever one of these nodes happens to
  be the guard[4], or be in the same /16 or node family as the guard, Tor
  will build that circuit using a second "primary" guard, as per proposal
  271[7].

  Worse still, the choice of RP, IP, and exit can all be controlled by an
  adversary (to varying degrees), enabling them to force the use of a
  second guard at will.

  Because this happens somewhat infrequently in normal operation, a fresh
  TLS connection will typically be created to the second "primary" guard,
  and that TLS connection will be used only for the circuit for that
  particular request. This property makes all sorts of traffic analysis
  attacks easier, because this TLS connection will not benefit from any
  multiplexing.

  This is more serious than traffic injection via an already in-use
  guard because the lack of multiplexing means that the data retention
  level required to gain information from this activity is very low, and
  may exist for other reasons. To gain information from this behavior, an
  adversary needs only connection 5-tuples + timestamps, as opposed to
  detailed timeseries data that is polluted by other concurrent activity
  and padding.

  In the most severe form of this attack, the adversary can take a suspect
  list of Tor client IP addresses (or the list of all Guard node IP addresses)
  and observe when secondary Tor connections are made to them at the time when
  they cycle through all guards as RPs for connections to an onion
  service. This adversary does not require collusion on the part of observers
  beyond the ability to provide 5-tuple connection logs (which ISPs may retain
  for reasons such as netflow accounting, IDS, or DoS protection systems).

  A fully passive adversary can also make use of this behavior. Clients
  unlucky enough to pick guard nodes in heavily used /16s or in large node
  families will tend to make use of a second guard more frequently even
  without effort from the adversary. In these cases, the lack of
  multiplexing also means that observers along the path to this secondary
  guard gain more information per observation.

2.2. Why not MOAR guards?

  We do not want to increase the number of observation points for client
  activity into the Tor network[1]. We merely want better multiplexing for
  the cases where this already happens.

2.3. Can you put some numbers on that?

  The Changing of the Guards[13] paper studies this from a few different
  angles, but one of the crucially missing