Right now, if I've understood correctly, a client wanting to use Tor Browser's default bridges tries the first bridge of whichever bridge type they've selected, then the second, then third, etc. This is suboptimal because it leads to:
The first default bridge gets hammered with many clients.
The other bridges possibly aren't getting enough clients.
The clients will only move to using a different default bridge if the ones previously tried are already overloaded, which means that a client waits longer to bootstrap Tor.
The clients who do end up all sharing the first default bridge are probably having a bad time because they're all sharing the bandwidth and CPU capacities of one over-stressed bridge.
Can we just pick a random number, mod the total number of default bridges for that type, and use that bridge? Is there anything smarter we could do? Would we need to store state somewhere on which ones were previously tried?
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related.
Learn more.
Over the longer term, should we patch tor to pick a random bridge from its list as well, or do we want to preserve the in-order behaviour?
Our load balancing when we have multiple bridges on the tor daemon side is subopotimal/non-existent, and that's where I'd rather see this addressed. What I view as the ideal behavior would be to pick at random, and persist the chosen bridge to minimize churn.
Would we need to store state somewhere on which ones were previously tried?
Yes, if we're solving this from the tor-browser side, then Tor Browser should persist the first working bridge it encounters.
I cannot comment on whether this is a good idea and whether persistent state is needed, but the Tor Launcher changes look OK. Just a couple of minor comments that can be addressed later if there is not time right now:
Since the rearrangeBridges() function is only used inside tl-util.jsm, we should move it to the TLUtilInternal object (and rename it to _rearrangeBridges).
I would have used Math.floor() instead of parseInt() but either one works.
From a style perspective, I do not really like how everything is embedded inside the final for loop expression. It seems like excessive use of the comma operator and I find it harder to read than if something was in the loop body.
Just so it is clear: this patch will cause the default set of bridges to be used in a different order each time Tor Browser is restarted or reconfigured.
Ok, I'll take the patch as is as we are running out of time and it is improving the situation I think. That said I am a fan of the persisting option + bringing the available bridge bandwidth into the equation. We know the operators and could ask them + hardcode the bandwidth using that value for distributing users even more fairly. These (and other) enhancements should be done in a follow-up ticket though.
To add to the complexity of this situation, I wonder what happens if we have for instance two bridges listed as the "first" bridge. Is there going to be an accidental load balancing in practice? or would it break things?
Also, we have only 3 bridges on port 443 and only one on 80. how are we making it easier for censored people who only have access through this ports to pick the right one?
To add to the complexity of this situation, I wonder what happens if we have for instance two bridges listed as the "first" bridge. Is there going to be an accidental load balancing in practice? or would it break things?
I'm not sure what you mean here, surely there can only be one "first" bridge each time Tor Browser launches. (See below.)
Also, we have only 3 bridges on port 443 and only one on 80. how are we making it easier for censored people who only have access through this ports to pick the right one?
As far as I understand it, this patch automatically reorders the default bridges used by Tor Browser each time it restarts. Then Tor Browser tries each bridge in turn to see if it works.
I'm not sure what you mean here, surely there can only be one "first" bridge each time Tor Browser launches.
If you take a look at bridge_prefs.js file, the first obfs4 bridge starts with:
{{{
pref("extensions.torlauncher.default_bridge.obfs4.1", "obfs4...
}}}
and the second one with
{{{
pref("extensions.torlauncher.default_bridge.obfs4.2", "obfs4...
}}}
What happens if they all are obfs4.1? Does Tor Browser try to connect to all of them at once?
If they are all pref("extensions.torlauncher.default_bridge.obfs4.1", "obfs4... then the pref is overwritten each time, and you'd only end up with one bridge, because FF prefs are key-values which expect keys to not collide.
Ok, I'll take the patch as is as we are running out of time and it is improving the situation I think. That said I am a fan of the persisting option + bringing the available bridge bandwidth into the equation. We know the operators and could ask them + hardcode the bandwidth using that value for distributing users even more fairly. These (and other) enhancements should be done in a follow-up ticket though.
Should we close this ticket and make new tickets for persisting the ordering and another for hardcoding the bandwidth? Is there any revision of my patch that still needs to be done?
Ok, I'll take the patch as is as we are running out of time and it is improving the situation I think. That said I am a fan of the persisting option + bringing the available bridge bandwidth into the equation. We know the operators and could ask them + hardcode the bandwidth using that value for distributing users even more fairly. These (and other) enhancements should be done in a follow-up ticket though.
Should we close this ticket and make new tickets for persisting the ordering and another for hardcoding the bandwidth? Is there any revision of my patch that still needs to be done?
See: comment:6. I think at least item 1) and 3) are worth it. And, yes, for persisting the ordering and bandwidth hardcoding we should make separate tickets.
Ok, this ticket came a long way since I last noticed it.
I agree with what Yawning said way up at the top -- this is best fixed inside Tor.
Tor already has the mechanism for figuring out which bridges work, and also the mechanism for keeping state about which one it picked to be its "first" bridge (they go into the state file and are treated just like guards).
So all Tor needs to do is shuffle its bridge list every time it reads it from torrc, and I think everything else we need will follow.
(Except the bandwidth weighting stuff -- either Tor chooses from all of them equally because it doesn't have any descriptors at the time it chooses which one will go into the state file first, or it does have the descriptors so it weights by the self-advertised bandwidths in the descriptors. I'd have to check, but my guess would be the former. Still, I think that is better solved inside Tor, where Tor Browser's job would be to add a weight to the bridge line.)
(Except the bandwidth weighting stuff -- either Tor chooses from all of them equally because it doesn't have any descriptors at the time it chooses which one will go into the state file first, or it does have the descriptors so it weights by the self-advertised bandwidths in the descriptors. I'd have to check, but my guess would be the former. Still, I think that is better solved inside Tor, where Tor Browser's job would be to add a weight to the bridge line.)
So you mean we would add a parameter to bridge lines that specifies weight? Or another optional line underneath it like
Changing the bridge lines once we're taking PTs into account starts to get super ugly… I think if we're going this route we'd need to add something like the BridgeWeight lines.
I am triaging old tickets.
Tor Launcher still randomly reorders the bridges each time it starts up. But maybe it shouldn't because tor is doing something smart now? Nick?
Trac: Cc: isis, gk, yawning, dcf, mcs, brade to isis, gk, yawning, dcf, mcs, brade, nickm Status: needs_revision to needs_information