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.