Opened 3 years ago

Last modified 6 months ago

#17773 accepted enhancement

Should clients avoid using guards that lost the Guard flag?

Reported by: arma Owned by: arma
Priority: Medium Milestone: Tor: unspecified
Component: Core Tor/Tor Version:
Severity: Normal Keywords: tor-client guards
Cc: s7r Actual Points:
Parent ID: Points: medium?
Reviewer: Sponsor: SponsorV-can

Description

Nick and I both thought that at least in the past, Tor clients would stop using a relay as their guard, if it loses the Guard flag.

But it looks like the code doesn't do that -- once a relay is your guard, you'll use it in the guard position regardless of whether it has the Guard flag at this moment or not.

This is actually a tricky design decision. In favor of avoiding guards that don't have the guard flag:

  • If they get really slow, we can instruct clients to abandon them.
  • If a relay gets the guard flag for only a short period of time, it will have only a small number of (dedicated) users using it for the next months.

In favor of using non-Guard guards anyway:

  • An attacker can't push you away from your guard by hurting its performance in the eyes of the directory authorities.
  • You won't rotate guards as many times.

That "can't push you away" one looks big. What other aspects should we be considering here?

Child Tickets

Change History (29)

comment:1 Changed 3 years ago by teor

We should consider what happens when we blacklist guards for behaving badly.
(Can someone check my logic here?)

If a guard gets marked as Invalid, then it will be dropped from the consensus, and we'll stop using it as a guard.

If a guard gets marked as BadExit, then we'll keep using it, which is what we want, because it's only interfering with exit traffic. (We hope.)

Are there any other flags we use to mark bad guards?

comment:2 Changed 3 years ago by teor

I think entry_guards_set_from_config() already does something useful - it places entry nodes without the Guard flag after entry nodes with the Guard flag:

    } else if (! node->is_possible_guard) {
      smartlist_add(worse_entry_nodes, (node_t*)node);
      SMARTLIST_DEL_CURRENT(entry_nodes, node);
    }
  } SMARTLIST_FOREACH_END(node);

  /* Now build the new entry_guards list. */
  smartlist_clear(entry_guards);
  /* First, the previously configured guards that are in EntryNodes. */
  smartlist_add_all(entry_guards, old_entry_guards_on_list);
  /* Next, scramble the rest of EntryNodes, putting the guards first. */
  smartlist_shuffle(entry_nodes);
  smartlist_shuffle(worse_entry_nodes);
  smartlist_add_all(entry_nodes, worse_entry_nodes);

comment:3 Changed 3 years ago by s7r

I think we can live with this, given that the goal of 1 entry guard for longer time is to make a client not choose so many times. Fast back of the envelope calculations tell us that you have less chances of getting a bad guard if you stick to one that lost its guard flag as opposite to having to choose again from the relays with active Guard flags.

The fact that if this is done intentionally will make a relay have a very small number of dedicated users for the next months is true, but maybe it's worth the tradeoff - I don't see how you can make this attack a targeted one (not without combining it with other attacks like path bias ; guard turnover for which we have proposals). It's a paradox here, if I am not targeting someone particular (since I can't with this method), it means maybe I am pure bad and just want to mass deanonymize Tor users, in which case a very small number of dedicated users isn't attractive. Also, I don't see how you can defend against this properly, an operator can just keep the guard flag, allow selectively a very small number of dedicated users IP addresses at firewall level and drop the rest (will this lose him the guard flag if he allows traffic only from some users and directory authorities and every IP in the consensus plus every IP address in exit list?).

Another reason to allow this would be that in the future, hopefully we will grow significantly in number of relays that we will have to rotate the Guard flags from time to time between a n% of the relays in the network that fulfill the requirements (maybe a weighted hash ring based on shared randomness).

comment:4 Changed 3 years ago by s7r

Cc: s7r added

comment:5 Changed 3 years ago by nickm

Keywords: must-fix-before-028-rc added

Marking these as must-fix-before-028-rc.

Actually, some of them may not need to get 'fixed' before the rc, but I believe that they should either get fixed, or we should have a good explanation of why they don't need to get fixed.

comment:6 Changed 3 years ago by asn

Keywords: must-fix-before-028-rc removed
Milestone: Tor: 0.2.8.x-finalTor: 0.2.9.x-final
Sponsor: None

I'm gonna push this to 0.2.9 since the correct solution is not obvious here and more research needs to be done. Also, the current situation is indeed not ideal but not terribly broken, so this is not super urgent.

comment:7 Changed 3 years ago by nickm

Points: medium?

comment:8 Changed 3 years ago by isabela

Milestone: Tor: 0.2.9.x-finalTor: 0.2.???

tickets market to be removed from milestone 029

comment:9 Changed 2 years ago by arma

I recommend closing this ticket with the answer "no, leave things as they are".

comment:10 Changed 2 years ago by teor

