On Tue, Jan 04, 2022 at 11:57:36PM -0500, Roger Dingledine wrote:
Hm. It looks promising! But we might still have a Tor-side problem remaining. I think it boils down to how long the KCP sessions last.
The details on how exactly these bridge instances will diverge over time:
The keys directory will start out the same, but after four weeks (DEFAULT_ONION_KEY_LIFETIME_DAYS, used to be one week but in Tor 0.3.1.1-alpha, proposal 274, we bumped it up to four weeks) each bridge will rotate its onion key (the one clients use for circuit-level crypto). That is, each instance will generate its own fresh onion key.
The two bridge instances actually haven't diverged completely at that point, since Tor remembers the previous onion key (i.e. the onion key from the previous period) and is willing to receive create cells that use it for one further week (DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS). So it is after 5 weeks that the original (shared) onion key will no longer work.
Where this matters is (after this 5 weeks have passed) if the client connects to the bridge, fetches and caches the bridge descriptor of instance A, and then later it connects to the bridge again and gets passed to instance B. In this case, the create cell that the client generates will use the onion key for instance A, and instance B won't know how to decrypt it so it will send a destroy cell back.
I've done an experiment with a second snowflake bridge that has the same identity keys but different onion keys. A client can bootstrap with either one starting from a clean state, but it fails if you bootstrap with one and then try to bootstrap with the other using the same DataDirectory. The error you get is ```plain onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 ```
The first bridge is the existing "prod" snowflake bridge with nickname: * flakey
The other "staging" bridge is the load-balanced configuration with four instances. All four instances currently have the same onion keys; which however are different from the "prod"'s onion keys. (The onion keys actually come from a backup I made.) * flakey1 * flakey2 * flakey3 * flakey4
Bootstrapping "prod" with a fresh DataDirectory "datadir.prod" works. Here is torrc.prod:
```plain UseBridges 1 SocksPort auto DataDirectory datadir.prod ClientTransportPlugin snowflake exec ./client -keep-local-addresses -log snowflake.log Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net/ max=1 ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 ```
Notice `new bridge descriptor 'flakey' (fresh)`:
```plain snowflake/client$ tor -f torrc.prod [notice] Tor 0.3.5.16 running on Linux with Libevent 2.1.8-stable, OpenSSL 1.1.1d, Zlib 1.2.11, Liblzma 5.2.4, and Libzstd 1.3.8. [notice] Bootstrapped 0%: Starting [notice] Starting with guard context "bridges" [notice] Delaying directory fetches: No running bridges [notice] Bootstrapped 5%: Connecting to directory server [notice] Bootstrapped 10%: Finishing handshake with directory server [notice] Bootstrapped 15%: Establishing an encrypted directory connection [notice] Bootstrapped 20%: Asking for networkstatus consensus [notice] new bridge descriptor 'flakey' (fresh): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [notice] Bootstrapped 25%: Loading networkstatus consensus [notice] I learned some more directory information, but not enough to build a circuit: We have no usable consensus. [notice] Bootstrapped 40%: Loading authority key certs [notice] The current consensus has no exit nodes. Tor can only build internal paths, such as paths to onion services. [notice] Bootstrapped 45%: Asking for relay descriptors for internal paths [notice] I learned some more directory information, but not enough to build a circuit: We need more microdescriptors: we have 0/6673, and can only build 0% of likely paths. (We have 100% of guards bw, 0% of midpoint bw, and 0% of end bw (no exits in consensus, using mid) = 0% of path bw.) [notice] Bootstrapped 50%: Loading relay descriptors for internal paths [notice] The current consensus contains exit nodes. Tor can build exit and internal paths. [notice] Bootstrapped 57%: Loading relay descriptors [notice] Bootstrapped 64%: Loading relay descriptors [notice] Bootstrapped 73%: Loading relay descriptors [notice] Bootstrapped 78%: Loading relay descriptors [notice] Bootstrapped 80%: Connecting to the Tor network [notice] Bootstrapped 85%: Finishing handshake with first hop [notice] Bootstrapped 90%: Establishing a Tor circuit [notice] Bootstrapped 100%: Done ```
Bootstrapping "staging" with a fresh DataDirectory "datadir.staging" also works. Here is torrc.staging:
```plain UseBridges 1 SocksPort auto DataDirectory datadir.staging ClientTransportPlugin snowflake exec ./client -keep-local-addresses -log snowflake.log Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=http://127.0.0.1:8000/ max=1 ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 ```
Notice `new bridge descriptor 'flakey4' (fresh)`:
```plain snowflake/broker$ ./broker -disable-tls -addr 127.0.0.1:8000 snowflake/proxy$ ./proxy -capacity 10 -broker http://127.0.0.1:8000/ -keep-local-addresses -relay wss://snowflake-staging.bamsoftware.com/ snowflake/client$ tor -f torrc.staging [notice] Tor 0.3.5.16 running on Linux with Libevent 2.1.8-stable, OpenSSL 1.1.1d, Zlib 1.2.11, Liblzma 5.2.4, and Libzstd 1.3.8. [notice] Bootstrapped 0%: Starting [notice] Starting with guard context "bridges" [notice] Delaying directory fetches: No running bridges [notice] Bootstrapped 5%: Connecting to directory server [notice] Bootstrapped 10%: Finishing handshake with directory server [notice] Bootstrapped 15%: Establishing an encrypted directory connection [notice] Bootstrapped 20%: Asking for networkstatus consensus [notice] new bridge descriptor 'flakey4' (fresh): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey4 at 192.0.2.3 [notice] Bootstrapped 25%: Loading networkstatus consensus [notice] I learned some more directory information, but not enough to build a circuit: We have no usable consensus. [notice] Bootstrapped 40%: Loading authority key certs [notice] The current consensus has no exit nodes. Tor can only build internal paths, such as paths to onion services. [notice] Bootstrapped 45%: Asking for relay descriptors for internal paths [notice] I learned some more directory information, but not enough to build a circuit: We need more microdescriptors: we have 0/6673, and can only build 0% of likely paths. (We have 100% of guards bw, 0% of midpoint bw, and 0% of end bw (no exits in consensus, using mid) = 0% of path bw.) [notice] Bootstrapped 50%: Loading relay descriptors for internal paths [notice] The current consensus contains exit nodes. Tor can build exit and internal paths. [notice] Bootstrapped 57%: Loading relay descriptors [notice] Bootstrapped 63%: Loading relay descriptors [notice] Bootstrapped 72%: Loading relay descriptors [notice] Bootstrapped 77%: Loading relay descriptors [notice] Bootstrapped 80%: Connecting to the Tor network [notice] Bootstrapped 85%: Finishing handshake with first hop [notice] Bootstrapped 90%: Establishing a Tor circuit [notice] Bootstrapped 100%: Done ```
But now, if we try running torrc.staging but give it the DataDirectory "datadir.prod", it fails at 90%. Notice `new bridge descriptor 'flakey' (cached)`: if the descriptor had not been cached it would have been flakey[1234] instead.
```plain $ tor -f torrc.staging DataDirectory datadir.prod Log "notice stderr" Log "info file info.log" [notice] Tor 0.3.5.16 running on Linux with Libevent 2.1.8-stable, OpenSSL 1.1.1d, Zlib 1.2.11, Liblzma 5.2.4, and Libzstd 1.3.8. [notice] Bootstrapped 0%: Starting [notice] Starting with guard context "bridges" [notice] new bridge descriptor 'flakey' (cached): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [notice] Delaying directory fetches: Pluggable transport proxies still configuring [notice] Bootstrapped 5%: Connecting to directory server [notice] Bootstrapped 10%: Finishing handshake with directory server [notice] Bootstrapped 80%: Connecting to the Tor network [notice] Bootstrapped 90%: Establishing a Tor circuit [notice] Delaying directory fetches: No running bridges ```
Here is an excerpt from the info-level log that shows the error. The important part seems to be `onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4`.
```plain [notice] new bridge descriptor 'flakey' (cached): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [notice] Delaying directory fetches: Pluggable transport proxies still configuring [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] onion_pick_cpath_exit(): Using requested exit node '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] circuit_handle_first_hop(): Next router is [scrubbed]: Not connected. Connecting. [notice] Bootstrapped 5%: Connecting to directory server [info] connection_or_set_canonical(): Channel 0 chose an idle timeout of 247. [info] connection_or_set_identity_digest(): Set identity digest for 0x55c3f9356770 ([scrubbed]): 2B280B23E1107BB62ABFC40DDCC8824814F80A72 1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko. [info] connection_or_set_identity_digest(): (Previously: 0000000000000000000000000000000000000000 <unset>) [info] connection_or_set_canonical(): Channel 1 chose an idle timeout of 232. [info] circuit_predict_and_launch_new(): Have 0 clean circs (0 internal), need another exit circ. [info] choose_good_exit_server_general(): Found 1336 servers that might support 0/0 pending connections. [info] choose_good_exit_server_general(): Chose exit server '$0F1C8168DFD0AADBE61BD71194D37C867FED5A21~FreeExit at 81.17.18.60' [info] extend_info_from_node(): Including Ed25519 ID for $0F1C8168DFD0AADBE61BD71194D37C867FED5A21~FreeExit at 81.17.18.60 [info] select_primary_guard_for_circuit(): Selected primary guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) for circuit. [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] extend_info_from_node(): Including Ed25519 ID for $7158D1E0D9F90F7999ACB3B073DA762C9B2C3275~maltimore at 207.180.224.17 [info] circuit_handle_first_hop(): Next router is [scrubbed]: Connection in progress; waiting. [info] connection_edge_process_inbuf(): data from edge while in 'waiting for circuit' state. Leaving it on buffer. [info] connection_edge_process_inbuf(): data from edge while in 'waiting for circuit' state. Leaving it on buffer. [notice] Bootstrapped 10%: Finishing handshake with directory server [notice] Bootstrapped 80%: Connecting to the Tor network [info] parse_socks_client(): SOCKS 5 client: need authentication. [info] parse_socks_client(): SOCKS 5 client: authentication successful. [info] connection_read_proxy_handshake(): Proxy Client: connection to 192.0.2.3:1 successful [info] circuit_predict_and_launch_new(): Have 1 clean circs (0 internal), need another exit circ. [info] choose_good_exit_server_general(): Found 1336 servers that might support 0/0 pending connections. [info] choose_good_exit_server_general(): Chose exit server '$D8A1F5A8EA1AF53E3414B9C48FE6B10C31ACC9B2~privexse1exit at 185.130.44.108' [info] extend_info_from_node(): Including Ed25519 ID for $D8A1F5A8EA1AF53E3414B9C48FE6B10C31ACC9B2~privexse1exit at 185.130.44.108 [info] select_primary_guard_for_circuit(): Selected primary guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) for circuit. [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] extend_info_from_node(): Including Ed25519 ID for $2F9AFDE43DC8E3F05803304C01BD3DBF329169AC~dutreuil at 213.152.168.27 [info] circuit_handle_first_hop(): Next router is [scrubbed]: Connection in progress; waiting. [info] circuit_predict_and_launch_new(): Have 2 clean circs (0 uptime-internal, 0 internal), need another hidden service circ. [info] extend_info_from_node(): Including Ed25519 ID for $8967A8912E61070FCFA9B8EC9869E5AC8F94949A~4Freunde at 145.239.154.56 [info] select_primary_guard_for_circuit(): Selected primary guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) for circuit. [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] extend_info_from_node(): Including Ed25519 ID for $9367EB01DF75DE6265A0971249204029D6A55877~oddling at 5.182.210.231 [info] circuit_handle_first_hop(): Next router is [scrubbed]: Connection in progress; waiting. [info] circuit_predict_and_launch_new(): Have 3 clean circs (1 uptime-internal, 1 internal), need another hidden service circ. [info] extend_info_from_node(): Including Ed25519 ID for $AF85E6556FD5692BC554A93BAC9FACBFC2D79EFD~whoUSicebeer09b at 192.187.103.74 [info] select_primary_guard_for_circuit(): Selected primary guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) for circuit. [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] extend_info_from_node(): Including Ed25519 ID for $9515B435D8D063E537AB137FCF5A97B1ACE3CA2A~corvuscorone at 135.181.178.197 [info] circuit_handle_first_hop(): Next router is [scrubbed]: Connection in progress; waiting. [info] circuit_predict_and_launch_new(): Have 4 clean circs (2 uptime-internal, 2 internal), need another hidden service circ. [info] extend_info_from_node(): Including Ed25519 ID for $68A9F0DFFC7C8F57B3DEA3801D6CF001652A809F~vpskilobug at 213.164.206.145 [info] select_primary_guard_for_circuit(): Selected primary guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) for circuit. [info] extend_info_from_node(): Including Ed25519 ID for $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3 [info] extend_info_from_node(): Including Ed25519 ID for $2C13A54E3E8A6AFB18E0DE5890E5B08AAF5B0F36~history at 138.201.123.109 [info] circuit_handle_first_hop(): Next router is [scrubbed]: Connection in progress; waiting. [info] channel_tls_process_versions_cell(): Negotiated version 5 with [scrubbed]:1; Waiting for CERTS cell [info] connection_or_client_learned_peer_id(): learned peer id for 0x55c3f9356770 ([scrubbed]): 2B280B23E1107BB62ABFC40DDCC8824814F80A72, 1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko [info] channel_tls_process_certs_cell(): Got some good certificates from [scrubbed]:1: Authenticated it with RSA and Ed25519 [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [notice] Bootstrapped 90%: Establishing a Tor circuit [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] circuit_send_first_onion_skin(): First hop: finished sending CREATE cell to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey at 192.0.2.3' [info] channel_tls_process_netinfo_cell(): Got good NETINFO cell from [scrubbed]:1; OR connection is now open, using protocol version 5. Its ID digest is 2B280B23E1107BB62ABFC40DDCC8824814F80A72. Our address is apparently [scrubbed]. [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 3457244666 (id: 1) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 4237434553 (id: 2) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 3082862549 (id: 6) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 2596950236 (id: 4) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] circuit_build_failed(): Our circuit 3457244666 (id: 1) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] connection_ap_fail_onehop(): Closing one-hop stream to '$2B280B23E1107BB62ABFC40DDCC8824814F80A72/192.0.2.3' because the OR conn just failed. [info] circuit_free_(): Circuit 0 (id: 1) has been freed. [info] circuit_build_failed(): Our circuit 4237434553 (id: 2) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] circuit_free_(): Circuit 0 (id: 2) has been freed. [info] circuit_build_failed(): Our circuit 3082862549 (id: 6) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] circuit_free_(): Circuit 0 (id: 6) has been freed. [info] circuit_build_failed(): Our circuit 2596950236 (id: 4) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] circuit_free_(): Circuit 0 (id: 4) has been freed. [info] connection_free_minimal(): Freeing linked Socks connection [waiting for circuit] with 121 bytes on inbuf, 0 on outbuf. [info] connection_dir_client_reached_eof(): 'fetch' response not all here, but we're at eof. Closing. [info] entry_guards_note_guard_failure(): Recorded failure for primary confirmed guard $2B280B23E1107BB62ABFC40DDCC8824814F80A72 ($2B280B23E1107BB62ABFC40DDCC8824814F80A72) [info] connection_dir_client_request_failed(): Giving up on serverdesc/extrainfo fetch from directory server at '192.0.2.3'; retrying [info] connection_free_minimal(): Freeing linked Directory connection [client reading] with 0 bytes on inbuf, 0 on outbuf. [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 2912328161 (id: 5) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] onion_skin_ntor_client_handshake(): Invalid result from curve25519 handshake: 4 [info] circuit_mark_for_close_(): Circuit 2793970028 (id: 3) marked for close at ../src/core/or/command.c:443 (orig reason: 1, new reason: 0) [info] circuit_build_failed(): Our circuit 2912328161 (id: 5) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] circuit_free_(): Circuit 0 (id: 5) has been freed. [info] circuit_build_failed(): Our circuit 2793970028 (id: 3) failed to get a response from the first hop (192.0.2.3:1). I'm going to try to rotate to a better connection. [info] circuit_free_(): Circuit 0 (id: 3) has been freed. [info] connection_ap_make_link(): Making internal direct tunnel to [scrubbed]:1 ... [info] connection_ap_make_link(): ... application connection created and linked. [info] should_delay_dir_fetches(): Delaying dir fetches (no running bridges known) [notice] Delaying directory fetches: No running bridges ```
As you suggested, CREATE_FAST in place of CREATE works. I hacked `should_use_create_fast_for_circuit` to always return true:
```diff diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 2bcc642a97..4005ba56ce 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -801,6 +801,7 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info);
+ return true; return ! circuit_has_usable_onion_key(circ); } ```
And then the mixed configuration with the "staging" bridge and the "prod" DataDirectory bootstraps. Notice `new bridge descriptor 'flakey' (cached)` followed later by `new bridge descriptor 'flakey1' (fresh)`.
```plain $ ~/tor/src/app/tor -f torrc.staging DataDirectory datadir.prod [notice] Tor 0.4.6.8 (git-d5efc2c98619568e) running on Linux with Libevent 2.1.8-stable, OpenSSL 1.1.1d, Zlib 1.2.11, Liblzma 5.2.4, Libzstd N/A and Glibc 2.28 as libc. [notice] Bootstrapped 0% (starting): Starting [notice] Starting with guard context "bridges" [notice] new bridge descriptor 'flakey' (cached): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey [1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko] at 192.0.2.3 [notice] Delaying directory fetches: Pluggable transport proxies still configuring [notice] Bootstrapped 1% (conn_pt): Connecting to pluggable transport [notice] Bootstrapped 2% (conn_done_pt): Connected to pluggable transport [notice] Bootstrapped 10% (conn_done): Connected to a relay [notice] Bootstrapped 14% (handshake): Handshaking with a relay [notice] Bootstrapped 15% (handshake_done): Handshake with a relay done [notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits [notice] Bootstrapped 95% (circuit_create): Establishing a Tor circuit [notice] new bridge descriptor 'flakey1' (fresh): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey1 [1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko] at 192.0.2.3 [notice] Bootstrapped 100% (done): Done ```
If this is an issue, we can definitely work around it, by e.g. disabling the onion key rotation on the bridges, or setting up a periodic rsync+hup between the bridges, or teaching clients to use createfast cells in this situation (this type of circuit crypto doesn't use the onion key at all, and just relies on TLS for security -- which can only be done for the first hop of the circuit but that's the one we're talking about here).
What do you recommend trying? I guess the quickest way to get more capacity on the snowflake bridge is to disable onion key rotation by patching the tor source code, though I wouldn't want to maintain that long-term.
Gary, I was wondering how you are dealing with the changing onion key issue, and I suppose it is [this](https://forum.torproject.net/t/tor-relays-how-to-reduce-tor-cpu-load-on-a-si...):
use Source IP Address Sticky Sessions (Pinning)
The same client source address gets pinned to the same tor instance and therefore the same onion key. If I understand correctly, there's a potential failure if a client changes its IP address and later gets mapped to a different instance. Is that right?