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?
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
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);
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).
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.
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.
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.
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)
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?
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.
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.
See #20509 (moved) 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.
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).
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 (moved) 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. :(