What if the guard changes keys?
Does the client mark it as down, and use another guard?
(Related to #19074.)

comment:11 Changed 2 years ago by arma

What's *supposed* to happen is that the client decides that its guard isn't Running anymore, so it moves on to another one, but it keeps the first one around for some months in case it comes back.

Last edited 2 years ago by arma (previous) (diff)

comment:12 Changed 2 years ago by arma

Keywords: TorCoreTeam201606 added
Owner: set to arma
Status: newaccepted

comment:13 Changed 2 years ago by asn

Are we sure that we keep on connecting to nodes that used to be guards but are not anymore?

If you check entry_guard_set_status() which gets called by entry_guards_compute_status() everytime we receive a new consensus, you can see:

  else if (!options->UseBridges && !node->is_possible_guard &&
           !routerset_contains_node(options->EntryNodes,node))
    *reason = "not recommended as a guard";

which will later make the entry_guard_t get marked with bad_since. Then we will stop picking it as guard.

To be honest, I'm not sure what's the best behavior here. Both choices (are there only two?) seem to have positives and negatives. FWIW, I'm pretty sure that the (incomplete) prop259 specifies the same behavior as the current code (mark nodes as bad and don't connect to them when they are not guards anymore)

comment:14 Changed 2 years ago by nickm

Sponsor: None

Change Core Tor tickets with sponsor "None" to "", per our practice elsewhere. This will help sorting.

comment:15 Changed 2 years ago by arma

Gosh. You sure look right!

I took this ticket for this month because my plan was to just close it and say we're done.

Now it looks like we will need a better plan than that.

comment:16 Changed 2 years ago by arma

Ok, I looked at the code again, and asn is right. We currently do the opposite of what I thought we did, and based on the discussions above, I think we should change our behavior to do what I thought we did.

Does this want a mini-proposal? How do we best proceed from here? Also, is this choice orthogonal to all the recent prop#259 work?

comment:17 in reply to:  16 Changed 2 years ago by asn

Replying to arma:

Ok, I looked at the code again, and asn is right. We currently do the opposite of what I thought we did, and based on the discussions above, I think we should change our behavior to do what I thought we did.

I also think that the idea of keeping non-Guard relays that were once your guard, has slightly better security properties than ditching them.

I stressed slightly because I don't feel too strong about either way here.

For an example of a negative edge case, consider a relay whose operator is no longer able to keep its uptime and it loses its guard flag. If that relay is flaky, any client that uses it will have to move to other guards when that relay is down, so the client will get exposed to more guards anyway.

Does this want a mini-proposal? How do we best proceed from here? Also, is this choice orthogonal to all the recent prop#259 work?

Funny thing is that all prop259 versions so far (including nick's newest one) seem to suggest the current behavior. That is, upon receiving a fresh consensus, we stop using guards that have lost their Guard flag.

If we think the other approach is better, we should lobby it to Nick for inclusion in his current proposal.

comment:18 Changed 2 years ago by cypherpunks

What is supposed to happen if the guard flag is dropped while the client is connected?

What is supposed to happen if the guard is set manually? Will tor refuse to build circuits?

comment:19 in reply to:  11 Changed 2 years ago by arma

Replying to arma:

What's *supposed* to happen is that the client decides that its guard isn't Running anymore, so it moves on to another one, but it keeps the first one around for some months in case it comes back.

For clarity, we currently think that this is what *does* happen in the code currently.

comment:20 in reply to:  description Changed 2 years ago by arma

Replying to arma:

What other aspects should we be considering here?

See #20509 for a case where we want to take away the Guard flag from relays that are buggy and would make poor guards. In that case we would want clients to jump ship from those relays. And we either do it by taking away their Guard flag, or we do it by rejecting the relays from the network.

comment:21 in reply to:  18 ; Changed 2 years ago by arma

Replying to cypherpunks:

What is supposed to happen if the guard flag is dropped while the client is connected?

I'm not sure what the code does, but I expect that it would leave existing circuits alone, and opt to use a different first hop when making future circuits.

What is supposed to happen if the guard is set manually? Will tor refuse to build circuits?

If you put a relay in your EntryNodes list, Tor should never care whether it has the Guard flag. See the code snippet from asn above where it checks routerset_contains_node(options->EntryNodes,node).

comment:22 Changed 2 years ago by teor

Milestone: Tor: 0.2.???Tor: 0.3.???

Milestone renamed

comment:23 Changed 22 months ago by nickm

Keywords: tor-03-unspecified-201612 added
Milestone: Tor: 0.3.???Tor: unspecified

Finally admitting that 0.3.??? was a euphemism for Tor: unspecified all along.

comment:24 Changed 17 months ago by nickm

Keywords: tor-03-unspecified-201612 removed

Remove an old triaging keyword.

comment:25 Changed 17 months ago by nickm

Keywords: TorCoreTeam201606 removed

comment:26 Changed 16 months ago by arma

This might be a good one to make progress on during the wilmington hackfest (2017).

comment:27 Changed 16 months ago by nickm

Keywords: tor-client guards added

Note that prop271 has substantially changed the original behavior here.

comment:28 Changed 15 months ago by nickm

Sponsor: SponsorV-can

comment:29 in reply to:  21 Changed 6 months ago by arma

Replying to arma:

What is supposed to happen if the guard is set manually? Will tor refuse to build circuits?

If you put a relay in your EntryNodes list, Tor should never care whether it has the Guard flag. See the code snippet from asn above where it checks routerset_contains_node(options->EntryNodes,node).

But see #22204 for a bug in the new design that prevents you from requesting any relays for your first hop that don't have the Guard flag right now. :(

Note: See TracTickets for help on using tickets.