``` Filename: 310-bandaid-on-guard-selection.txt Title: Towards load-balancing in Prop 271 Author: Florentin Rochet, Aaron Johnson et al. Created: 2019-10-27 Supersedes: 271 Status: Closed 1. Motivation and Context Prop 271 causes guards to be selected with probabilities different than their weights due to the way it samples many guards and then chooses primary guards from that sample. We are suggesting a straightforward fix to the problem, which is, roughly speaking, to choose primary guards in the order in which they were sampled. In more detail, Prop 271 chooses guards via a multi-step process: 1. It chooses 20 distinct guards (and sometimes more) by sampling without replacement with probability proportional to consensus weight. 2. It produces two subsets of the sample: (1) "filtered" guards, which are guards that satisfy various torrc constraints and path bias, and (2) "confirmed" guards, which are guards through which a circuit has been constructed. 3. The "primary" guards (i.e. the actual guards used for circuits) are chosen from the confirmed and/or filtered subsets. I'm ignoring the additional "usable" subsets for clarity. This description is based on Section 4.6 of the specification (https://gitweb.torproject.org/torspec.git/tree/guard-spec.txt). 1.1 Picturing the problem when Tor starts the first time The primary guards are selected *uniformly at random* from the filtered guards when no confirmed guards exist. No confirmed guards appear to exist until some primary guards have been selected, and so when Tor is started the first time the primary guards always come only from the filtered set. The uniformly-random selection causes a bias in primary-guard selection away from consensus weights and towards a more uniform selection of guards. As just an example of the problem, if there were only 20 guards in the network, the sampled set would be all guards and primary guard selection would be entirely uniformly random, ignoring weights entirely. This bias is worse the larger the sampled set is relative to the entire set of guards, and it has a significant effect on Tor simulations in Shadow, which are typically on smaller networks. 2. Solution Design We propose a solution that fits well within the existing guard-selection algorithm. Our solution is to select primary guards in the order they were sampled. This ordering should be applied after the filtering and/or confirmed guard sets are constructed as normal. That is, primary guards should be selected from the filtered guards (if no guards are both confirmed and filtered) or from the set of confirmed and filtered guards (if such guards exist) in the order they were initially sampled. This solution guarantees that each primary guard is selected (without replacement) from all guards with a probability that is proportional to its consensus weight. 2.1 Performance implications This proposal is a straightforward fix to the unbalanced network that may arise from the uniform selection of sampled relays. It solves the performance correctness in Shadow for which simulations live on a small timeframe. However, it does not solve all the load-balancing problems of Proposal 271. One other load-balancing issue comes when we choose our guards on a date but then make decisions about them on a different date. Building a sampled list of relays at day 0 that we intend to use in a long time for most of them is taking the risk to slowly make the network unbalanced. 2.2 Security implications This proposal solves the following problems: Prop271 reduces Tor's security by increasing the number of clients that an adversary running small relays can observe. In addition, an adversary has to wait less time than it should after it starts a malicious guard to be chosen by a client. This weakness occurs because the malicious guard only needs to enter the sampled list to have a chance to be chosen as primary, rather than having to wait until all previously-sampled guards have already expired. 2.3 Implementation notes The code used for ordering the confirmed list by confirmed idx should be removed, and a sampled order should be applied throughout the various lists. The next sampled idx should be recalculed from the state file, and the sampled_idx values should be recalculated to be a dense array when we save the state. 3. Going Further -- Let's not choose our History (future work) A deeper refactoring of Prop 271 would try to solve the load balancing problem of choosing guards on a date but then making decisions about them on a different date. One suggestion is to remove the sampled list, which we can picture as a "forward history" and to have instead a real history of previously sampled guards. When moving to the next guard, we could consider *current* weights and make the decision. The history should resist attacks that try to force clients onto compromised guards, using relays that are part of the history if they're still available (in sampled order), and by tracking its size. This should maintain the initial goals of Prop 271. ```