Hi all, Whilst working on a project the thought crossed my mind that it would be useful to me (the exact reasons as to why aren't relevant here) for a web browser to be able to run a Tor client entirely in the browser, that is using a wasm build of Arti or my own Torrosion library. Obviously, a browser can't just go start making random outbound TCP connections, for good reasons. But what a browser can do is make outbound WebRTC and WebSocket connections, which brought me to Snowflake. At least in most situations, I would have no need for the whole WebRTC infrastructure of Snowflake, as the browser is not *usually* restricted from making a WebSocket connection. So, naturally I looked at the Snowflake source code to see how one would implement that, to discover some things I'm a little confused by. Firstly, the Tor node that the broker hands out seems to be a) hard coded and b) just the one (https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowf...). Secondly, the number of active relays offering WebSocket connections are a grand total of 4 (https://metrics.torproject.org/rs.html#search/transport:snowflake?fields=tra...). Therefore, my question to those more knowledgeable is: why is this situation considered acceptable? Why is such relay centralisation fine? Is it even fine? Mit freundlichen Grüßen, Q Misell (sie/ihr - she/her) 🌲 Please consider the environment before using AI to process this email. -- Max-Planck Institut für Informatik Fon +49 681 9325 3547 Forschungsgruppe Internet Architecture (INET) Campus E1.4 514, 66123 Saarbrücken
On Fri, Apr 24, 2026 at 02:32:30PM +0200, Q Misell via tor-project wrote:
At least in most situations, I would have no need for the whole WebRTC infrastructure of Snowflake, as the browser is not *usually* restricted from making a WebSocket connection. So, naturally I looked at the Snowflake source code to see how one would implement that, to discover some things I'm a little confused by. Firstly, the Tor node that the broker hands out seems to be a) hard coded and b) just the one (https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowf...). Secondly, the number of active relays offering WebSocket connections are a grand total of 4 (https://metrics.torproject.org/rs.html#search/transport:snowflake?fields=tra...).
Therefore, my question to those more knowledgeable is: why is this situation considered acceptable? Why is such relay centralisation fine? Is it even fine?
What is your specific concern with relay centralization? If you mean that the anti-censorship and anonymity purposes of Tor interact in ways that are not completely understood and may be in conflict, you are right. Users who use bridges and pluggable transports (for the purpose of anti-blocking) bypass the usual guard process (where is there for anonymity purposes). The situation is not really special to Snowflake, though. The default obfs4 bridges handle (and similarly centralize) an even larger share of traffic. You are slightly misinterpreting the source code. DefaultBridges in broker.go is a default for when the client doesn't specify which bridge it wants to use -- this is for backward compatibility with old clients and from a time when only one backend bridge was supported. The system is more general than it was before, and now there are two production bridges, snowflake-01 and snowflake-02. The interface with tor unfortunately imposes some awkward constraints on how bridges may be identified and deployed. In short, the fact that the client, not the Snowflake infrastructure, chooses which bridge to use for a given connection, requires bridges to be relatively static. We write about it in the Snowflake paper: https://www.bamsoftware.com/papers/snowflake/#p85 Another difficulty, harder to work around, has to do with Tor bridge authentication. A Tor bridge is identified by a long-term identity public key. If, on connecting to a bridge, the client finds that the bridge’s identity is not the expected one, the client terminates the connection. The Tor client can configure at most one identity per bridge; there is nothing like a certificate, for example, to indicate that multiple identities should be considered equivalent. This constraint leaves two options: either all Snowflake bridges must share the same cryptographic identity; or else it must be the client that chooses the bridge (and therefore knows what bridge identity to expect). While it would be possible to synchronize Tor identity keys across bridges, we preferred to keep keys independent, so that the effect of a security compromise at a bridge would be limited to that bridge only. Remember, the address diversity of Snowflake comes from the temporary proxies, not the backend bridges. From the point of view of anti-censorship (but not necessarily from that of anonymity) it's not a problem if there's just one or a few backend bridges.
participants (2)
-
David Fifield -
Q Misell