/ doc / dev / notes / vanguards.md
vanguards.md
  1  # Building vanguards in Arti
  2  
  3  Here's a summary of the vanguards design.
  4  For canonical information, see the
  5  [specification](https://spec.torproject.org/vanguards-spec/index.html)
  6  
  7  
  8  ## Summary of what we're building.
  9  
 10  The Vanguards design is a change to circuit path construction rules.
 11  
 12  This change applies to HS circuits only.
 13  (That is, circuits that are built for hsservice or hsclient.
 14  This includes circuits to connect to introduction points,
 15  rendezvous points, and hsdirs.)
 16  
 17  We call "circuit stem" the portion of a hidden service circuit
 18  that is built differently when vanguards are in use.
 19  
 20  The vanguard design will apply to the "stem" circuits
 21  that we build in HsCircPool.  These circuits correspond to
 22  everything in an HS circuit _before_ we add an introduction point,
 23  rendezvous point, or hsdir.  For client rendezvous connections,
 24  we use the circuits stems unmodified, and use the
 25  final hop as our rendezvous point.
 26  
 27  Here's our schema:
 28  ```
 29       Client hsdir:  GUARDED -> HsDir
 30       Client intro:  GUARDED -> Ipt
 31       Client rend:   GUARDED
 32       Service hsdir: NAIVE   -> HsDir      (*)
 33       Service intro: NAIVE   -> Ipt
 34       Service rend:  GUARDED -> Rpt
 35  ```
 36  
 37  Note that in some of these cases (marked above with `GUARDED`),
 38  we are building a circuit to a final hop
 39  that an adversary can easily control.
 40  Right now, we don't distinguish these cases,
 41  but with vanguards we will.
 42  
 43  > Note: the client rendezvous case is an exception to this rule:
 44  > the rendezvous point is selected by the client, so it cannot easily be
 45  > controlled by an attacker.
 46  >
 47  > This type of circuit would more accurately be described as a NAIVE circuit
 48  > that gets extended by an extra hop if Full-Vanguards are in use
 49  > (this is necessary to avoid using the L3 guard as a rendezvous point).
 50  > However, for the sake of simplicity, we define these circuits in terms of
 51  > GUARDED.
 52  >
 53  > Note: in the client rendezvous case, the last node from the GUARDED
 54  > circuit stem is the rendezvous point.
 55  
 56  > (I've marked "service hsdir" with a *,
 57  > since maybe we want to call that one "guarded" as well.)
 58  
 59  Currently, circuit stems are built by taking a guard node,
 60  then two arbitrarily chosen middle nodes:
 61  ```
 62     NAIVE   = G -> M -> M
 63     GUARDED = G -> M -> M
 64  ```
 65  
 66  There two variants of vanguards: "lite" and "full".
 67  Both of then introduce pools of additional guards,
 68  called "vanguards".
 69  The "lite" variant adds a single "L2" pool.
 70  The "full" variant adds an "L2" pool and an "L3" pool.
 71  
 72  With "lite", we build circuit stems by taking a guard node,
 73  then a vanguard from the "L2" pool, then an arbitrary middle node:
 74  ```
 75     NAIVE   = G -> L2 -> M
 76     GUARDED = G -> L2 -> M
 77  ```
 78  
 79  With "full", we build circuit stems by taking a guard node,
 80  a vanguard from the L2 pool,
 81  and a vanguard from the L3 pool.
 82  For "guarded" circuits, we also add a middle node:
 83  ```
 84     NAIVE   = G -> L2 -> L3
 85     GUARDED = G -> L2 -> L3 -> M
 86  ```
 87  
 88  ### Pool management
 89  
 90  Here's how we maintain L2 and L3 guards.
 91  
 92  In both cases, vanguards are added to each pool
 93  up to a target `NUM_GUARDS` number taken from a consensus parameter.
 94  This number depends on the variant and the pool in question.
 95  
 96  To be added as a vanguard, a relay must be flagged Stable and Fast.
 97  
 98  The vanguards in single a pool must be distinct from one another.
 99  There is no inter-pool restriction.
100  
101  Every vanguard gets an "expiration time" when it's added to the pool;
102  when this time expires, we remove the vanguard.
103  We additionally remove a vanguard if it is every unlisted,
104  or if it ever loses the Stable or Fast flag.
105  
106  To pick the expiration time when adding a vanguard,
107  we choose from a random distribution.
108  This distribution depends on the variant and the pool in question.
109  
110  In vanguards-full, these pools are persistent,
111  and must be stored to disk.
112  
113  In vanguards-lite, these pools are not persistent.
114  
115  ### Loosened path restirctions
116  
117  When building a circuit stem,
118  we no longer apply certain restrictions to the circuits we build.
119  In particular:
120  
121   - We no longer apply family or same-subnet restrictions at all.
122   - We do not exclude the guard from appearing as
123     either of the last two hops of the circuit.
124  
125  ### Which variant to apply
126  
127  By default, "vanguards-lite" applies to every circuit stem.
128  
129  We will implement a global option that applies "vanguards-full"
130  to every circuit stem.
131  
132  For now, we will share a single L2 pool,
133  no matter which variant is in use:
134  vanguards will not be discarded on a switch
135  from one variant to another.
136  
137  > In the future, we might want to apply "full" or "lite"
138  > to specific services,
139  > either when providing those services or connecting to them.
140  >
141  > To do so, our main open design question to answer
142  > would be whether they share an L2 pool.
143  
144  
145  -----
146  
147  
148  ## Implementing vanguards in arti
149  
150  Pool maintenance might belong logically in tor-guardmgr,
151  or might belong in a new tor-vanguardmgr crate.
152  It shouldn't share an implementation with the main guard pool though,
153  since the criteria for keeping and using
154  guards and vanguards are completely different.
155  
156  New vanguard code will be:
157   * pool maintenance
158   * pool persistence
159  
160  We can have a single VanguardPool implementation
161  shared by both variants, and both pools.
162  
163  Code to modify will be concentrated in `tor_circmgr`:
164   * `HsCircPool::take_or_launch_stub_circuit`.
165   * `HsCircPool::get_or_launch_client_rend`.
166   * `HsCircPool::get_or_launch_specific`.
167   * `hspool::circuit_compatible_with_target`
168   * `CircMgr::launch_hs_unmanaged`
169  
170   * `TargetCircUsage::build_path`.
171   * Anything that touches `SupportedCircUsage::HsOnly`.
172  
173  We will also need a new path-selection implementation.
174  This will either be a new implementation
175  similar to `ExitPathBuilder`,
176  or an additional set of options to a possibly renamed
177  `ExitPathBuilder`.
178  It will probably share some code with `ExitPathBuilder`.
179  
180  We'll need `CircMgr` to have access to the vanguard pools,
181  either by owning a `VanguardMgr` directly,
182  or by owning it through `GuardMgr`.
183  
184  The `VanguardMgr` will need to know which pools
185  will be required.
186  This will depend on whether "full" might be wanted.
187  
188  So that we can later support fine-grained decisions
189  about whether to use "lite" or "full",
190  we should have it be a parameter passed to HsCircPool,
191  telling it whether a "lite" or "full" circuit is needed.
192  
193  ## Estimated steps:
194  
195   * [ ] Implement vanguard pools and a vanguard manager to maintain them.
196   * [ ] Give CircMgr an Arc<VanguardMgr> whenever `onion-service-client`
197         or `onion-service-service` is enabled.
198   * [ ] Implement a global "full-vanguards" configuration option;
199         have it get fed to the vanguardmgr, to tor-hsclient, and to tor-hsservice.
200   * [ ] Give HsCircPool additional arguments to declare whether its
201         circuits are Naive or Guarded
202         (probably not so named in the code!)
203         and whether they are "lite" or "full".
204   * [ ] Implement path selection for (Naive, Guarded) x (lite, full)
205         circuits in CircMgr::launch_hs_unmanaged.
206