From 7fa81734d774c22889851c30b4ad4457b52970c9 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Tue, 6 Oct 2026 09:59:53 +0800 Subject: [PATCH] Add opt-in printable TCP salt experiment for ss-local Add `ss-local --printable-salt` / `"printable_salt": true`, disabled by default. For each outgoing TCP salt it picks a prefix length uniformly from 6-12 bytes and samples those bytes as printable ASCII (0x20-0x7e) immediately before key derivation. The salt stays 32 bytes with no framing or markers, so the wire format is unchanged and any stock server interoperates. Only chacha20-ietf-poly1305 and aes-256-gcm are accepted; other ciphers fail at startup. UDP, server responses, and AEAD-2022 are untouched. Crypto unit tests cover length distribution, empty first writes, exact framing overhead, salt-tail preservation, byte-at-a-time decryption, tampering and replay rejection. CLI tests check local-only exposure and cipher rejection via flag, config key and bad config type. interop.py gains --printable-salt and --server-bin for independent stock servers. docs/printable-salt.md records the design, entropy bound, fingerprint caveats and route-experiment procedure; docs/encoding-experiments.md and tests/experiments/ hold the Base85/lowpop85/TLS outer-transport prototypes. docs/measurements/printable-salt-2026-09-23/ archives the sanitized results of the aborted field trials. Co-Authored-By: Claude --- README.md | 4 + completions/bash/ss-local | 2 +- completions/zsh/_ss-local | 1 + doc/shadowsocks-c.md | 1 + docs/encoding-experiments.md | 110 ++++ .../printable-salt-2026-09-23/README.md | 166 ++++++ .../encoding-aborted.json | 273 ++++++++++ .../encoding-events.jsonl | 486 ++++++++++++++++++ .../local-packets.json | 30 ++ .../local-transports.json | 92 ++++ .../salt-aborted.json | 41 ++ .../salt-events.jsonl | 428 +++++++++++++++ .../printable-salt-2026-09-23/ssh-path.json | 7 + .../synthetic-encodings.json | 102 ++++ docs/printable-salt.md | 149 ++++++ src/aead.c | 9 + src/common.h | 1 + src/crypto.h | 1 + src/jconf.c | 5 + src/jconf.h | 1 + src/local.c | 17 + src/utils.c | 13 + tests/CMakeLists.txt | 16 + tests/check_printable_pcap.py | 82 +++ tests/experiments/analyze.py | 103 ++++ tests/experiments/benchmark.py | 80 +++ tests/experiments/local_interop.py | 71 +++ tests/experiments/route_screen.py | 166 ++++++ tests/experiments/route_server.py | 150 ++++++ tests/experiments/test_supervisor.py | 72 +++ tests/experiments/test_transport.py | 130 +++++ tests/experiments/transport.py | 138 +++++ tests/interop.py | 10 + tests/printable_salt_experiment.py | 272 ++++++++++ tests/test_cli.py | 36 ++ tests/test_crypto.c | 125 +++++ 36 files changed, 3389 insertions(+), 1 deletion(-) create mode 100644 docs/encoding-experiments.md create mode 100644 docs/measurements/printable-salt-2026-09-23/README.md create mode 100644 docs/measurements/printable-salt-2026-09-23/encoding-aborted.json create mode 100644 docs/measurements/printable-salt-2026-09-23/encoding-events.jsonl create mode 100644 docs/measurements/printable-salt-2026-09-23/local-packets.json create mode 100644 docs/measurements/printable-salt-2026-09-23/local-transports.json create mode 100644 docs/measurements/printable-salt-2026-09-23/salt-aborted.json create mode 100644 docs/measurements/printable-salt-2026-09-23/salt-events.jsonl create mode 100644 docs/measurements/printable-salt-2026-09-23/ssh-path.json create mode 100644 docs/measurements/printable-salt-2026-09-23/synthetic-encodings.json create mode 100644 docs/printable-salt.md create mode 100644 tests/check_printable_pcap.py create mode 100644 tests/experiments/analyze.py create mode 100644 tests/experiments/benchmark.py create mode 100644 tests/experiments/local_interop.py create mode 100644 tests/experiments/route_screen.py create mode 100644 tests/experiments/route_server.py create mode 100644 tests/experiments/test_supervisor.py create mode 100644 tests/experiments/test_transport.py create mode 100644 tests/experiments/transport.py create mode 100644 tests/printable_salt_experiment.py diff --git a/README.md b/README.md index ea6d0f617..15f48faf7 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Current version: 3.3.6 | [Changelog](debian/changelog) [CLI reference and configuration guide](https://shadowsocks.github.io/shadowsocks-c/) are generated from the source with Doxygen and published after updates to `master`. +An opt-in [printable TCP salt experiment](docs/printable-salt.md) is available +through `ss-local --printable-salt` or `"printable_salt": true` in the config +file. It is disabled by default. + Use `--help` for grouped CLI options and `--version` for version information. See [CLI conventions](https://shadowsocks.github.io/shadowsocks-c/index.html#cli_conventions) for the long flags, short aliases, and configuration precedence. diff --git a/completions/bash/ss-local b/completions/bash/ss-local index 2d1f80851..2a3175a6a 100644 --- a/completions/bash/ss-local +++ b/completions/bash/ss-local @@ -1,7 +1,7 @@ _ss_local() { local cur prev opts ciphers - opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --fast-open --acl --mtu --mptcp --no-delay --key --plugin --plugin-opts --help' + opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --fast-open --acl --mtu --mptcp --no-delay --printable-salt --key --plugin --plugin-opts --help' ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' cur=${COMP_WORDS[COMP_CWORD]} prev="${COMP_WORDS[COMP_CWORD-1]}" diff --git a/completions/zsh/_ss-local b/completions/zsh/_ss-local index 4b8265479..4f7933507 100644 --- a/completions/zsh/_ss-local +++ b/completions/zsh/_ss-local @@ -24,6 +24,7 @@ _arguments "-h::" \ "--acl:acl file:_files" \ "--mtu::" \ "--mptcp::" \ + "--printable-salt[Experimental printable TCP salt]" \ "--no-delay::" \ "--key:key in base64:" \ "--plugin:plugin name:" \ diff --git a/doc/shadowsocks-c.md b/doc/shadowsocks-c.md index 7f0480ab8..e1ce79c18 100644 --- a/doc/shadowsocks-c.md +++ b/doc/shadowsocks-c.md @@ -79,6 +79,7 @@ The config file equivalent of command line options is listed as examples below. - `--fast-open`: `"fast_open": true` - `--reuse-port`: `"reuse_port": true` - `--no-delay`: `"no_delay": true` +- `--printable-salt`: `"printable_salt": true` (ss-local only) - `--plugin "obfs-server"`: `"plugin": "obfs-server"` - `--plugin-opts "obfs=http"`: `"plugin_opts": "obfs=http"` - `-6`: `"ipv6_first": true` diff --git a/docs/encoding-experiments.md b/docs/encoding-experiments.md new file mode 100644 index 000000000..8416dac63 --- /dev/null +++ b/docs/encoding-experiments.md @@ -0,0 +1,110 @@ +# Outer-transport experiments + +These Python prototypes extend the printable-salt investigation. They wrap the +TCP ciphertext of unchanged Shadowsocks peers. They are research fixtures, not +production plugins. Both endpoints need a matching relay; UDP is not wrapped. +The original `--printable-salt` flag remains a separate, disabled-by-default, +wire-compatible client option. + +Base64 has been dropped from the active experiments. Earlier measurements are +retained unchanged in the historical report linked below. + +## Candidates and tradeoffs + +| Mode | Transformation | Bulk expansion | Main observable property | +|---|---|---:|---| +| raw | Transparent relay control | 0% | Ordinary Shadowsocks ciphertext | +| printable salt | Random 6–12-byte printable prefix, tested separately | 0% | First six bytes always printable | +| Base85 | Base85 records with newline separators | About 25.01% | Wider printable alphabet | +| lowpop85 | Base85 symbols mapped to 85 low-popcount byte values | About 25.01% | Restricted alphabet, mostly zero bits | +| TLS | Verified TLS 1.3 with two-byte inner record lengths | Variable; handshake plus TLS records | Actual OpenSSL TLS handshake and record behavior | + +The bulk expansion figures include delimiters/padding for 16 KiB input records. +Small writes have proportionally more framing overhead. EOF is represented by +an empty encoded record, allowing TCP half-close through the relays. Base85 records preserve every ciphertext byte. The low-popcount mapping is public and +reversible; its symbols have at most three set bits, with `0xff` as a separator. +It is a simple baseline, **not** the keyed bit-shuffling construction from the +[modified-Shadowsocks implementation](https://gfw.report/blog/modified_shadowsocks/en/). + +Base85 and lowpop85 have about `log2(85) = 6.41` bits per symbol. None destroys information or +makes the underlying encryption weaker merely by encoding it. Conversely, +lower byte entropy does not establish lower detectability: these encodings have +recognizable alphabets. A capable classifier can decode them or learn their +patterns. The low-popcount variant is particularly easy to distinguish from +uniform bytes. + +TLS uses a fresh, short-lived experiment certificate, verified by the client, +with hostname `experiment.invalid`. It is genuine TLS, not a fabricated TLS +prefix. It does not imitate a browser or carry HTTP, and the self-signed +certificate and OpenSSL handshake can themselves be fingerprinted. No existing +server certificate, key, or service is reused or modified. + +## Local screening + +```sh +python3 tests/experiments/test_transport.py +python3 tests/experiments/benchmark.py \ + --output build-artifacts/printable-salt/encoding-screen.json +python3 tests/experiments/local_interop.py --bin build-printable-stock/bin \ + --output build-artifacts/printable-salt/encoding-local-interop.json +``` + +The tests cover fragmented and coalesced records, malformed/truncated input, +record size limits, half-close (including TLS), certificate verification, +concurrency, and empty readiness connections. +Local interoperability exercises all four relay modes around an independently +built stock server/client pair, with both supported ciphers, concurrent payloads +from one byte to one MiB, and a verified ten MiB bidirectional transfer. + +The synthetic benchmark uses uniform random bytes as a ciphertext model. It +measures byte histograms, popcount, expansion, and encode/decode speed, and checks +2,000 independent 100-byte samples per mode against the four published +[historical byte-statistic exemptions](https://gfw.report/publications/usenixsecurity23/en/). +Those classifier results are simulated, not observed firewall decisions. +These timings measure the Python prototypes, not the inherent speed of each format. + +## Route screening + +After verifying SSH trust, route, unused ports, available disk, and server health: + +```sh +python3 tests/experiments/route_screen.py \ + --host root@SERVER --host-key-alias VERIFIED_KNOWN_HOST \ + --address SERVER_IPV4 --stock-bin build-printable-stock/bin/ss-local \ + --ports 32220 32221 32222 32223 \ + --output build-artifacts/printable-salt/encoding-route-v2 +python3 tests/experiments/analyze.py \ + build-artifacts/printable-salt/encoding-route-v2 +``` + +The protocol is saved before outcomes are observed. Four two-minute phases rotate +each mode over every port. Each mode attempts a verified one KiB transfer every +five seconds, plus one ten MiB transfer per phase: 100 transfers per mode, 400 in +total. Raw mode traverses the same relay architecture, providing a control for +Python relay overhead. The backend is one unchanged stock server using +`chacha20-ietf-poly1305`; all phases use fresh test credentials from the same run. + +Server-local clients verify each entire relay/crypto path at phase start and +every 30 seconds. Management or local-control failure aborts the run. Ports and +listeners are isolated; no firewall rule or production service is changed. +A remote watchdog bounds the supervisor lifetime; a 60-second control-command +timeout also stops it if a broken SSH path never delivers EOF. Cleanup stops owned processes, +removes private configs and certificate keys, and retrieves captures. + +Captures include full experiment packets and the SSH control flow. They contain +address metadata and are kept in a private output directory. The analyzer reports +first-arriving payloads separately from payloads at the TCP stream start: packet +reordering can make these differ. It also separates other source addresses from +the test client and looks for exact replayed opening payloads. A matching replay +from another address is evidence of replay traffic, not sufficient attribution +to a particular actor. A lack of observed probes is not proof of resistance. + +Performance figures are end-to-end echo timings with concurrent traffic sharing +the same route and a small server. TLS includes a fresh connection handshake. +Small-transfer completion time is the latency metric; local SOCKS handshake time +is not remote RTT. Bulk throughput counts payload bytes once, though the echo +moves them in both directions. An eight-minute all-success result establishes only +short-run compatibility and measured prototype performance. It cannot establish +long-term censorship resistance or a speed advantage from a small sample. + +Recorded results: [2026-09-23 measurements and limitations](measurements/printable-salt-2026-09-23/README.md). diff --git a/docs/measurements/printable-salt-2026-09-23/README.md b/docs/measurements/printable-salt-2026-09-23/README.md new file mode 100644 index 000000000..32fdbd501 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/README.md @@ -0,0 +1,166 @@ +# Printable salt and outer-transport results — 2026-09-23 + +## Conclusion + +The opt-in printable-salt implementation is interoperable and adds no framing +bytes. Base64, Base85, low-popcount encoding, and verified TLS prototypes also +transferred data successfully around unchanged Shadowsocks peers. + +**Neither planned field trial completed.** Both stopped on loss of the direct +SSH management path. All recorded transfer outcomes succeeded, including the +raw controls, so there is **no demonstrated availability or censorship-resistance +advantage**. Some in-flight outcomes could be omitted by the logger at abort; +these are not counted as successes. The logger was subsequently fixed. + +Three unsolicited exact replays were captured against raw Shadowsocks openings, +including raw traffic on two different ports in the rotated experiment. None +were observed against printable-salt or outer-transport openings in these +captures. This is a limited observation of replay traffic, not attribution to +the GFW or proof of protection. The original acceptance criterion—modified +traffic repeatedly succeeding while stock fails, including after crossover—was +not met. + +## Environment and reproducibility + +- Direct Mac `en0` route; the proxy-free address lookup reported China Mobile, + Anhui. The Singapore server saw the same mainland source address. +- All measurement child processes had proxy environment variables removed. +- Base source: `d52ddf2bcee97d799c74f54bf63533351a05324c`. + An independent `git archive` checkout was built before edits. +- Local stock and modified C builds: Release, system dependencies, macOS arm64. + Remote peer: unchanged shadowsocks-rust 1.24.0, Linux x86-64. +- Remote stock binary SHA-256: + `bbb26b41ad6ef40fd9a9ab399009ddff14ec22b1a04b77288671d9fa50dd9b06`. +- Fresh credentials, isolated temporary listeners, loopback-only echo origins, + no firewall changes, and no production service changes. +- [Salt reproduction](../../printable-salt.md) and + [outer-transport reproduction](../../encoding-experiments.md). + +## Local validation + +Regular and sanitizer CMake/CTest builds passed **25/25** tests each. The suite +includes first-write/empty-write behavior, exact framing overhead, salt-tail +preservation, byte-fragmented decryption, tampering, replay rejection, CLI cipher +validation, enabled interoperability, and experiment supervisor cleanup. + +Independent stock-C and Rust interoperability passed for both supported ciphers. +Default TCP/UDP interoperability passed for all six AEAD/AEAD-2022 methods. +The repository's 10 MiB stress tests passed for all three standard AEAD ciphers. +Python lint, CLI documentation checks, and documentation unit tests passed. + +Loopback packet captures checked 32 enabled and 32 disabled connections per +cipher. All 64 enabled first transmitted payloads began with six printable +bytes; none of the 64 disabled samples happened to do so. All payloads followed +the observed SYN sequence correctly. See [packet results](local-packets.json). + +All five outer-relay modes passed local testing with both ciphers: four +concurrent transfers per case and a verified 10 MiB echo transfer. Codec tests +cover fragmentation, coalescing, malformed records, size limits, concurrency, +empty readiness connections, half-close, and TLS certificate verification. +Supervisor tests verify real backend/listener cleanup after EOF, silence, and +termination. See [local results](local-transports.json). + +## Salt field trial: aborted before crossover + +Planned: two 30-minute phases, swapping stock/modified clients between ports +32181 and 32182; a one KiB transfer every five seconds plus ten 10 MiB transfers +per mode per phase. + +Observed: approximately 16 minutes, from 10:20:21 UTC until cleanup at 10:36:30. +Each mode recorded **197 successful outcomes**: 191 small and six large transfers. +All 32 completed health checks passed, including verified server-local transfers. +The next control exchange failed when SSH stopped responding. No port crossover +was reached. Median small-transfer completion times were 173.4 ms stock and +172.6 ms modified. Large-transfer medians were 23.89 and 27.25 Mbps respectively; +these six samples under shared load do not establish a speed difference. + +Both endpoint captures confirm 197 legitimate transmitted openings per mode. +All 197 modified openings had the required first-packet prefix. A different +source replayed a stock opening's entire 79 bytes **3.109 seconds** later. The +server sent no application bytes in that replay connection; this alone does not +prove replay rejection, because the opening contained only a destination header. +Replay rejection is separately tested in the crypto unit tests. + +[Sanitized summary](salt-aborted.json) · [recorded events](salt-events.jsonl). + +## Outer-transport field trial: interrupted fourth rotation + +Planned: five two-minute phases across five ports; every mode visits every port, +with 24 small transfers and one 10 MiB transfer per phase. The raw control uses +the same Python relay architecture. Server-local controls exercise each complete +relay/crypto path at every phase start and every 30 seconds. + +Observed: three complete phases and part of the fourth, starting 10:43 UTC and +aborting at 10:50:53 UTC. All 19 completed health checkpoints passed. Values below +are **recorded outcomes**, not a claim that every scheduled or in-flight attempt +completed. Four large transfers per mode were recorded. Timings include shared +route/server load and concurrent bulk traffic; tail latency is substantial. + +| Mode | Recorded success | Small median ms | Small p95 ms | Large median Mbps | +|---|---:|---:|---:|---:| +| raw | 92/92 | 182.7 | 2646.3 | 12.73 | +| base64 | 93/93 | 181.2 | 2382.5 | 5.42 | +| base85 | 92/92 | 186.9 | 2382.6 | 4.11 | +| lowpop85 | 92/92 | 197.5 | 2383.1 | 3.79 | +| tls | 92/92 | 280.9 | 3078.0 | 4.80 | + +The full endpoint captures match these recorded connection counts. All encoded +client openings meet a published historical byte-statistic exemption; only one +of 92 raw openings does. This is evaluation of captured bytes against historical +rules, not an observation that a firewall applied those rules. + +At the server, three TLS connections had later TCP data arrive before the stream +start. Their first-arriving payload did not match the historical exemptions; +the eventual stream-start payload did. This is why packet arrival and application +write boundaries must not be conflated. + +Two other source addresses replayed exact 79-byte raw openings, one on port +32220 in phase one after **3.930 seconds**, and one on port 32223 in phase four +after **0.936 seconds**. No equivalent replay was observed for the other modes. +The low counts and incomplete rotation prevent a strong comparative conclusion. + +[Sanitized summary](encoding-aborted.json) · [recorded events](encoding-events.jsonl). +Short calibration runs and the superseded run containing empty readiness +connections remain in the private artifact directory and are excluded above. + +## SSH failure and cleanup + +The client capture's last SSH request found in the server capture was sent at +10:50:38.585912 UTC. Starting at **10:50:43.584421 UTC**, ten captured client SSH +payload packets, including retransmissions, were absent from the server capture. +Both captures reported zero kernel capture drops. This supports forward-path +loss for the management connection; it does not identify the cause or actor. +See [packet comparison](ssh-path.json). + +Fresh direct SSH connections also temporarily timed out. Recovery through the +existing local HTTP proxy reached the healthy server from a different egress IP. +That alternate route was used only for recovery and cleanup, not measurements. +Direct SSH subsequently recovered. The retrieved server capture's SHA-256 +matched the remote file: +`4c86092fe8b7ca6dcdd77c5e4017c937d28a8d2ded9fba07d75d5786c6db2477`. + +All experimental processes/listeners, temporary remote files and certificate +keys were removed. Original TCP/UDP listeners remained unchanged. No temporary +firewall rules were created. Raw captures, build hashes, test logs, recovery +verification, and reproduction helpers are retained locally under +`build-artifacts/printable-salt/` (not committed). + +The failed control connection exposed two harness limitations, now fixed: +remote cleanup now has a 60-second control-message deadline in addition to its +lifetime watchdog, and transfer workers persist outcomes directly rather than +waiting for the control loop to collect them. These fixes were validated locally; +no further live load was started after the second management failure. + +## Encoding tradeoff + +The synthetic benchmark found bulk expansion of 33.36% for Base64 and 25.01% for +Base85/lowpop85. Their empirical symbol entropies were about 6.00 and 6.41 bits per +byte; lowpop85 averaged 2.44 one-bits per byte. Every transformed 100-byte sample +passed at least one historical exemption, versus five of 2,000 raw samples. +See [synthetic measurements](synthetic-encodings.json). + +These encodings retain all ciphertext information while introducing recognizable +alphabets. Printable salt is cheapest but imposes a fixed printable property on +the first six bytes. TLS uses a real protocol but adds connection setup and has +its own handshake/certificate fingerprint. The measurements do not justify +selecting any candidate as a proven censorship-resistant transport. diff --git a/docs/measurements/printable-salt-2026-09-23/encoding-aborted.json b/docs/measurements/printable-salt-2026-09-23/encoding-aborted.json new file mode 100644 index 000000000..5a1d939d6 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/encoding-aborted.json @@ -0,0 +1,273 @@ +{ + "protocol": { + "modes": [ + "raw", + "base64", + "base85", + "lowpop85", + "tls" + ], + "ports": [ + 32220, + 32221, + 32222, + 32223, + 32224 + ], + "phases": 5, + "phase_seconds": 120, + "small_interval_seconds": 5, + "small_bytes": 1024, + "large_per_phase": 1, + "large_bytes": 10485760, + "rotation": "mode i uses port (i + phase_index) modulo 5", + "acceptance": "screening only; all-success is compatibility, not censorship resistance" + }, + "complete": false, + "aborts": [ + { + "event": "aborted", + "reason": "AssertionError: remote supervisor stopped", + "utc": "2026-09-23T10:50:53Z" + } + ], + "completed_phases": 3, + "outcome_logging_limit": "Runs before the durable-outcome fix can omit in-flight outcomes at abort.", + "health_checks": 19, + "health_failures": 0, + "modes": { + "raw": { + "recorded_outcomes": 92, + "success": 92, + "errors": [], + "small_median_ms": 182.72097949989075, + "small_p95_ms": 2646.290791999945, + "large_median_mbps": 12.72926290474592 + }, + "base64": { + "recorded_outcomes": 93, + "success": 93, + "errors": [], + "small_median_ms": 181.17083300012382, + "small_p95_ms": 2382.4694589998217, + "large_median_mbps": 5.420371172252078 + }, + "base85": { + "recorded_outcomes": 92, + "success": 92, + "errors": [], + "small_median_ms": 186.88187499992637, + "small_p95_ms": 2382.5787079999827, + "large_median_mbps": 4.107073353264521 + }, + "lowpop85": { + "recorded_outcomes": 92, + "success": 92, + "errors": [], + "small_median_ms": 197.4834169998303, + "small_p95_ms": 2383.1408749997536, + "large_median_mbps": 3.789692522854444 + }, + "tls": { + "recorded_outcomes": 92, + "success": 92, + "errors": [], + "small_median_ms": 280.86322900003324, + "small_p95_ms": 3078.0023329998585, + "large_median_mbps": 4.804416561409541 + } + }, + "client.pcap/unsolicited": { + "connections": 0, + "exact_replays": [] + }, + "client.pcap": { + "raw": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 1, + "popcount": 0, + "prefix": 0, + "half": 1, + "run": 0, + "tls_header": 0 + }, + "base64": { + "connections": 93, + "sequence_ok": 93, + "complete_first_payload": 93, + "historical_exemption": 93, + "popcount": 0, + "prefix": 93, + "half": 93, + "run": 93, + "tls_header": 0 + }, + "base85": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 92, + "popcount": 0, + "prefix": 92, + "half": 92, + "run": 92, + "tls_header": 0 + }, + "tls": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 92, + "popcount": 0, + "prefix": 0, + "half": 0, + "run": 0, + "tls_header": 92 + }, + "lowpop85": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 92, + "popcount": 92, + "prefix": 0, + "half": 1, + "run": 1, + "tls_header": 0 + } + }, + "client.pcap/stream_start": { + "raw": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 1 + }, + "base64": { + "connections": 93, + "complete_first_payload": 93, + "historical_exemption": 93 + }, + "base85": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + }, + "tls": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + }, + "lowpop85": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + } + }, + "remote-server.pcap/unsolicited": { + "connections": 2, + "exact_replays": [ + { + "mode": "raw", + "phase": 1, + "port": 32220, + "delay_seconds": 3.929837942123413, + "payload_bytes": 79, + "payload_sha256": "82a31e39eaef22fd6ed9c588772aa89ac6792cb16513e6390b229b00be33c812" + }, + { + "mode": "raw", + "phase": 4, + "port": 32223, + "delay_seconds": 0.9364199638366699, + "payload_bytes": 79, + "payload_sha256": "652fa6336adc1bdd23cd51836d7b6816952be871c83a65a042734b747d056611" + } + ] + }, + "remote-server.pcap": { + "raw": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 1, + "popcount": 0, + "prefix": 0, + "half": 1, + "run": 0, + "tls_header": 0 + }, + "base85": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 92, + "popcount": 0, + "prefix": 92, + "half": 92, + "run": 92, + "tls_header": 0 + }, + "base64": { + "connections": 93, + "sequence_ok": 93, + "complete_first_payload": 93, + "historical_exemption": 93, + "popcount": 0, + "prefix": 93, + "half": 93, + "run": 93, + "tls_header": 0 + }, + "tls": { + "connections": 92, + "sequence_ok": 89, + "complete_first_payload": 92, + "historical_exemption": 89, + "popcount": 0, + "prefix": 0, + "half": 0, + "run": 0, + "tls_header": 89 + }, + "lowpop85": { + "connections": 92, + "sequence_ok": 92, + "complete_first_payload": 92, + "historical_exemption": 92, + "popcount": 92, + "prefix": 0, + "half": 1, + "run": 1, + "tls_header": 0 + } + }, + "remote-server.pcap/stream_start": { + "raw": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 1 + }, + "base85": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + }, + "base64": { + "connections": 93, + "complete_first_payload": 93, + "historical_exemption": 93 + }, + "tls": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + }, + "lowpop85": { + "connections": 92, + "complete_first_payload": 92, + "historical_exemption": 92 + } + } +} diff --git a/docs/measurements/printable-salt-2026-09-23/encoding-events.jsonl b/docs/measurements/printable-salt-2026-09-23/encoding-events.jsonl new file mode 100644 index 000000000..1cc6ea27c --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/encoding-events.jsonl @@ -0,0 +1,486 @@ +{"event": "start", "ready": true, "origin": 41389, "utc": "2026-09-23T10:43:14Z"} +{"event": "phase_start", "phase": 1, "port_modes": ["raw", "base64", "base85", "lowpop85", "tls"], "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:43:15Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:43:15Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.2419579998095287, "seconds": 0.17446949999975914, "mbps": 0.046953765557941694, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "raw", "port": 32220, "size": 10485760, "success": true, "socks_handshake_ms": 0.8227920002354949, "seconds": 4.060716500000126, "mbps": 20.657950388803897, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8983330003502488, "seconds": 0.17621412500011502, "mbps": 0.04648889525737312, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.4394170002560713, "seconds": 0.17870345800020004, "mbps": 0.045841306551498456, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9070830001292052, "seconds": 0.48815045799983636, "mbps": 0.01678171118299503, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0128330000043206, "seconds": 0.7059324580000066, "mbps": 0.011604509620097285, "utc": "2026-09-23T10:43:20Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "base64", "port": 32221, "size": 10485760, "success": true, "socks_handshake_ms": 1.1926250003853056, "seconds": 5.492637750000085, "mbps": 15.272458119051942, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.8407499999520951, "seconds": 0.42844462499988367, "mbps": 0.019120323892503552, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6841250001343724, "seconds": 0.42579750000004424, "mbps": 0.01923919233907937, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.025916999878973, "seconds": 0.42880925000008574, "mbps": 0.01910406550231452, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9926249999807624, "seconds": 0.42894970799989096, "mbps": 0.019097809946526604, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7258330001604918, "seconds": 0.5787047919998258, "mbps": 0.014155749379041715, "utc": "2026-09-23T10:43:25Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.9065419999387814, "seconds": 0.6608993330000885, "mbps": 0.01239523115088225, "utc": "2026-09-23T10:43:30Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1815420002676547, "seconds": 0.6672900830003528, "mbps": 0.012276519925436491, "utc": "2026-09-23T10:43:30Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.7041250000838772, "seconds": 0.2992224169997826, "mbps": 0.02737762792687405, "utc": "2026-09-23T10:43:30Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.2035830000058922, "seconds": 0.28932733300007385, "mbps": 0.028313951243583022, "utc": "2026-09-23T10:43:30Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6827500001236331, "seconds": 0.9541730830001143, "mbps": 0.008585444450227714, "utc": "2026-09-23T10:43:30Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "base85", "port": 32222, "size": 10485760, "success": true, "socks_handshake_ms": 1.4580830002159928, "seconds": 19.698984999999993, "mbps": 4.258396054416003, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.6290830003526935, "seconds": 2.3645943750002516, "mbps": 0.003464441972208924, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8011660002011922, "seconds": 2.368553457999951, "mbps": 0.003458651090323066, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9347919999527221, "seconds": 2.3684998339999765, "mbps": 0.0034587293958831164, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5503750000789296, "seconds": 2.3704472919998807, "mbps": 0.003455887851903527, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0345830000915157, "seconds": 3.0780023329998585, "mbps": 0.002661466468745648, "utc": "2026-09-23T10:43:35Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "lowpop85", "port": 32223, "size": 10485760, "success": true, "socks_handshake_ms": 0.6903749999764841, "seconds": 20.9540806670002, "mbps": 4.0033290571468045, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "tls", "port": 32224, "size": 10485760, "success": true, "socks_handshake_ms": 1.0671659997569805, "seconds": 20.382740499999727, "mbps": 4.115544717846019, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.7801249998919957, "seconds": 0.4601099589999649, "mbps": 0.01780443965569679, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.7235409998429532, "seconds": 0.4565855000000738, "mbps": 0.017941875070493208, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9570829997755936, "seconds": 0.45592279199991026, "mbps": 0.017967954539113307, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.8267920002253959, "seconds": 0.4544464999999036, "mbps": 0.01802632433081064, "utc": "2026-09-23T10:43:40Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9958750001715089, "seconds": 0.6483252909997645, "mbps": 0.012635632318719732, "utc": "2026-09-23T10:43:40Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.6090409999378608, "seconds": 0.16991479099988283, "mbps": 0.048212400767427305, "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1356250001881563, "seconds": 0.1726579999999558, "mbps": 0.04744639692340985, "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9404999996149854, "seconds": 0.4274662919997354, "mbps": 0.019164084170653323, "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.8843340001476463, "seconds": 0.4888963749999675, "mbps": 0.016756107058475415, "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.1494579998725385, "seconds": 0.7081100420000439, "mbps": 0.011568823366579925, "utc": "2026-09-23T10:43:45Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.825332999942475, "seconds": 0.17394816600017293, "mbps": 0.04709448905596312, "utc": "2026-09-23T10:43:50Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.221541999711917, "seconds": 0.16402108399961435, "mbps": 0.04994479856028302, "utc": "2026-09-23T10:43:50Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.2352080002528965, "seconds": 0.4201240830002462, "mbps": 0.019499001203402092, "utc": "2026-09-23T10:43:50Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5990419997251593, "seconds": 0.45502816699990944, "mbps": 0.018003281102379823, "utc": "2026-09-23T10:43:50Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0086659999615222, "seconds": 0.27190650000011374, "mbps": 0.030128003560034693, "utc": "2026-09-23T10:43:50Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 3.3781659999476688, "seconds": 0.1667170409996288, "mbps": 0.049137148493525865, "utc": "2026-09-23T10:43:55Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 4.112541000267811, "seconds": 0.16866300000037882, "mbps": 0.04857022583483989, "utc": "2026-09-23T10:43:55Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 3.117707999990671, "seconds": 0.1790470410001035, "mbps": 0.04575333920204392, "utc": "2026-09-23T10:43:55Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 3.3133330002783623, "seconds": 0.47593279100010477, "mbps": 0.017212514361083803, "utc": "2026-09-23T10:43:55Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.5604170000406157, "seconds": 0.6678765829997246, "mbps": 0.0122657392226662, "utc": "2026-09-23T10:43:55Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.9367089998922893, "seconds": 0.4796681669999998, "mbps": 0.01707847333550488, "utc": "2026-09-23T10:44:00Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.351541000076395, "seconds": 0.17732887500005745, "mbps": 0.046196650150728956, "utc": "2026-09-23T10:44:00Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.7431660003239813, "seconds": 0.17129670800022723, "mbps": 0.04782345262577453, "utc": "2026-09-23T10:44:00Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.8858329997565306, "seconds": 0.20365979200005313, "mbps": 0.04022394366384241, "utc": "2026-09-23T10:44:00Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7954169996082783, "seconds": 0.27528191700002935, "mbps": 0.029758583815729264, "utc": "2026-09-23T10:44:00Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.6234160002568387, "seconds": 0.17225437500019325, "mbps": 0.047557572920808595, "utc": "2026-09-23T10:44:05Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2854159999733383, "seconds": 0.1708589159998155, "mbps": 0.047945990714402316, "utc": "2026-09-23T10:44:05Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.1767500000132713, "seconds": 0.4845225419999224, "mbps": 0.016907366097326616, "utc": "2026-09-23T10:44:05Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.2460419998205907, "seconds": 0.43003666699996757, "mbps": 0.0190495383966889, "utc": "2026-09-23T10:44:05Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9984579996853427, "seconds": 0.2699701249998725, "mbps": 0.030344098259034658, "utc": "2026-09-23T10:44:05Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.7601250001462176, "seconds": 0.19031812499997613, "mbps": 0.04304371956166039, "utc": "2026-09-23T10:44:10Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.2050420002415194, "seconds": 0.17494000000033338, "mbps": 0.04682748370861089, "utc": "2026-09-23T10:44:10Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.5400830002363364, "seconds": 0.4874410000002172, "mbps": 0.016806136537542697, "utc": "2026-09-23T10:44:10Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5457080003216106, "seconds": 0.17762637500027267, "mbps": 0.04611927704986055, "utc": "2026-09-23T10:44:10Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2152079998486442, "seconds": 0.6340424169998187, "mbps": 0.012920271231636452, "utc": "2026-09-23T10:44:10Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.1150840000482276, "seconds": 0.47792470900003536, "mbps": 0.017140775201056602, "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.436374999684631, "seconds": 0.1774734159998843, "mbps": 0.04615902586788175, "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.3036669997745776, "seconds": 0.17126562499970532, "mbps": 0.047832132104817265, "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.259332999779872, "seconds": 0.1833489579998968, "mbps": 0.04467982850496816, "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2180000003354507, "seconds": 0.27435600000035265, "mbps": 0.0298590152939592, "utc": "2026-09-23T10:44:15Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.2746249999509018, "seconds": 0.1968614580000576, "mbps": 0.041613021071893116, "utc": "2026-09-23T10:44:20Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1937919998672442, "seconds": 0.19589300000006915, "mbps": 0.04181874798995936, "utc": "2026-09-23T10:44:20Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6911249997756386, "seconds": 0.16890762499997436, "mbps": 0.048499882702164834, "utc": "2026-09-23T10:44:20Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.1588749998736603, "seconds": 0.3596611660000235, "mbps": 0.02277699338826996, "utc": "2026-09-23T10:44:20Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0268749997521809, "seconds": 0.7049873339997248, "mbps": 0.011620066921660748, "utc": "2026-09-23T10:44:20Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.2623329998859845, "seconds": 0.16636100000005172, "mbps": 0.04924231039725328, "utc": "2026-09-23T10:44:25Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2810409998564865, "seconds": 0.16897649999964415, "mbps": 0.04848011409880813, "utc": "2026-09-23T10:44:25Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.3943750000180444, "seconds": 0.4800997500001358, "mbps": 0.017063120736883704, "utc": "2026-09-23T10:44:25Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.268500000151107, "seconds": 0.4789945410002474, "mbps": 0.017102491362204833, "utc": "2026-09-23T10:44:25Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.3536250003198802, "seconds": 0.2603060420001384, "mbps": 0.031470648691264896, "utc": "2026-09-23T10:44:25Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.9287090001635079, "seconds": 0.16784520900000643, "mbps": 0.04880687419561488, "utc": "2026-09-23T10:44:30Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.4272090000085882, "seconds": 0.1626080420001017, "mbps": 0.05037881213768552, "utc": "2026-09-23T10:44:30Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.7507499999519496, "seconds": 0.1719244159999107, "mbps": 0.04764884587424892, "utc": "2026-09-23T10:44:30Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.7477909998669929, "seconds": 0.47805216599999767, "mbps": 0.01713620517305645, "utc": "2026-09-23T10:44:30Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8876669999153819, "seconds": 0.25798237499975585, "mbps": 0.03175410723313076, "utc": "2026-09-23T10:44:30Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.768666000065423, "seconds": 0.16606012500005818, "mbps": 0.049331529769697145, "utc": "2026-09-23T10:44:35Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.442791999783367, "seconds": 0.19018770799993945, "mbps": 0.04307323583710577, "utc": "2026-09-23T10:44:35Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.1054579997326073, "seconds": 0.17778016700003718, "mbps": 0.046079380721913074, "utc": "2026-09-23T10:44:35Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.4136249999173742, "seconds": 0.18412733300010586, "mbps": 0.044490950183888725, "utc": "2026-09-23T10:44:35Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2719579999611597, "seconds": 0.7068914159999622, "mbps": 0.011588767121201594, "utc": "2026-09-23T10:44:35Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.983750000159489, "seconds": 0.162863500000185, "mbps": 0.05029979092915659, "utc": "2026-09-23T10:44:40Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.9104169998863654, "seconds": 0.1612722089998897, "mbps": 0.05079610461592674, "utc": "2026-09-23T10:44:40Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9628329999031848, "seconds": 0.17854912499979037, "mbps": 0.045880930528276846, "utc": "2026-09-23T10:44:40Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9905419997267018, "seconds": 0.47057174999963536, "mbps": 0.017408609845377135, "utc": "2026-09-23T10:44:40Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.5949159999545373, "seconds": 0.6163009999995666, "mbps": 0.013292206243387178, "utc": "2026-09-23T10:44:40Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0763750001387962, "seconds": 0.41354112500039264, "mbps": 0.01980939622387549, "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1132500003441237, "seconds": 0.17032045900032244, "mbps": 0.04809756883043916, "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.7192499997472623, "seconds": 0.16969499999959226, "mbps": 0.04827484604743618, "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.852749999921798, "seconds": 0.4744364170001063, "mbps": 0.017266802687278038, "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.514500000008411, "seconds": 0.6210234589998436, "mbps": 0.013191128098756836, "utc": "2026-09-23T10:44:45Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3696670002900646, "seconds": 0.1617425419999563, "mbps": 0.05064839403848502, "utc": "2026-09-23T10:44:50Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.9460420001232706, "seconds": 0.49592087500013804, "mbps": 0.016518764208096143, "utc": "2026-09-23T10:44:50Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.5533749997302948, "seconds": 0.4907671669998308, "mbps": 0.016692233203128733, "utc": "2026-09-23T10:44:50Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.3085420000606973, "seconds": 0.17548733400008132, "mbps": 0.04668143172085687, "utc": "2026-09-23T10:44:50Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2474999998630665, "seconds": 0.6973948750001, "mbps": 0.01174657327385554, "utc": "2026-09-23T10:44:50Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.137459000095987, "seconds": 0.1809635839999828, "mbps": 0.04526877628595584, "utc": "2026-09-23T10:44:55Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.704457999949227, "seconds": 0.47410820799996145, "mbps": 0.017278755907977585, "utc": "2026-09-23T10:44:55Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.66008399992279, "seconds": 0.17801120900003298, "mbps": 0.046019573969628406, "utc": "2026-09-23T10:44:55Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.491583999722934, "seconds": 0.17791958399993746, "mbps": 0.04604327312277708, "utc": "2026-09-23T10:44:55Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.095541000016965, "seconds": 0.2575470829997357, "mbps": 0.031807776289232544, "utc": "2026-09-23T10:44:55Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 3.8880840002093464, "seconds": 0.16964162500016755, "mbps": 0.04829003494862719, "utc": "2026-09-23T10:45:00Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 4.48970899969936, "seconds": 0.17410933399969508, "mbps": 0.04705089504284903, "utc": "2026-09-23T10:45:00Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.393125000049622, "seconds": 0.1810732500002814, "mbps": 0.04524135950499186, "utc": "2026-09-23T10:45:00Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 3.1479579997721885, "seconds": 0.4849527080000371, "mbps": 0.01689236881217575, "utc": "2026-09-23T10:45:00Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 3.9907079999466077, "seconds": 0.2646583330001704, "mbps": 0.030953115691221125, "utc": "2026-09-23T10:45:00Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3923329997851397, "seconds": 0.17329712499986272, "mbps": 0.04727141318707099, "utc": "2026-09-23T10:45:05Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.3803749998260173, "seconds": 0.47212024999998903, "mbps": 0.017351511611713732, "utc": "2026-09-23T10:45:05Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.9337499998073326, "seconds": 0.16984116699995866, "mbps": 0.048233300233988585, "utc": "2026-09-23T10:45:05Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.3802920002490282, "seconds": 0.4716408330000377, "mbps": 0.017369149205958057, "utc": "2026-09-23T10:45:05Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.223208000032173, "seconds": 0.2676235409999208, "mbps": 0.03061016220543328, "utc": "2026-09-23T10:45:05Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.6851670000287413, "seconds": 0.1641349579999769, "mbps": 0.04991014772124993, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.496583999847644, "seconds": 0.16895662499973696, "mbps": 0.048485816996005654, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.5495840000548924, "seconds": 0.4388494169998012, "mbps": 0.018666995289647863, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.8028749998629792, "seconds": 0.17881566699998075, "mbps": 0.04581254057565818, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.5814579999423586, "seconds": 0.7377986249998685, "mbps": 0.011103300714339851, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "raw", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.9300409999232215, "seconds": 0.16521062499987238, "mbps": 0.04958518860397949, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "base64", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1054999999942083, "seconds": 0.1844949579999593, "mbps": 0.04440229743298355, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "base85", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.542208999784634, "seconds": 0.18768833399963114, "mbps": 0.043646825699971845, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "lowpop85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.953375000084634, "seconds": 0.18520204200012813, "mbps": 0.04423277363213053, "utc": "2026-09-23T10:45:10Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "tls", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.6594579999255075, "seconds": 0.6810124579997137, "mbps": 0.012029148518166234, "utc": "2026-09-23T10:45:11Z"} +{"event": "phase_complete", "phase": 1, "utc": "2026-09-23T10:45:15Z"} +{"event": "phase_start", "phase": 2, "port_modes": ["tls", "raw", "base64", "base85", "lowpop85"], "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:45:16Z"} +{"event": "health", "phase": 2, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:45:16Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.7553749999024149, "seconds": 0.18376204199967106, "mbps": 0.04457939142847936, "utc": "2026-09-23T10:45:21Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.2898750001113513, "seconds": 0.520984333999877, "mbps": 0.01572408125423966, "utc": "2026-09-23T10:45:21Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5355840000665921, "seconds": 0.18199770899991563, "mbps": 0.04501155561251487, "utc": "2026-09-23T10:45:21Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.1062919998039433, "seconds": 0.17938937500002794, "mbps": 0.04566602676439853, "utc": "2026-09-23T10:45:21Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.8154579997826659, "seconds": 0.26632358300003034, "mbps": 0.030759574153067275, "utc": "2026-09-23T10:45:21Z"} +{"event": "transfer", "phase": 2, "tick": 1, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.4922919997625286, "seconds": 3.345208624999941, "mbps": 0.0024488756661627175, "utc": "2026-09-23T10:45:26Z"} +{"event": "transfer", "phase": 2, "tick": 1, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.5175000001145236, "seconds": 2.9682693330000802, "mbps": 0.002759857371743354, "utc": "2026-09-23T10:45:26Z"} +{"event": "transfer", "phase": 2, "tick": 1, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.016916000025958, "seconds": 2.9710008750003, "mbps": 0.0027573199553497852, "utc": "2026-09-23T10:45:26Z"} +{"event": "transfer", "phase": 2, "tick": 1, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7771250002406305, "seconds": 2.968766625000171, "mbps": 0.002759395073703218, "utc": "2026-09-23T10:45:26Z"} +{"event": "transfer", "phase": 2, "tick": 1, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.197584000237839, "seconds": 3.673247708999952, "mbps": 0.002230179026567823, "utc": "2026-09-23T10:45:26Z"} +{"event": "transfer", "phase": 2, "tick": 2, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.4082500001677545, "seconds": 3.107177750000119, "mbps": 0.0026364761398023294, "utc": "2026-09-23T10:45:31Z"} +{"event": "transfer", "phase": 2, "tick": 2, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.8987500000330328, "seconds": 3.1080490839999584, "mbps": 0.002635737010130214, "utc": "2026-09-23T10:45:31Z"} +{"event": "transfer", "phase": 2, "tick": 2, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.0754580002867442, "seconds": 3.507621083000231, "mbps": 0.0023354860192005126, "utc": "2026-09-23T10:45:31Z"} +{"event": "transfer", "phase": 2, "tick": 2, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.1063749998356798, "seconds": 3.1052072089996727, "mbps": 0.0026381492276127405, "utc": "2026-09-23T10:45:31Z"} +{"event": "transfer", "phase": 2, "tick": 2, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0677090003810008, "seconds": 4.198138749999998, "mbps": 0.001951340936504303, "utc": "2026-09-23T10:45:31Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "raw", "port": 32221, "size": 10485760, "success": true, "socks_handshake_ms": 1.252249999652122, "seconds": 17.474171874999683, "mbps": 4.800575420687942, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "base64", "port": 32222, "size": 10485760, "success": true, "socks_handshake_ms": 1.7567089998919982, "seconds": 19.204049209000004, "mbps": 4.368145440946209, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "base85", "port": 32223, "size": 10485760, "success": true, "socks_handshake_ms": 1.5305419997275749, "seconds": 18.884270624999772, "mbps": 4.442113845209788, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "lowpop85", "port": 32224, "size": 10485760, "success": true, "socks_handshake_ms": 1.3220830001046124, "seconds": 18.740668707999703, "mbps": 4.476151908293011, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 0, "mode": "tls", "port": 32220, "size": 10485760, "success": true, "socks_handshake_ms": 0.8978330001809809, "seconds": 15.270649166000112, "mbps": 5.493288404973064, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 3, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8634169998913421, "seconds": 2.7757438329999786, "mbps": 0.0029512809873187113, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 3, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.721291999980167, "seconds": 2.7747620420000203, "mbps": 0.002952325235822849, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 3, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.5149160001565178, "seconds": 2.7764861659998132, "mbps": 0.0029504919204414834, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 3, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6838330000391579, "seconds": 2.77683291700032, "mbps": 0.0029501234841487786, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 3, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.4928749999635329, "seconds": 3.414173249999749, "mbps": 0.00239940957887846, "utc": "2026-09-23T10:45:36Z"} +{"event": "transfer", "phase": 2, "tick": 4, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.5206669998187863, "seconds": 0.1680914999997185, "mbps": 0.04873536139551208, "utc": "2026-09-23T10:45:41Z"} +{"event": "transfer", "phase": 2, "tick": 4, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.8443329998044646, "seconds": 0.4543034999996962, "mbps": 0.018031998432777818, "utc": "2026-09-23T10:45:41Z"} +{"event": "transfer", "phase": 2, "tick": 4, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9025829999700363, "seconds": 0.17465887500020472, "mbps": 0.04690285563782773, "utc": "2026-09-23T10:45:41Z"} +{"event": "transfer", "phase": 2, "tick": 4, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.957292000293819, "seconds": 0.1791920000000573, "mbps": 0.04571632662170957, "utc": "2026-09-23T10:45:41Z"} +{"event": "transfer", "phase": 2, "tick": 4, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.9062920003088948, "seconds": 0.2654409170004328, "mbps": 0.030861858422477656, "utc": "2026-09-23T10:45:41Z"} +{"event": "health", "phase": 2, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 5, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2002080002275761, "seconds": 0.17065083299985417, "mbps": 0.048004453631978465, "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 5, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.888209000298957, "seconds": 0.1796179170000869, "mbps": 0.045607922287596935, "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 5, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.105874999666412, "seconds": 0.1805384999997841, "mbps": 0.045375363149742554, "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 5, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.793583999893599, "seconds": 0.16920824999988326, "mbps": 0.0484137150523432, "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 5, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.9232920001522871, "seconds": 0.7179155419999006, "mbps": 0.01141081300062053, "utc": "2026-09-23T10:45:46Z"} +{"event": "transfer", "phase": 2, "tick": 6, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0907920000136073, "seconds": 0.16850808399976813, "mbps": 0.04861487832246239, "utc": "2026-09-23T10:45:51Z"} +{"event": "transfer", "phase": 2, "tick": 6, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.7857919999878504, "seconds": 0.46788870799991855, "mbps": 0.017508437070469812, "utc": "2026-09-23T10:45:51Z"} +{"event": "transfer", "phase": 2, "tick": 6, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5285839999705786, "seconds": 0.1732830420000937, "mbps": 0.04727525501309915, "utc": "2026-09-23T10:45:51Z"} +{"event": "transfer", "phase": 2, "tick": 6, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2294590001147299, "seconds": 0.4805029999997714, "mbps": 0.017048800944018866, "utc": "2026-09-23T10:45:51Z"} +{"event": "transfer", "phase": 2, "tick": 6, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.5732079998779227, "seconds": 0.2489260419997663, "mbps": 0.03290937313825803, "utc": "2026-09-23T10:45:51Z"} +{"event": "transfer", "phase": 2, "tick": 7, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1565410000002885, "seconds": 0.4300135000003138, "mbps": 0.019050564691559736, "utc": "2026-09-23T10:45:56Z"} +{"event": "transfer", "phase": 2, "tick": 7, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.0489579999557463, "seconds": 0.18117083300012382, "mbps": 0.04521699141270936, "utc": "2026-09-23T10:45:56Z"} +{"event": "transfer", "phase": 2, "tick": 7, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9491249998063722, "seconds": 0.47077170900001875, "mbps": 0.017401215585789744, "utc": "2026-09-23T10:45:56Z"} +{"event": "transfer", "phase": 2, "tick": 7, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.5906250000625732, "seconds": 0.17103562500005864, "mbps": 0.04789645432053814, "utc": "2026-09-23T10:45:56Z"} +{"event": "transfer", "phase": 2, "tick": 7, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0467079996487882, "seconds": 0.25211283299995557, "mbps": 0.03249338759364718, "utc": "2026-09-23T10:45:56Z"} +{"event": "transfer", "phase": 2, "tick": 8, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.014417000078538, "seconds": 0.4816533329999402, "mbps": 0.01700808328051374, "utc": "2026-09-23T10:46:01Z"} +{"event": "transfer", "phase": 2, "tick": 8, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.8482500002173765, "seconds": 0.18090491700013445, "mbps": 0.04528345683381238, "utc": "2026-09-23T10:46:01Z"} +{"event": "transfer", "phase": 2, "tick": 8, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5339169999606383, "seconds": 0.1662609580002936, "mbps": 0.04927194031917904, "utc": "2026-09-23T10:46:01Z"} +{"event": "transfer", "phase": 2, "tick": 8, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8677089999764576, "seconds": 0.1741490839999642, "mbps": 0.04704015554857403, "utc": "2026-09-23T10:46:01Z"} +{"event": "transfer", "phase": 2, "tick": 8, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.5153330000430287, "seconds": 0.262780415999714, "mbps": 0.031174317038941423, "utc": "2026-09-23T10:46:01Z"} +{"event": "transfer", "phase": 2, "tick": 9, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.079541000057361, "seconds": 0.1855095830001119, "mbps": 0.04415944377382951, "utc": "2026-09-23T10:46:06Z"} +{"event": "transfer", "phase": 2, "tick": 9, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.0535419998850557, "seconds": 0.4837038330001633, "mbps": 0.016935983221777022, "utc": "2026-09-23T10:46:06Z"} +{"event": "transfer", "phase": 2, "tick": 9, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.0984169998664584, "seconds": 0.18288674999985233, "mbps": 0.04479274742433016, "utc": "2026-09-23T10:46:06Z"} +{"event": "transfer", "phase": 2, "tick": 9, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.9474579999041453, "seconds": 0.41697537499976534, "mbps": 0.019646244097759034, "utc": "2026-09-23T10:46:06Z"} +{"event": "transfer", "phase": 2, "tick": 9, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.6874580001058348, "seconds": 0.2666732080001566, "mbps": 0.030719246456866373, "utc": "2026-09-23T10:46:06Z"} +{"event": "transfer", "phase": 2, "tick": 10, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2080000001333246, "seconds": 0.17650066699980016, "mbps": 0.046413422335731314, "utc": "2026-09-23T10:46:11Z"} +{"event": "transfer", "phase": 2, "tick": 10, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.2063750000379514, "seconds": 0.16882787499980623, "mbps": 0.04852279281492705, "utc": "2026-09-23T10:46:11Z"} +{"event": "transfer", "phase": 2, "tick": 10, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.4140839998617594, "seconds": 0.17504891699991276, "mbps": 0.04679834723001504, "utc": "2026-09-23T10:46:11Z"} +{"event": "transfer", "phase": 2, "tick": 10, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2120410001443815, "seconds": 0.1709552080001231, "mbps": 0.0479189847202204, "utc": "2026-09-23T10:46:11Z"} +{"event": "transfer", "phase": 2, "tick": 10, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.7686250002952875, "seconds": 0.7190897089999453, "mbps": 0.011392180832893305, "utc": "2026-09-23T10:46:11Z"} +{"event": "health", "phase": 2, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 11, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6034580001141876, "seconds": 0.16222379200007708, "mbps": 0.05049814148097406, "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 11, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6899999998495332, "seconds": 0.47079854200001137, "mbps": 0.01740022380952871, "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 11, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.5602920000455924, "seconds": 0.48047408299999006, "mbps": 0.01704982701429115, "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 11, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6875839999338496, "seconds": 0.17328566700007286, "mbps": 0.04727453886879493, "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 11, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.821541000277648, "seconds": 0.2651054580001073, "mbps": 0.030900910384110927, "utc": "2026-09-23T10:46:16Z"} +{"event": "transfer", "phase": 2, "tick": 12, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.4989999999670545, "seconds": 0.17998225000019374, "mbps": 0.04551559945489726, "utc": "2026-09-23T10:46:21Z"} +{"event": "transfer", "phase": 2, "tick": 12, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9276249998038111, "seconds": 0.17457295799977146, "mbps": 0.046925939125180685, "utc": "2026-09-23T10:46:21Z"} +{"event": "transfer", "phase": 2, "tick": 12, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.4805830001023423, "seconds": 0.1756372919999194, "mbps": 0.046641575412149715, "utc": "2026-09-23T10:46:21Z"} +{"event": "transfer", "phase": 2, "tick": 12, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.6633340001135366, "seconds": 0.4806421670000418, "mbps": 0.017043864567960986, "utc": "2026-09-23T10:46:21Z"} +{"event": "transfer", "phase": 2, "tick": 12, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.91683299979195, "seconds": 0.740469624999605, "mbps": 0.011063249218365129, "utc": "2026-09-23T10:46:21Z"} +{"event": "transfer", "phase": 2, "tick": 13, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0011670001404127, "seconds": 0.17524374999993597, "mbps": 0.04674631762903381, "utc": "2026-09-23T10:46:26Z"} +{"event": "transfer", "phase": 2, "tick": 13, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9087499997804116, "seconds": 0.17732216700005665, "mbps": 0.04619839774458308, "utc": "2026-09-23T10:46:26Z"} +{"event": "transfer", "phase": 2, "tick": 13, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.6338750001523294, "seconds": 0.17877450000014505, "mbps": 0.04582308998203521, "utc": "2026-09-23T10:46:26Z"} +{"event": "transfer", "phase": 2, "tick": 13, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.494500000262633, "seconds": 0.17369616700034385, "mbps": 0.04716281390356636, "utc": "2026-09-23T10:46:26Z"} +{"event": "transfer", "phase": 2, "tick": 13, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.822999999854801, "seconds": 0.6636096659999566, "mbps": 0.012344606204094284, "utc": "2026-09-23T10:46:26Z"} +{"event": "transfer", "phase": 2, "tick": 14, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.311874999828433, "seconds": 0.17814929199994367, "mbps": 0.04598390433122007, "utc": "2026-09-23T10:46:31Z"} +{"event": "transfer", "phase": 2, "tick": 14, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.3458749999699648, "seconds": 0.18521624999993946, "mbps": 0.04422938052143199, "utc": "2026-09-23T10:46:31Z"} +{"event": "transfer", "phase": 2, "tick": 14, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.0651250001719745, "seconds": 0.18825029100025858, "mbps": 0.04351653299695961, "utc": "2026-09-23T10:46:31Z"} +{"event": "transfer", "phase": 2, "tick": 14, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2675419998231519, "seconds": 0.17606362499964234, "mbps": 0.04652863417992582, "utc": "2026-09-23T10:46:31Z"} +{"event": "transfer", "phase": 2, "tick": 14, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.1086250001426379, "seconds": 0.2674381669999093, "mbps": 0.030631379551755523, "utc": "2026-09-23T10:46:31Z"} +{"event": "transfer", "phase": 2, "tick": 15, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0966669997287681, "seconds": 0.18019362499990166, "mbps": 0.045462207666916464, "utc": "2026-09-23T10:46:36Z"} +{"event": "transfer", "phase": 2, "tick": 15, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.0543749999669672, "seconds": 0.15506020899965733, "mbps": 0.052831090921708374, "utc": "2026-09-23T10:46:36Z"} +{"event": "transfer", "phase": 2, "tick": 15, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.7700420001128805, "seconds": 0.17394133400011924, "mbps": 0.047096338814984505, "utc": "2026-09-23T10:46:36Z"} +{"event": "transfer", "phase": 2, "tick": 15, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7232919997477438, "seconds": 0.16321404200016332, "mbps": 0.050191759848652005, "utc": "2026-09-23T10:46:36Z"} +{"event": "transfer", "phase": 2, "tick": 15, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.348582999980863, "seconds": 0.253195166000296, "mbps": 0.03235448815792329, "utc": "2026-09-23T10:46:36Z"} +{"event": "transfer", "phase": 2, "tick": 16, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2676659998760442, "seconds": 0.17957875000001877, "mbps": 0.04561786959759517, "utc": "2026-09-23T10:46:41Z"} +{"event": "transfer", "phase": 2, "tick": 16, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.1611250001806184, "seconds": 0.17614941600004386, "mbps": 0.04650597308819895, "utc": "2026-09-23T10:46:41Z"} +{"event": "transfer", "phase": 2, "tick": 16, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9744170001795283, "seconds": 0.17997275000016089, "mbps": 0.04551800203082232, "utc": "2026-09-23T10:46:41Z"} +{"event": "transfer", "phase": 2, "tick": 16, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0055419998025172, "seconds": 0.18493533399987427, "mbps": 0.04429656476574438, "utc": "2026-09-23T10:46:41Z"} +{"event": "transfer", "phase": 2, "tick": 16, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.7840840003154881, "seconds": 0.6272983339999882, "mbps": 0.013059177039038897, "utc": "2026-09-23T10:46:41Z"} +{"event": "health", "phase": 2, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 17, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 3.9784159998816904, "seconds": 0.41463983299991014, "mbps": 0.01975690550695783, "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 17, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 3.0905419998816797, "seconds": 0.17748745800008692, "mbps": 0.046155373975754324, "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 17, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.92875000013737, "seconds": 0.1972064589999718, "mbps": 0.04154022156039611, "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 17, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.9246670001157327, "seconds": 0.4588493749997724, "mbps": 0.017853353292687963, "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 17, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.8433750003387104, "seconds": 0.27430129100002887, "mbps": 0.029864970631870404, "utc": "2026-09-23T10:46:46Z"} +{"event": "transfer", "phase": 2, "tick": 18, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.754207999965729, "seconds": 0.177890208000008, "mbps": 0.04605087650467884, "utc": "2026-09-23T10:46:51Z"} +{"event": "transfer", "phase": 2, "tick": 18, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.5906670000731538, "seconds": 0.18290291700031958, "mbps": 0.04478878814155647, "utc": "2026-09-23T10:46:51Z"} +{"event": "transfer", "phase": 2, "tick": 18, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.7280839997511066, "seconds": 0.48571645899983196, "mbps": 0.01686580688838225, "utc": "2026-09-23T10:46:51Z"} +{"event": "transfer", "phase": 2, "tick": 18, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0897500001192384, "seconds": 0.17549083299991253, "mbps": 0.04668050096955254, "utc": "2026-09-23T10:46:51Z"} +{"event": "transfer", "phase": 2, "tick": 18, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.5402499998344865, "seconds": 0.2542970409999725, "mbps": 0.03221429540739676, "utc": "2026-09-23T10:46:51Z"} +{"event": "transfer", "phase": 2, "tick": 19, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.5864160002602148, "seconds": 0.17699287499999627, "mbps": 0.04628434901687524, "utc": "2026-09-23T10:46:56Z"} +{"event": "transfer", "phase": 2, "tick": 19, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.5460419997689314, "seconds": 0.4688787919999413, "mbps": 0.017471466271822812, "utc": "2026-09-23T10:46:56Z"} +{"event": "transfer", "phase": 2, "tick": 19, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.6949580001673894, "seconds": 0.16525729200020578, "mbps": 0.049571186244476276, "utc": "2026-09-23T10:46:56Z"} +{"event": "transfer", "phase": 2, "tick": 19, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7840419998501602, "seconds": 0.42510683399996196, "mbps": 0.019270450025277018, "utc": "2026-09-23T10:46:56Z"} +{"event": "transfer", "phase": 2, "tick": 19, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.5814999999529391, "seconds": 0.2466285410000637, "mbps": 0.033215944783932715, "utc": "2026-09-23T10:46:56Z"} +{"event": "transfer", "phase": 2, "tick": 20, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.5814580001460854, "seconds": 0.47821508300012283, "mbps": 0.01713036725777613, "utc": "2026-09-23T10:47:01Z"} +{"event": "transfer", "phase": 2, "tick": 20, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.9299999999020656, "seconds": 0.16415579100021205, "mbps": 0.0499038136278081, "utc": "2026-09-23T10:47:01Z"} +{"event": "transfer", "phase": 2, "tick": 20, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.8360419999225996, "seconds": 0.1677491249997729, "mbps": 0.04883482998800196, "utc": "2026-09-23T10:47:01Z"} +{"event": "transfer", "phase": 2, "tick": 20, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.5149579999160778, "seconds": 0.17589716599968597, "mbps": 0.0465726662134774, "utc": "2026-09-23T10:47:01Z"} +{"event": "transfer", "phase": 2, "tick": 20, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3945410000815173, "seconds": 0.7215815829999883, "mbps": 0.011352839641418803, "utc": "2026-09-23T10:47:01Z"} +{"event": "transfer", "phase": 2, "tick": 21, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1622079996413959, "seconds": 0.16861937499970736, "mbps": 0.04858279186489819, "utc": "2026-09-23T10:47:06Z"} +{"event": "transfer", "phase": 2, "tick": 21, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.694832999874052, "seconds": 0.17642383299971698, "mbps": 0.04643363575494441, "utc": "2026-09-23T10:47:06Z"} +{"event": "transfer", "phase": 2, "tick": 21, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.461583000036626, "seconds": 0.1845483330002935, "mbps": 0.04438945541700976, "utc": "2026-09-23T10:47:06Z"} +{"event": "transfer", "phase": 2, "tick": 21, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.873624999916501, "seconds": 0.1766643330001898, "mbps": 0.04637042384775652, "utc": "2026-09-23T10:47:06Z"} +{"event": "transfer", "phase": 2, "tick": 21, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3403749999270076, "seconds": 0.28282695899997634, "mbps": 0.028964707003057248, "utc": "2026-09-23T10:47:06Z"} +{"event": "transfer", "phase": 2, "tick": 22, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.3020419996792043, "seconds": 0.4173099589997946, "mbps": 0.01963049245130532, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 22, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.179333999971277, "seconds": 0.1864876669997102, "mbps": 0.04392783786615085, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 22, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.3489590003009653, "seconds": 0.1933662500000537, "mbps": 0.04236520075244633, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 22, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.9386669996492856, "seconds": 0.19130704199960746, "mbps": 0.042821215122947794, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 22, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.5865420000409358, "seconds": 0.28448124999977153, "mbps": 0.02879627391965755, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 23, "mode": "raw", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.4634589997513103, "seconds": 0.17061812499969164, "mbps": 0.04801365622799339, "utc": "2026-09-23T10:47:11Z"} +{"event": "transfer", "phase": 2, "tick": 23, "mode": "base64", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.2026660001538403, "seconds": 0.4170134159999179, "mbps": 0.019644451918548377, "utc": "2026-09-23T10:47:12Z"} +{"event": "transfer", "phase": 2, "tick": 23, "mode": "base85", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.3464580001709692, "seconds": 0.17515829200010558, "mbps": 0.04676912469547866, "utc": "2026-09-23T10:47:12Z"} +{"event": "transfer", "phase": 2, "tick": 23, "mode": "lowpop85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2139999998908024, "seconds": 0.4783012080001754, "mbps": 0.017127282689189855, "utc": "2026-09-23T10:47:12Z"} +{"event": "transfer", "phase": 2, "tick": 23, "mode": "tls", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.334540999981982, "seconds": 0.2810435830001552, "mbps": 0.02914850398842046, "utc": "2026-09-23T10:47:12Z"} +{"event": "phase_complete", "phase": 2, "utc": "2026-09-23T10:47:16Z"} +{"event": "phase_start", "phase": 3, "port_modes": ["lowpop85", "tls", "raw", "base64", "base85"], "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:47:17Z"} +{"event": "health", "phase": 3, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:47:17Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.6489589997945586, "seconds": 0.4763893750000534, "mbps": 0.01719601743846424, "utc": "2026-09-23T10:47:22Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.8465839998498268, "seconds": 0.48741483399999197, "mbps": 0.016807038745152627, "utc": "2026-09-23T10:47:22Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.9737499997063424, "seconds": 0.17493387500007884, "mbps": 0.046829123290136394, "utc": "2026-09-23T10:47:22Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.4186250000420841, "seconds": 0.1734386660000382, "mbps": 0.047232835612320695, "utc": "2026-09-23T10:47:22Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.8091670003741456, "seconds": 0.2548860000001696, "mbps": 0.03213985860343271, "utc": "2026-09-23T10:47:22Z"} +{"event": "transfer", "phase": 3, "tick": 1, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.1503749997245905, "seconds": 2.646290791999945, "mbps": 0.0030956537447681108, "utc": "2026-09-23T10:47:27Z"} +{"event": "transfer", "phase": 3, "tick": 1, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.6817499997850973, "seconds": 2.3824694589998217, "mbps": 0.003438449113819517, "utc": "2026-09-23T10:47:27Z"} +{"event": "transfer", "phase": 3, "tick": 1, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8056670003497857, "seconds": 2.3825787079999827, "mbps": 0.0034382914497194687, "utc": "2026-09-23T10:47:27Z"} +{"event": "transfer", "phase": 3, "tick": 1, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.8443749998150452, "seconds": 2.3831408749997536, "mbps": 0.0034374803797533986, "utc": "2026-09-23T10:47:27Z"} +{"event": "transfer", "phase": 3, "tick": 1, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6410410001080891, "seconds": 2.931810915999904, "mbps": 0.0027941774673439644, "utc": "2026-09-23T10:47:27Z"} +{"event": "transfer", "phase": 3, "tick": 2, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 102.59920799990141, "seconds": 0.27651049999985844, "mbps": 0.029626361385929986, "utc": "2026-09-23T10:47:32Z"} +{"event": "transfer", "phase": 3, "tick": 2, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 103.15283399995678, "seconds": 0.26565220899965425, "mbps": 0.030837311802706154, "utc": "2026-09-23T10:47:32Z"} +{"event": "transfer", "phase": 3, "tick": 2, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 102.40879200000563, "seconds": 0.2741751670000667, "mbps": 0.02987870889123232, "utc": "2026-09-23T10:47:32Z"} +{"event": "transfer", "phase": 3, "tick": 2, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 101.95554199981416, "seconds": 0.5398778329999914, "mbps": 0.015173803218551727, "utc": "2026-09-23T10:47:32Z"} +{"event": "transfer", "phase": 3, "tick": 2, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 101.57541599983233, "seconds": 0.8741516249997403, "mbps": 0.009371371928757135, "utc": "2026-09-23T10:47:32Z"} +{"event": "transfer", "phase": 3, "tick": 3, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.5305000001717417, "seconds": 0.24162133300023925, "mbps": 0.03390429105857092, "utc": "2026-09-23T10:47:37Z"} +{"event": "transfer", "phase": 3, "tick": 3, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.4583750003112073, "seconds": 0.4866099999999278, "mbps": 0.016834836933070044, "utc": "2026-09-23T10:47:37Z"} +{"event": "transfer", "phase": 3, "tick": 3, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.4961669999138394, "seconds": 0.44335904199988363, "mbps": 0.018477124010030113, "utc": "2026-09-23T10:47:37Z"} +{"event": "transfer", "phase": 3, "tick": 3, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.8218330003728624, "seconds": 0.2425642080002035, "mbps": 0.033772501176237535, "utc": "2026-09-23T10:47:37Z"} +{"event": "transfer", "phase": 3, "tick": 3, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0977920001096209, "seconds": 0.42023158299980423, "mbps": 0.019494013137998284, "utc": "2026-09-23T10:47:37Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "raw", "port": 32222, "size": 10485760, "success": true, "socks_handshake_ms": 0.8817920002002211, "seconds": 22.308338166999874, "mbps": 3.7603016133263765, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "base64", "port": 32223, "size": 10485760, "success": true, "socks_handshake_ms": 1.0542079999140697, "seconds": 20.628349082999648, "mbps": 4.066543554332842, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "tls", "port": 32221, "size": 10485760, "success": true, "socks_handshake_ms": 0.9115829998336267, "seconds": 21.44314600000007, "mbps": 3.91202298394087, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 4, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6926669998392754, "seconds": 0.2991048750000118, "mbps": 0.027388386765677678, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 4, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.7107080000423593, "seconds": 0.3026142079997953, "mbps": 0.027070771244176152, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 4, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6375829998432891, "seconds": 0.3027359580000848, "mbps": 0.027059884310134397, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 4, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.5584589998761658, "seconds": 0.3033647090001068, "mbps": 0.02700380023438097, "utc": "2026-09-23T10:47:42Z"} +{"event": "transfer", "phase": 3, "tick": 4, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8066249997682462, "seconds": 0.3607072499999049, "mbps": 0.022710938025232816, "utc": "2026-09-23T10:47:42Z"} +{"event": "health", "phase": 3, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 5, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.072666000254685, "seconds": 0.4775625410002249, "mbps": 0.017153774211106188, "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 5, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.2475409998842224, "seconds": 0.16153516599979412, "mbps": 0.05071341555442139, "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 5, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.663291000364552, "seconds": 0.46406970800035197, "mbps": 0.017652520426939364, "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 5, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0461669999131118, "seconds": 0.17008529199983968, "mbps": 0.04816407053002397, "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 5, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.5757919998359284, "seconds": 0.82200899999998, "mbps": 0.00996582762475861, "utc": "2026-09-23T10:47:47Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "base85", "port": 32224, "size": 10485760, "success": true, "socks_handshake_ms": 1.7772080000213464, "seconds": 31.07729512500009, "mbps": 2.699272239189116, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 6, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6100840000726748, "seconds": 0.1675729170001432, "mbps": 0.048886181291413575, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 6, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.6367080000018177, "seconds": 0.4450064580000799, "mbps": 0.018408721610054767, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 6, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.36999999974796083, "seconds": 0.4678331669997533, "mbps": 0.01751051566637711, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 6, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.38829200002510333, "seconds": 0.559239417000299, "mbps": 0.014648466740668997, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 6, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.31287499996324186, "seconds": 0.257966375000251, "mbps": 0.03175607673671434, "utc": "2026-09-23T10:47:52Z"} +{"event": "transfer", "phase": 3, "tick": 0, "mode": "lowpop85", "port": 32220, "size": 10485760, "success": true, "socks_handshake_ms": 1.371584000025905, "seconds": 35.449576541999704, "mbps": 2.3663492820743297, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 7, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.216417000250658, "seconds": 0.6339855420001186, "mbps": 0.012921430312362656, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 7, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.5871660000593693, "seconds": 0.17626295800027947, "mbps": 0.046476015680997546, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 7, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.09424999982366, "seconds": 0.479178624999804, "mbps": 0.017095921171365585, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 7, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.1112919996776327, "seconds": 0.1796678749997227, "mbps": 0.04559524066287668, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 7, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6401249997907144, "seconds": 0.25695795799992993, "mbps": 0.03188070166716624, "utc": "2026-09-23T10:47:57Z"} +{"event": "transfer", "phase": 3, "tick": 8, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6572080001205904, "seconds": 0.40961508300006244, "mbps": 0.019999263552506318, "utc": "2026-09-23T10:48:02Z"} +{"event": "transfer", "phase": 3, "tick": 8, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.8048340000641474, "seconds": 0.1699498340003629, "mbps": 0.04820245955628593, "utc": "2026-09-23T10:48:02Z"} +{"event": "transfer", "phase": 3, "tick": 8, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.5461669998112484, "seconds": 0.4403142090000074, "mbps": 0.018604895850635298, "utc": "2026-09-23T10:48:02Z"} +{"event": "transfer", "phase": 3, "tick": 8, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.6345419997160207, "seconds": 0.16720141699988744, "mbps": 0.04899480008596766, "utc": "2026-09-23T10:48:02Z"} +{"event": "transfer", "phase": 3, "tick": 8, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8475419999740552, "seconds": 0.719309666999834, "mbps": 0.01138869721321553, "utc": "2026-09-23T10:48:02Z"} +{"event": "transfer", "phase": 3, "tick": 9, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 3.7007079999966663, "seconds": 0.185799667000083, "mbps": 0.04409049882740824, "utc": "2026-09-23T10:48:07Z"} +{"event": "transfer", "phase": 3, "tick": 9, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.7521669999259757, "seconds": 0.19221895900000163, "mbps": 0.042618064537535714, "utc": "2026-09-23T10:48:07Z"} +{"event": "transfer", "phase": 3, "tick": 9, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 3.600416999688605, "seconds": 0.4783143750000818, "mbps": 0.017126811210720145, "utc": "2026-09-23T10:48:07Z"} +{"event": "transfer", "phase": 3, "tick": 9, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.813333000176499, "seconds": 0.1868448330001229, "mbps": 0.043843866958818235, "utc": "2026-09-23T10:48:07Z"} +{"event": "transfer", "phase": 3, "tick": 9, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.7145829999426496, "seconds": 0.2754460000001018, "mbps": 0.029740856647026907, "utc": "2026-09-23T10:48:07Z"} +{"event": "transfer", "phase": 3, "tick": 10, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.1601670003074105, "seconds": 0.17650220900031854, "mbps": 0.0464130168477677, "utc": "2026-09-23T10:48:12Z"} +{"event": "transfer", "phase": 3, "tick": 10, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.4697080000587448, "seconds": 0.17975775000013527, "mbps": 0.04557244402532762, "utc": "2026-09-23T10:48:12Z"} +{"event": "transfer", "phase": 3, "tick": 10, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.1372089998076262, "seconds": 0.4234261249998781, "mbps": 0.01934694039013856, "utc": "2026-09-23T10:48:12Z"} +{"event": "transfer", "phase": 3, "tick": 10, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3743750000685395, "seconds": 0.48288079200028733, "mbps": 0.01696484957719156, "utc": "2026-09-23T10:48:12Z"} +{"event": "transfer", "phase": 3, "tick": 10, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.5457080001178838, "seconds": 0.2692446249998284, "mbps": 0.030425862726155523, "utc": "2026-09-23T10:48:12Z"} +{"event": "health", "phase": 3, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 11, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 5.2776669999730075, "seconds": 0.46511387500004275, "mbps": 0.017612891036628928, "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 11, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 5.537665999781893, "seconds": 0.1723399999996218, "mbps": 0.04753394452836241, "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 11, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 5.580750000262924, "seconds": 0.1714658750001945, "mbps": 0.047776270351116264, "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 11, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.510250000137603, "seconds": 0.1896366669998315, "mbps": 0.04319839685859528, "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 11, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 5.214249999880849, "seconds": 0.2806828749999113, "mbps": 0.029185962984035235, "utc": "2026-09-23T10:48:17Z"} +{"event": "transfer", "phase": 3, "tick": 12, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.8354170001657621, "seconds": 0.17286070900036066, "mbps": 0.04739075783834086, "utc": "2026-09-23T10:48:22Z"} +{"event": "transfer", "phase": 3, "tick": 12, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9472500000811124, "seconds": 0.18067837500029782, "mbps": 0.04534023510000296, "utc": "2026-09-23T10:48:22Z"} +{"event": "transfer", "phase": 3, "tick": 12, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.7989999999153952, "seconds": 0.45325887499984674, "mbps": 0.018073556750549606, "utc": "2026-09-23T10:48:22Z"} +{"event": "transfer", "phase": 3, "tick": 12, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.8224590001191245, "seconds": 0.48725400000012087, "mbps": 0.016812586453878196, "utc": "2026-09-23T10:48:22Z"} +{"event": "transfer", "phase": 3, "tick": 12, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.43208399958894, "seconds": 0.2531112089995986, "mbps": 0.032365220143265136, "utc": "2026-09-23T10:48:22Z"} +{"event": "transfer", "phase": 3, "tick": 13, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.213791999816749, "seconds": 0.47024904199997763, "mbps": 0.017420556488875076, "utc": "2026-09-23T10:48:27Z"} +{"event": "transfer", "phase": 3, "tick": 13, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 4.75674999961484, "seconds": 0.17303499999979977, "mbps": 0.04734302308786939, "utc": "2026-09-23T10:48:27Z"} +{"event": "transfer", "phase": 3, "tick": 13, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.3283329999467242, "seconds": 0.16839024999990215, "mbps": 0.048648897427284295, "utc": "2026-09-23T10:48:27Z"} +{"event": "transfer", "phase": 3, "tick": 13, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 4.760625000017171, "seconds": 0.18188591600028303, "mbps": 0.04503922117855048, "utc": "2026-09-23T10:48:27Z"} +{"event": "transfer", "phase": 3, "tick": 13, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.3346249997994164, "seconds": 0.7305215420001332, "mbps": 0.01121390613283038, "utc": "2026-09-23T10:48:27Z"} +{"event": "transfer", "phase": 3, "tick": 14, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.0909590002702316, "seconds": 0.17618779200029167, "mbps": 0.04649584348038393, "utc": "2026-09-23T10:48:32Z"} +{"event": "transfer", "phase": 3, "tick": 14, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.6670420000082231, "seconds": 0.47251137500006735, "mbps": 0.01733714876176014, "utc": "2026-09-23T10:48:32Z"} +{"event": "transfer", "phase": 3, "tick": 14, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.8384170002718747, "seconds": 0.4971535840004435, "mbps": 0.016477805377729495, "utc": "2026-09-23T10:48:32Z"} +{"event": "transfer", "phase": 3, "tick": 14, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.9154579999849375, "seconds": 0.4641607080002359, "mbps": 0.01764905960113245, "utc": "2026-09-23T10:48:32Z"} +{"event": "transfer", "phase": 3, "tick": 14, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.964999999927386, "seconds": 0.2621070000000145, "mbps": 0.031254411366348656, "utc": "2026-09-23T10:48:32Z"} +{"event": "transfer", "phase": 3, "tick": 15, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.6982080001071154, "seconds": 0.4314501660001042, "mbps": 0.018987129095224455, "utc": "2026-09-23T10:48:37Z"} +{"event": "transfer", "phase": 3, "tick": 15, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.580749999902764, "seconds": 0.1761834170001748, "mbps": 0.04649699806873352, "utc": "2026-09-23T10:48:37Z"} +{"event": "transfer", "phase": 3, "tick": 15, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.4682499997652485, "seconds": 0.4395163330000287, "mbps": 0.01863867024937038, "utc": "2026-09-23T10:48:37Z"} +{"event": "transfer", "phase": 3, "tick": 15, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.365708000070299, "seconds": 0.1708928329999253, "mbps": 0.04793647490180925, "utc": "2026-09-23T10:48:37Z"} +{"event": "transfer", "phase": 3, "tick": 15, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.3940839999122545, "seconds": 0.7262619170001017, "mbps": 0.011279677218706284, "utc": "2026-09-23T10:48:37Z"} +{"event": "transfer", "phase": 3, "tick": 16, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.7133330002252478, "seconds": 0.46337237500029005, "mbps": 0.01767908585399566, "utc": "2026-09-23T10:48:42Z"} +{"event": "transfer", "phase": 3, "tick": 16, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.7203750000808213, "seconds": 0.17274287500003993, "mbps": 0.04742308474371581, "utc": "2026-09-23T10:48:42Z"} +{"event": "transfer", "phase": 3, "tick": 16, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.4771250000412692, "seconds": 0.4846656249997068, "mbps": 0.016902374704219958, "utc": "2026-09-23T10:48:42Z"} +{"event": "transfer", "phase": 3, "tick": 16, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.3631670001122984, "seconds": 0.1637034999998832, "mbps": 0.05004169122838452, "utc": "2026-09-23T10:48:42Z"} +{"event": "transfer", "phase": 3, "tick": 16, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.0985829996789107, "seconds": 0.7021907909997935, "mbps": 0.011666344966353182, "utc": "2026-09-23T10:48:42Z"} +{"event": "health", "phase": 3, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 17, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.3615839998237789, "seconds": 0.1658419169998524, "mbps": 0.04939643817556264, "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 17, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.6612500001210719, "seconds": 0.4703735409998444, "mbps": 0.01741594559631642, "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 17, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8477920000586892, "seconds": 0.17010179199996855, "mbps": 0.04815939857941952, "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 17, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.7539170001109596, "seconds": 0.4420377500000541, "mbps": 0.01853235385439139, "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 17, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.7426659999509866, "seconds": 0.23427445800007263, "mbps": 0.03496753367794563, "utc": "2026-09-23T10:48:47Z"} +{"event": "transfer", "phase": 3, "tick": 18, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.071541999863257, "seconds": 0.18875929199975872, "mbps": 0.0433991879987051, "utc": "2026-09-23T10:48:52Z"} +{"event": "transfer", "phase": 3, "tick": 18, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.7170830001305148, "seconds": 0.18496458300023733, "mbps": 0.04428956001803593, "utc": "2026-09-23T10:48:52Z"} +{"event": "transfer", "phase": 3, "tick": 18, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.663792000272224, "seconds": 0.18393375000005108, "mbps": 0.044537775150007675, "utc": "2026-09-23T10:48:52Z"} +{"event": "transfer", "phase": 3, "tick": 18, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3212089997978183, "seconds": 0.18118566700013616, "mbps": 0.045213289415403056, "utc": "2026-09-23T10:48:52Z"} +{"event": "transfer", "phase": 3, "tick": 18, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.3782089999949676, "seconds": 0.2592273750001368, "mbps": 0.03160160071827166, "utc": "2026-09-23T10:48:52Z"} +{"event": "transfer", "phase": 3, "tick": 19, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.1464999999807333, "seconds": 0.18102187500016953, "mbps": 0.04525419925073878, "utc": "2026-09-23T10:48:57Z"} +{"event": "transfer", "phase": 3, "tick": 19, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.0692919997600256, "seconds": 0.1672793749999073, "mbps": 0.048971966807052805, "utc": "2026-09-23T10:48:57Z"} +{"event": "transfer", "phase": 3, "tick": 19, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.6063750003922905, "seconds": 0.1649187080001866, "mbps": 0.049672957660999446, "utc": "2026-09-23T10:48:57Z"} +{"event": "transfer", "phase": 3, "tick": 19, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.2043749998156272, "seconds": 0.177972791999764, "mbps": 0.046029507701440465, "utc": "2026-09-23T10:48:57Z"} +{"event": "transfer", "phase": 3, "tick": 19, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.8094590000146127, "seconds": 0.2631667919999927, "mbps": 0.031128547556259403, "utc": "2026-09-23T10:48:57Z"} +{"event": "transfer", "phase": 3, "tick": 20, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.1146670003654435, "seconds": 0.16964416700011498, "mbps": 0.048289311356012894, "utc": "2026-09-23T10:49:02Z"} +{"event": "transfer", "phase": 3, "tick": 20, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.3038340002822224, "seconds": 0.17608816700021634, "mbps": 0.0465221493275578, "utc": "2026-09-23T10:49:02Z"} +{"event": "transfer", "phase": 3, "tick": 20, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9425420003026375, "seconds": 0.1718740420001268, "mbps": 0.0476628111183535, "utc": "2026-09-23T10:49:02Z"} +{"event": "transfer", "phase": 3, "tick": 20, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.56458300034501, "seconds": 0.18124500000021726, "mbps": 0.04519848823410401, "utc": "2026-09-23T10:49:02Z"} +{"event": "transfer", "phase": 3, "tick": 20, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.426625000021886, "seconds": 0.7104714170000079, "mbps": 0.011530372375275879, "utc": "2026-09-23T10:49:02Z"} +{"event": "transfer", "phase": 3, "tick": 21, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.7965000001822773, "seconds": 0.4774710840001717, "mbps": 0.01715705992364776, "utc": "2026-09-23T10:49:07Z"} +{"event": "transfer", "phase": 3, "tick": 21, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.1565829997598485, "seconds": 0.1758217080000577, "mbps": 0.04659265396282757, "utc": "2026-09-23T10:49:07Z"} +{"event": "transfer", "phase": 3, "tick": 21, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9557080002196017, "seconds": 0.17887916600011522, "mbps": 0.04579627791866339, "utc": "2026-09-23T10:49:07Z"} +{"event": "transfer", "phase": 3, "tick": 21, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.98591700018369, "seconds": 0.17475166699978217, "mbps": 0.04687795052627573, "utc": "2026-09-23T10:49:07Z"} +{"event": "transfer", "phase": 3, "tick": 21, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.577666999764915, "seconds": 0.25059974999976475, "mbps": 0.032689577703120976, "utc": "2026-09-23T10:49:07Z"} +{"event": "transfer", "phase": 3, "tick": 22, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.5241669998431462, "seconds": 0.18167991700011044, "mbps": 0.045090289203484284, "utc": "2026-09-23T10:49:12Z"} +{"event": "transfer", "phase": 3, "tick": 22, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5624160000697884, "seconds": 0.1780015409999578, "mbps": 0.04602207348307138, "utc": "2026-09-23T10:49:12Z"} +{"event": "transfer", "phase": 3, "tick": 22, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0923750000984, "seconds": 0.4241552909998063, "mbps": 0.019313681035759474, "utc": "2026-09-23T10:49:12Z"} +{"event": "transfer", "phase": 3, "tick": 22, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3129999997545383, "seconds": 0.17187370900001042, "mbps": 0.04766290346360945, "utc": "2026-09-23T10:49:12Z"} +{"event": "transfer", "phase": 3, "tick": 22, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2530839999271848, "seconds": 0.25733995900009177, "mbps": 0.0318333772641857, "utc": "2026-09-23T10:49:12Z"} +{"event": "transfer", "phase": 3, "tick": 23, "mode": "raw", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.0434999999233696, "seconds": 0.4341508749998866, "mbps": 0.018869016445036853, "utc": "2026-09-23T10:49:13Z"} +{"event": "transfer", "phase": 3, "tick": 23, "mode": "base64", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.9870000003502355, "seconds": 0.1773473749999539, "mbps": 0.04619183114496129, "utc": "2026-09-23T10:49:13Z"} +{"event": "transfer", "phase": 3, "tick": 23, "mode": "base85", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9187499999825377, "seconds": 0.17376500000000306, "mbps": 0.04714413144188907, "utc": "2026-09-23T10:49:13Z"} +{"event": "transfer", "phase": 3, "tick": 23, "mode": "lowpop85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.7651250002709276, "seconds": 0.48806979200026035, "mbps": 0.016784484789412312, "utc": "2026-09-23T10:49:13Z"} +{"event": "transfer", "phase": 3, "tick": 23, "mode": "tls", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6906670000716986, "seconds": 0.258849249999912, "mbps": 0.03164776409436297, "utc": "2026-09-23T10:49:13Z"} +{"event": "phase_complete", "phase": 3, "utc": "2026-09-23T10:49:17Z"} +{"event": "phase_start", "phase": 4, "port_modes": ["base85", "lowpop85", "tls", "raw", "base64"], "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:49:18Z"} +{"event": "health", "phase": 4, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:49:19Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.166374999887921, "seconds": 0.48064245799969285, "mbps": 0.017043854248942017, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "raw", "port": 32223, "size": 10485760, "success": true, "socks_handshake_ms": 2.0145419998698344, "seconds": 3.4463355840002805, "mbps": 24.340659217704662, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.0323329999882844, "seconds": 0.4907058750000033, "mbps": 0.01669431815952875, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 2.026500000283704, "seconds": 0.1938712910000504, "mbps": 0.042254838030649264, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.5422090000356548, "seconds": 0.41844004199992924, "mbps": 0.019577476287514054, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.4602920000470476, "seconds": 0.2508511249998264, "mbps": 0.03265681985682013, "utc": "2026-09-23T10:49:23Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "tls", "port": 32222, "size": 10485760, "success": true, "socks_handshake_ms": 2.2463339996647846, "seconds": 9.67709320899985, "mbps": 8.668520410858978, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 1, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.3481670002875035, "seconds": 0.19271058300000732, "mbps": 0.04250934158608035, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 1, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.497083000231214, "seconds": 0.18867520799994963, "mbps": 0.04341852905232884, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 1, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.7982499996614933, "seconds": 0.18996195799991256, "mbps": 0.043124423891249694, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 1, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.1349170003995823, "seconds": 0.4919025000003785, "mbps": 0.016653706781310722, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 1, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.706666999780282, "seconds": 0.271728875000008, "mbps": 0.030147697774113108, "utc": "2026-09-23T10:49:28Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "base64", "port": 32224, "size": 10485760, "success": true, "socks_handshake_ms": 2.359291999709967, "seconds": 12.960189124999943, "mbps": 6.472596903557947, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 2, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.6194580000737915, "seconds": 0.5585275409998758, "mbps": 0.014667137067824238, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 2, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6621249999625434, "seconds": 0.560157375000017, "mbps": 0.014624461563145091, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 2, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.4600000002028537, "seconds": 0.1860754160002216, "mbps": 0.04402516020703264, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 2, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.6044159999873955, "seconds": 0.18097500000021682, "mbps": 0.04526592070722578, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 2, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.45095800032868283, "seconds": 0.7766825410003548, "mbps": 0.010547423905588034, "utc": "2026-09-23T10:49:33Z"} +{"event": "transfer", "phase": 4, "tick": 3, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.5917920002502797, "seconds": 2.870292458000222, "mbps": 0.0028540645665450746, "utc": "2026-09-23T10:49:38Z"} +{"event": "transfer", "phase": 4, "tick": 3, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.9557909997965908, "seconds": 2.868201916000089, "mbps": 0.0028561448042766545, "utc": "2026-09-23T10:49:38Z"} +{"event": "transfer", "phase": 4, "tick": 3, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0046249999504653, "seconds": 2.5228305829996316, "mbps": 0.0032471463027294355, "utc": "2026-09-23T10:49:38Z"} +{"event": "transfer", "phase": 4, "tick": 3, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8043749999160354, "seconds": 2.522159874999943, "mbps": 0.00324800980350232, "utc": "2026-09-23T10:49:38Z"} +{"event": "transfer", "phase": 4, "tick": 3, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.5184579999877315, "seconds": 3.504046291999657, "mbps": 0.0023378686573587086, "utc": "2026-09-23T10:49:38Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "base85", "port": 32220, "size": 10485760, "success": true, "socks_handshake_ms": 1.5254580002874718, "seconds": 21.20610912500024, "mbps": 3.955750652113041, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 0, "mode": "lowpop85", "port": 32221, "size": 10485760, "success": true, "socks_handshake_ms": 2.180416000101104, "seconds": 23.45770879099973, "mbps": 3.5760559885620826, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 4, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.5973330000633723, "seconds": 1.8344012080001448, "mbps": 0.00446576243205317, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 4, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.2661250002565794, "seconds": 1.9794604590001654, "mbps": 0.0041385014602099285, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 4, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3926249998803542, "seconds": 1.980526374999954, "mbps": 0.004136274125609758, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 4, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.2444160001905402, "seconds": 1.8321672500001114, "mbps": 0.004471207527587616, "utc": "2026-09-23T10:49:43Z"} +{"event": "transfer", "phase": 4, "tick": 4, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.8785839997690346, "seconds": 2.1072687920000135, "mbps": 0.00388749647463101, "utc": "2026-09-23T10:49:43Z"} +{"event": "health", "phase": 4, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 5, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.1798749999106803, "seconds": 0.4225141250003617, "mbps": 0.019388700910278413, "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 5, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.007916999697045, "seconds": 0.1757174579997809, "mbps": 0.04662029654452556, "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 5, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.4227080000637216, "seconds": 0.44049262499993347, "mbps": 0.018597360171469925, "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 5, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0096669998347352, "seconds": 0.17506979199970374, "mbps": 0.04679276708122132, "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 5, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.9473330003165756, "seconds": 0.2627990830001181, "mbps": 0.031172102681942454, "utc": "2026-09-23T10:49:49Z"} +{"event": "transfer", "phase": 4, "tick": 6, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.2008749999949941, "seconds": 0.1685489590004181, "mbps": 0.04860308867276765, "utc": "2026-09-23T10:49:53Z"} +{"event": "transfer", "phase": 4, "tick": 6, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0907089999818709, "seconds": 0.17457458399985626, "mbps": 0.046925502053648004, "utc": "2026-09-23T10:49:53Z"} +{"event": "transfer", "phase": 4, "tick": 6, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.739625000027445, "seconds": 0.43079874999966705, "mbps": 0.019015839762780953, "utc": "2026-09-23T10:49:53Z"} +{"event": "transfer", "phase": 4, "tick": 6, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0011669996856654, "seconds": 0.1623722499998621, "mbps": 0.05045197070316484, "utc": "2026-09-23T10:49:53Z"} +{"event": "transfer", "phase": 4, "tick": 6, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.693790999979683, "seconds": 0.7217756250001912, "mbps": 0.011349787546507725, "utc": "2026-09-23T10:49:53Z"} +{"event": "transfer", "phase": 4, "tick": 7, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.6932919997998397, "seconds": 0.17529574999980468, "mbps": 0.04673245072974746, "utc": "2026-09-23T10:49:58Z"} +{"event": "transfer", "phase": 4, "tick": 7, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.3084999997990963, "seconds": 0.47389704199986227, "mbps": 0.01728645522966227, "utc": "2026-09-23T10:49:58Z"} +{"event": "transfer", "phase": 4, "tick": 7, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3211659997978131, "seconds": 0.1735523329998614, "mbps": 0.047201900766188735, "utc": "2026-09-23T10:49:58Z"} +{"event": "transfer", "phase": 4, "tick": 7, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.967791999959445, "seconds": 0.17650237499992727, "mbps": 0.04641297319655543, "utc": "2026-09-23T10:49:58Z"} +{"event": "transfer", "phase": 4, "tick": 7, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.2240410001140845, "seconds": 0.24760025000023234, "mbps": 0.03308558856460085, "utc": "2026-09-23T10:49:58Z"} +{"event": "transfer", "phase": 4, "tick": 8, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.2347080000836286, "seconds": 0.1796793329999673, "mbps": 0.04559233309265174, "utc": "2026-09-23T10:50:03Z"} +{"event": "transfer", "phase": 4, "tick": 8, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8491660000800039, "seconds": 0.4928572079998048, "mbps": 0.0166214470784472, "utc": "2026-09-23T10:50:03Z"} +{"event": "transfer", "phase": 4, "tick": 8, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.9750829999575217, "seconds": 0.4798139170002287, "mbps": 0.017073285517052013, "utc": "2026-09-23T10:50:03Z"} +{"event": "transfer", "phase": 4, "tick": 8, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.0878749999392312, "seconds": 0.17042799999990166, "mbps": 0.04806721900160025, "utc": "2026-09-23T10:50:03Z"} +{"event": "transfer", "phase": 4, "tick": 8, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.299415999710618, "seconds": 0.2746270409998033, "mbps": 0.029829546173517078, "utc": "2026-09-23T10:50:03Z"} +{"event": "transfer", "phase": 4, "tick": 9, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.288625000142929, "seconds": 0.1684509589999834, "mbps": 0.048631364574189255, "utc": "2026-09-23T10:50:08Z"} +{"event": "transfer", "phase": 4, "tick": 9, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.277874999686901, "seconds": 0.1798262499996781, "mbps": 0.04555508442184978, "utc": "2026-09-23T10:50:08Z"} +{"event": "transfer", "phase": 4, "tick": 9, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3610410001092532, "seconds": 0.2012906660002045, "mbps": 0.04069736646403503, "utc": "2026-09-23T10:50:08Z"} +{"event": "transfer", "phase": 4, "tick": 9, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.1953750001557637, "seconds": 0.16860495799983255, "mbps": 0.048586946061266685, "utc": "2026-09-23T10:50:08Z"} +{"event": "transfer", "phase": 4, "tick": 9, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.735124999868276, "seconds": 0.2907927080000263, "mbps": 0.02817127037449391, "utc": "2026-09-23T10:50:08Z"} +{"event": "transfer", "phase": 4, "tick": 10, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.9957499998781714, "seconds": 0.48080266700026186, "mbps": 0.017038175039897477, "utc": "2026-09-23T10:50:13Z"} +{"event": "transfer", "phase": 4, "tick": 10, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.6955420001067978, "seconds": 0.18206641699998727, "mbps": 0.04499456920712936, "utc": "2026-09-23T10:50:13Z"} +{"event": "transfer", "phase": 4, "tick": 10, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.7142500000772998, "seconds": 0.1802685829998154, "mbps": 0.04544330389510184, "utc": "2026-09-23T10:50:13Z"} +{"event": "transfer", "phase": 4, "tick": 10, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.9606250000615546, "seconds": 0.4852473330001885, "mbps": 0.01688211236391652, "utc": "2026-09-23T10:50:13Z"} +{"event": "transfer", "phase": 4, "tick": 10, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9557920002407627, "seconds": 0.7220167919999767, "mbps": 0.011345996506962492, "utc": "2026-09-23T10:50:13Z"} +{"event": "health", "phase": 4, "healthy": true, "local_transfers": [true, true, true, true, true], "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 11, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 1.8049999998765998, "seconds": 0.18723816700003226, "mbps": 0.04375176349594679, "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 11, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.0265830001117138, "seconds": 0.4353659999997035, "mbps": 0.018816352218605906, "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 11, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.0845419997167483, "seconds": 0.17930841699990197, "mbps": 0.04568664503911425, "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 11, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.5142500001275039, "seconds": 0.4177634590000707, "mbps": 0.019609182716956136, "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 11, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.0060419999717851, "seconds": 0.2790750419999313, "mbps": 0.0293541118592827, "utc": "2026-09-23T10:50:19Z"} +{"event": "transfer", "phase": 4, "tick": 12, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.518499999998312, "seconds": 0.1721749580001415, "mbps": 0.04757950921058606, "utc": "2026-09-23T10:50:23Z"} +{"event": "transfer", "phase": 4, "tick": 12, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.6489170000349986, "seconds": 0.1759593329998097, "mbps": 0.04655621194022632, "utc": "2026-09-23T10:50:23Z"} +{"event": "transfer", "phase": 4, "tick": 12, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 0.578582999878563, "seconds": 0.17422916599980454, "mbps": 0.047018534198856175, "utc": "2026-09-23T10:50:23Z"} +{"event": "transfer", "phase": 4, "tick": 12, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.7123750001483131, "seconds": 0.17958712500012552, "mbps": 0.04561574221979596, "utc": "2026-09-23T10:50:23Z"} +{"event": "transfer", "phase": 4, "tick": 12, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.6503339996015711, "seconds": 0.24952424999992218, "mbps": 0.032830476396592936, "utc": "2026-09-23T10:50:23Z"} +{"event": "transfer", "phase": 4, "tick": 13, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 2.4822499999572756, "seconds": 0.4834789169999567, "mbps": 0.01694386189749973, "utc": "2026-09-23T10:50:28Z"} +{"event": "transfer", "phase": 4, "tick": 13, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 2.3419999997713603, "seconds": 0.1742402499999116, "mbps": 0.04701554319397588, "utc": "2026-09-23T10:50:28Z"} +{"event": "transfer", "phase": 4, "tick": 13, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.3557080001191935, "seconds": 0.17650870800025587, "mbps": 0.04641130793381664, "utc": "2026-09-23T10:50:28Z"} +{"event": "transfer", "phase": 4, "tick": 13, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 2.548500000102649, "seconds": 0.48033504100021673, "mbps": 0.017054762406968148, "utc": "2026-09-23T10:50:28Z"} +{"event": "transfer", "phase": 4, "tick": 13, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 2.0447920001060993, "seconds": 0.2684532919997764, "mbps": 0.03051555054130915, "utc": "2026-09-23T10:50:28Z"} +{"event": "transfer", "phase": 4, "tick": 14, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 0.7845410000300035, "seconds": 0.17079812499969194, "mbps": 0.047963055800611255, "utc": "2026-09-23T10:50:33Z"} +{"event": "transfer", "phase": 4, "tick": 14, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 0.8765829998083063, "seconds": 0.15850270800001454, "mbps": 0.05168365956245523, "utc": "2026-09-23T10:50:33Z"} +{"event": "transfer", "phase": 4, "tick": 14, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.028624999889871, "seconds": 0.1710546249996696, "mbps": 0.0478911341918748, "utc": "2026-09-23T10:50:33Z"} +{"event": "transfer", "phase": 4, "tick": 14, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 0.8217079998757981, "seconds": 0.17172720799999297, "mbps": 0.04770356483056742, "utc": "2026-09-23T10:50:33Z"} +{"event": "transfer", "phase": 4, "tick": 14, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 0.9295419999943988, "seconds": 0.27447012499987977, "mbps": 0.029846599880419003, "utc": "2026-09-23T10:50:33Z"} +{"event": "transfer", "phase": 4, "tick": 15, "mode": "raw", "port": 32223, "size": 1024, "success": true, "socks_handshake_ms": 3.3607499999561696, "seconds": 0.1756137080001281, "mbps": 0.04664783913106615, "utc": "2026-09-23T10:50:38Z"} +{"event": "transfer", "phase": 4, "tick": 15, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 1.824709000175062, "seconds": 0.43719770899997457, "mbps": 0.018737518132787095, "utc": "2026-09-23T10:50:38Z"} +{"event": "transfer", "phase": 4, "tick": 15, "mode": "base85", "port": 32220, "size": 1024, "success": true, "socks_handshake_ms": 1.7340829999739071, "seconds": 0.1800664159995904, "mbps": 0.04549432471637929, "utc": "2026-09-23T10:50:38Z"} +{"event": "transfer", "phase": 4, "tick": 15, "mode": "lowpop85", "port": 32221, "size": 1024, "success": true, "socks_handshake_ms": 1.700792000065121, "seconds": 0.48426083300000755, "mbps": 0.016916503342321455, "utc": "2026-09-23T10:50:38Z"} +{"event": "transfer", "phase": 4, "tick": 15, "mode": "tls", "port": 32222, "size": 1024, "success": true, "socks_handshake_ms": 1.6561669999646256, "seconds": 0.7182521250001628, "mbps": 0.011405465733913621, "utc": "2026-09-23T10:50:38Z"} +{"event": "transfer", "phase": 4, "tick": 16, "mode": "base64", "port": 32224, "size": 1024, "success": true, "socks_handshake_ms": 3.2940000000962755, "seconds": 0.4790282079998178, "mbps": 0.017101289367082773, "utc": "2026-09-23T10:50:43Z"} +{"event": "aborted", "reason": "AssertionError: remote supervisor stopped", "utc": "2026-09-23T10:50:53Z"} +{"event": "cleanup", "remote_exit": 255, "captures_retrieved": false, "utc": "2026-09-23T10:51:09Z"} diff --git a/docs/measurements/printable-salt-2026-09-23/local-packets.json b/docs/measurements/printable-salt-2026-09-23/local-packets.json new file mode 100644 index 000000000..881a58fa8 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/local-packets.json @@ -0,0 +1,30 @@ +[ + { + "method": "aes-256-gcm", + "enabled": false, + "flows": 32, + "printable": 0, + "sequence_ok": 32 + }, + { + "method": "aes-256-gcm", + "enabled": true, + "flows": 32, + "printable": 32, + "sequence_ok": 32 + }, + { + "method": "chacha20-ietf-poly1305", + "enabled": false, + "flows": 32, + "printable": 0, + "sequence_ok": 32 + }, + { + "method": "chacha20-ietf-poly1305", + "enabled": true, + "flows": 32, + "printable": 32, + "sequence_ok": 32 + } +] diff --git a/docs/measurements/printable-salt-2026-09-23/local-transports.json b/docs/measurements/printable-salt-2026-09-23/local-transports.json new file mode 100644 index 000000000..38e9dbcb6 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/local-transports.json @@ -0,0 +1,92 @@ +[ + { + "mode": "raw", + "cipher": "chacha20-ietf-poly1305", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.08012195900028019, + "echo_mbps": 1046.9798922378652 + }, + { + "mode": "base64", + "cipher": "chacha20-ietf-poly1305", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.07741466600009517, + "echo_mbps": 1083.5941603093252 + }, + { + "mode": "base85", + "cipher": "chacha20-ietf-poly1305", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.905553042000065, + "echo_mbps": 92.63519209733269 + }, + { + "mode": "lowpop85", + "cipher": "chacha20-ietf-poly1305", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 1.2371564999998554, + "echo_mbps": 67.80555249073969 + }, + { + "mode": "tls", + "cipher": "chacha20-ietf-poly1305", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.08228737499985073, + "echo_mbps": 1019.4283144911619 + }, + { + "mode": "raw", + "cipher": "aes-256-gcm", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.06935350000003382, + "echo_mbps": 1209.5435702590223 + }, + { + "mode": "base64", + "cipher": "aes-256-gcm", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.07823958400012998, + "echo_mbps": 1072.1692998758867 + }, + { + "mode": "base85", + "cipher": "aes-256-gcm", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.8975279999999657, + "echo_mbps": 93.4634685491742 + }, + { + "mode": "lowpop85", + "cipher": "aes-256-gcm", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 1.2540836660000423, + "echo_mbps": 66.89033776156141 + }, + { + "mode": "tls", + "cipher": "aes-256-gcm", + "concurrent_transfers": 4, + "success": true, + "large_bytes": 10485760, + "large_seconds": 0.06872141700023349, + "echo_mbps": 1220.6686599566913 + } +] diff --git a/docs/measurements/printable-salt-2026-09-23/salt-aborted.json b/docs/measurements/printable-salt-2026-09-23/salt-aborted.json new file mode 100644 index 000000000..57b36f462 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/salt-aborted.json @@ -0,0 +1,41 @@ +{ + "status": "aborted_management_ssh_timeout", + "planned_phases": 2, + "completed_phases": 0, + "recorded_start": "2026-09-23T10:20:21Z", + "cleanup": { + "event": "cleanup", + "remote_exit": 255, + "capture_retrieved": true, + "utc": "2026-09-23T10:36:30Z" + }, + "health_checks_passed": 32, + "modes": { + "stock": { + "recorded_transfers": 197, + "success": 197, + "small_count": 191, + "large_count": 6, + "small_median_ms": 173.38316699988354, + "large_median_mbps": 23.89289883802104 + }, + "modified": { + "recorded_transfers": 197, + "success": 197, + "small_count": 191, + "large_count": 6, + "small_median_ms": 172.58616700019047, + "large_median_mbps": 27.25382920437916 + } + }, + "unsolicited_replay": { + "mode": "stock", + "port": 32181, + "payload_bytes": 79, + "payload_sha256": "4ccffea9fe4f971ff965a11b7a3431d7f153ac0905903fb362ca37273064b7bf", + "delay_seconds": 3.1093130111694336, + "other_source": true, + "server_application_response_bytes": 0, + "attribution": "unknown" + } +} diff --git a/docs/measurements/printable-salt-2026-09-23/salt-events.jsonl b/docs/measurements/printable-salt-2026-09-23/salt-events.jsonl new file mode 100644 index 000000000..71d1104bd --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/salt-events.jsonl @@ -0,0 +1,428 @@ +{"event": "start", "ports": [32181, 32182], "phase_seconds": 1800, "origin": 35195, "utc": "2026-09-23T10:20:21Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:20:21Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.07708299992737, "seconds": 0.4746761669998705, "mbps": 0.017258081550157615, "utc": "2026-09-23T10:20:26Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 0.9884999999485444, "seconds": 3.68738541599987, "mbps": 22.749474366311524, "utc": "2026-09-23T10:20:26Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.166499999953885, "seconds": 0.18239775000006375, "mbps": 0.04491283472519336, "utc": "2026-09-23T10:20:26Z"} +{"event": "transfer", "phase": 1, "tick": 0, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 1.2602909998804535, "seconds": 1.2562909579999086, "mbps": 66.77281203516081, "utc": "2026-09-23T10:20:26Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8604170000126032, "seconds": 0.16168004199994357, "mbps": 0.05066797298334979, "utc": "2026-09-23T10:20:31Z"} +{"event": "transfer", "phase": 1, "tick": 1, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6520419999560545, "seconds": 0.16008416699992267, "mbps": 0.051173080720743336, "utc": "2026-09-23T10:20:31Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.029375000143773, "seconds": 0.16374612499998875, "mbps": 0.05002866480046818, "utc": "2026-09-23T10:20:36Z"} +{"event": "transfer", "phase": 1, "tick": 2, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6416249998437706, "seconds": 0.1810012910000296, "mbps": 0.04525934569162084, "utc": "2026-09-23T10:20:36Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4927080001380091, "seconds": 0.17101433300013014, "mbps": 0.04790241762948469, "utc": "2026-09-23T10:20:41Z"} +{"event": "transfer", "phase": 1, "tick": 3, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4393330000311835, "seconds": 0.462255500000083, "mbps": 0.01772180103859993, "utc": "2026-09-23T10:20:41Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6825000000389991, "seconds": 0.17441299999995863, "mbps": 0.046968975936437896, "utc": "2026-09-23T10:20:46Z"} +{"event": "transfer", "phase": 1, "tick": 4, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8116249998693092, "seconds": 0.16240758299977642, "mbps": 0.050440994494766155, "utc": "2026-09-23T10:20:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:20:51Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 2.547249999906853, "seconds": 0.4660955419999482, "mbps": 0.01757579565092882, "utc": "2026-09-23T10:20:51Z"} +{"event": "transfer", "phase": 1, "tick": 5, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.998749999984284, "seconds": 0.161428750000141, "mbps": 0.05074684651893076, "utc": "2026-09-23T10:20:51Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.430249999908483, "seconds": 0.16786183399995025, "mbps": 0.04880204037328955, "utc": "2026-09-23T10:20:56Z"} +{"event": "transfer", "phase": 1, "tick": 6, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3683750001073349, "seconds": 0.1655447919999915, "mbps": 0.04948509645655552, "utc": "2026-09-23T10:20:56Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8043329999054549, "seconds": 0.16805029099987223, "mbps": 0.04874731219600345, "utc": "2026-09-23T10:21:01Z"} +{"event": "transfer", "phase": 1, "tick": 7, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7184999999481079, "seconds": 0.17298270900005264, "mbps": 0.04735733442582118, "utc": "2026-09-23T10:21:01Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7589580000058049, "seconds": 0.4733758750001016, "mbps": 0.01730548689241555, "utc": "2026-09-23T10:21:06Z"} +{"event": "transfer", "phase": 1, "tick": 8, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.1182079999798589, "seconds": 0.17493629199998395, "mbps": 0.04682847627752823, "utc": "2026-09-23T10:21:06Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6244579999474809, "seconds": 0.41546966700002486, "mbps": 0.01971744425808951, "utc": "2026-09-23T10:21:11Z"} +{"event": "transfer", "phase": 1, "tick": 9, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6172089999836317, "seconds": 0.16211687499981053, "mbps": 0.05053144529222867, "utc": "2026-09-23T10:21:11Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.721291999980167, "seconds": 0.46248320800009424, "mbps": 0.01771307554154124, "utc": "2026-09-23T10:21:16Z"} +{"event": "transfer", "phase": 1, "tick": 10, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.1616660001436685, "seconds": 0.17358608300014566, "mbps": 0.04719272339357485, "utc": "2026-09-23T10:21:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:21:21Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.5892920000624144, "seconds": 0.17100879200006602, "mbps": 0.047903969756109596, "utc": "2026-09-23T10:21:21Z"} +{"event": "transfer", "phase": 1, "tick": 11, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.9834170000194717, "seconds": 0.16659470900003726, "mbps": 0.049173230345497754, "utc": "2026-09-23T10:21:21Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5423749998954008, "seconds": 0.47912720799990893, "mbps": 0.017097755801005473, "utc": "2026-09-23T10:21:26Z"} +{"event": "transfer", "phase": 1, "tick": 12, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5503749998752028, "seconds": 0.16778204100000949, "mbps": 0.04882524941986811, "utc": "2026-09-23T10:21:26Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7272910002029676, "seconds": 0.16632595800001582, "mbps": 0.04925268489960672, "utc": "2026-09-23T10:21:31Z"} +{"event": "transfer", "phase": 1, "tick": 13, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.889792000180023, "seconds": 0.47105058400006783, "mbps": 0.017390913583919514, "utc": "2026-09-23T10:21:31Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4371249999385327, "seconds": 0.1760685829999602, "mbps": 0.046527323957629915, "utc": "2026-09-23T10:21:36Z"} +{"event": "transfer", "phase": 1, "tick": 14, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9365420000904123, "seconds": 0.46219891700002336, "mbps": 0.017723970564819794, "utc": "2026-09-23T10:21:36Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6064579999929265, "seconds": 0.16133937500012507, "mbps": 0.05077495806583885, "utc": "2026-09-23T10:21:41Z"} +{"event": "transfer", "phase": 1, "tick": 15, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4845419998673606, "seconds": 0.1668760420000126, "mbps": 0.04909033017453387, "utc": "2026-09-23T10:21:41Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9139999999661086, "seconds": 0.16341687499993895, "mbps": 0.05012946184415202, "utc": "2026-09-23T10:21:46Z"} +{"event": "transfer", "phase": 1, "tick": 16, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.44737500002156594, "seconds": 0.47527916700005335, "mbps": 0.01723618573838958, "utc": "2026-09-23T10:21:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:21:51Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.504583000065395, "seconds": 0.46682733300008294, "mbps": 0.017548244117056754, "utc": "2026-09-23T10:21:51Z"} +{"event": "transfer", "phase": 1, "tick": 17, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.28158299983260804, "seconds": 0.16561366599989924, "mbps": 0.04946451701639757, "utc": "2026-09-23T10:21:51Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.48637500003678724, "seconds": 0.1668564999999944, "mbps": 0.049096079565376684, "utc": "2026-09-23T10:21:56Z"} +{"event": "transfer", "phase": 1, "tick": 18, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6385409999438707, "seconds": 0.17090925000002244, "mbps": 0.04793187027617829, "utc": "2026-09-23T10:21:56Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9501670001554885, "seconds": 0.16386862500007737, "mbps": 0.049991265869205485, "utc": "2026-09-23T10:22:01Z"} +{"event": "transfer", "phase": 1, "tick": 19, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5816249999952561, "seconds": 0.16834516700009772, "mbps": 0.04866192564943219, "utc": "2026-09-23T10:22:01Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4240829998470872, "seconds": 0.16433554199988976, "mbps": 0.04984922859843366, "utc": "2026-09-23T10:22:06Z"} +{"event": "transfer", "phase": 1, "tick": 20, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 2.2953329998927074, "seconds": 0.1777703749999091, "mbps": 0.046081918879926916, "utc": "2026-09-23T10:22:06Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6995409999035473, "seconds": 0.17045866599983128, "mbps": 0.04805857157187953, "utc": "2026-09-23T10:22:11Z"} +{"event": "transfer", "phase": 1, "tick": 21, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4591250001340086, "seconds": 0.17782200000010562, "mbps": 0.046068540450535565, "utc": "2026-09-23T10:22:11Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.48212499996225233, "seconds": 0.4061119579998831, "mbps": 0.02017177735998199, "utc": "2026-09-23T10:22:16Z"} +{"event": "transfer", "phase": 1, "tick": 22, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3857079998397239, "seconds": 0.4819466659998852, "mbps": 0.016997731446080695, "utc": "2026-09-23T10:22:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:22:21Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5678330001046561, "seconds": 0.173008333000098, "mbps": 0.047350320403326235, "utc": "2026-09-23T10:22:21Z"} +{"event": "transfer", "phase": 1, "tick": 23, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3730830001131835, "seconds": 0.1613667080000596, "mbps": 0.050766357581001, "utc": "2026-09-23T10:22:21Z"} +{"event": "transfer", "phase": 1, "tick": 24, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5192920000354206, "seconds": 0.17530233399997996, "mbps": 0.04673069555366523, "utc": "2026-09-23T10:22:26Z"} +{"event": "transfer", "phase": 1, "tick": 24, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3791249998812418, "seconds": 0.47544349999998303, "mbps": 0.01723022819746256, "utc": "2026-09-23T10:22:26Z"} +{"event": "transfer", "phase": 1, "tick": 25, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5282499998884305, "seconds": 0.16129158400008237, "mbps": 0.05079000278152031, "utc": "2026-09-23T10:22:31Z"} +{"event": "transfer", "phase": 1, "tick": 25, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3998750000846485, "seconds": 0.16129266600000847, "mbps": 0.050789662066839235, "utc": "2026-09-23T10:22:31Z"} +{"event": "transfer", "phase": 1, "tick": 26, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4982499999641732, "seconds": 0.1574301249997916, "mbps": 0.05203578412969465, "utc": "2026-09-23T10:22:36Z"} +{"event": "transfer", "phase": 1, "tick": 26, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.37212500001260196, "seconds": 0.4795134579999285, "mbps": 0.017083983490618154, "utc": "2026-09-23T10:22:36Z"} +{"event": "transfer", "phase": 1, "tick": 27, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6369590000758762, "seconds": 0.16320025000004534, "mbps": 0.05019600153797389, "utc": "2026-09-23T10:22:41Z"} +{"event": "transfer", "phase": 1, "tick": 27, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7193340002231707, "seconds": 0.166861666999921, "mbps": 0.04909455926749119, "utc": "2026-09-23T10:22:41Z"} +{"event": "transfer", "phase": 1, "tick": 28, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.3880829999616253, "seconds": 0.15547220799999195, "mbps": 0.05269108932961462, "utc": "2026-09-23T10:22:46Z"} +{"event": "transfer", "phase": 1, "tick": 28, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4258750000190048, "seconds": 0.15996387499990306, "mbps": 0.05121156261065172, "utc": "2026-09-23T10:22:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:22:51Z"} +{"event": "transfer", "phase": 1, "tick": 29, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5581250002251181, "seconds": 0.43378574999997, "mbps": 0.018884898823902277, "utc": "2026-09-23T10:22:51Z"} +{"event": "transfer", "phase": 1, "tick": 29, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3197089999957825, "seconds": 0.16345729200020287, "mbps": 0.050117066664666345, "utc": "2026-09-23T10:22:51Z"} +{"event": "transfer", "phase": 1, "tick": 30, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5762089999734599, "seconds": 0.16137666700024056, "mbps": 0.05076322464875166, "utc": "2026-09-23T10:22:56Z"} +{"event": "transfer", "phase": 1, "tick": 30, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7460830001946306, "seconds": 0.17550695799991445, "mbps": 0.04667621211920267, "utc": "2026-09-23T10:22:56Z"} +{"event": "transfer", "phase": 1, "tick": 31, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0450409999975818, "seconds": 0.17688812500000495, "mbps": 0.04631175778475672, "utc": "2026-09-23T10:23:01Z"} +{"event": "transfer", "phase": 1, "tick": 31, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.4825829998699191, "seconds": 0.47172295800010033, "mbps": 0.017366125309504776, "utc": "2026-09-23T10:23:01Z"} +{"event": "transfer", "phase": 1, "tick": 32, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9310000000368746, "seconds": 0.17008608300011474, "mbps": 0.04816384653878163, "utc": "2026-09-23T10:23:06Z"} +{"event": "transfer", "phase": 1, "tick": 32, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8893750000424916, "seconds": 0.16769266700021035, "mbps": 0.048851271475035485, "utc": "2026-09-23T10:23:06Z"} +{"event": "transfer", "phase": 1, "tick": 33, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0348340001655743, "seconds": 0.47415924999995696, "mbps": 0.01727689589520977, "utc": "2026-09-23T10:23:11Z"} +{"event": "transfer", "phase": 1, "tick": 33, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.450124999792024, "seconds": 0.1640834579998227, "mbps": 0.049925812753220083, "utc": "2026-09-23T10:23:11Z"} +{"event": "transfer", "phase": 1, "tick": 34, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6645829998888075, "seconds": 0.16685479099987788, "mbps": 0.04909658242900557, "utc": "2026-09-23T10:23:16Z"} +{"event": "transfer", "phase": 1, "tick": 34, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5886250000912696, "seconds": 0.48344358400026977, "mbps": 0.016945100258059127, "utc": "2026-09-23T10:23:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:23:21Z"} +{"event": "transfer", "phase": 1, "tick": 35, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5301250002958113, "seconds": 0.4568431249999776, "mbps": 0.017931757208780152, "utc": "2026-09-23T10:23:21Z"} +{"event": "transfer", "phase": 1, "tick": 35, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3622499998527928, "seconds": 0.4861939170000369, "mbps": 0.016849244125774158, "utc": "2026-09-23T10:23:21Z"} +{"event": "transfer", "phase": 1, "tick": 36, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.100459000099363, "seconds": 0.47372054200013736, "mbps": 0.017292895860947538, "utc": "2026-09-23T10:23:26Z"} +{"event": "transfer", "phase": 1, "tick": 36, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 0.6604589998460142, "seconds": 1.2613280420000592, "mbps": 66.50615637386746, "utc": "2026-09-23T10:23:26Z"} +{"event": "transfer", "phase": 1, "tick": 36, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8209590000660683, "seconds": 0.16412520899984884, "mbps": 0.049913112372685815, "utc": "2026-09-23T10:23:26Z"} +{"event": "transfer", "phase": 1, "tick": 36, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 0.9732090002216864, "seconds": 8.626497666999967, "mbps": 9.724233778083548, "utc": "2026-09-23T10:23:31Z"} +{"event": "transfer", "phase": 1, "tick": 37, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.49008399992089835, "seconds": 0.1756322920000457, "mbps": 0.046642903231017836, "utc": "2026-09-23T10:23:31Z"} +{"event": "transfer", "phase": 1, "tick": 37, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4568749995996768, "seconds": 0.43638037499977145, "mbps": 0.01877261322763264, "utc": "2026-09-23T10:23:31Z"} +{"event": "transfer", "phase": 1, "tick": 38, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4349160003584984, "seconds": 0.16769579100036935, "mbps": 0.048850361426077515, "utc": "2026-09-23T10:23:36Z"} +{"event": "transfer", "phase": 1, "tick": 38, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6523329998344707, "seconds": 0.47816554199971506, "mbps": 0.017132142073100036, "utc": "2026-09-23T10:23:36Z"} +{"event": "transfer", "phase": 1, "tick": 39, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5417080001279828, "seconds": 0.17466800000011062, "mbps": 0.046900405340387544, "utc": "2026-09-23T10:23:41Z"} +{"event": "transfer", "phase": 1, "tick": 39, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5767500001638837, "seconds": 0.16907670900036464, "mbps": 0.0484513807279176, "utc": "2026-09-23T10:23:41Z"} +{"event": "transfer", "phase": 1, "tick": 40, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6635830000050191, "seconds": 0.17263483299984728, "mbps": 0.047452764066491994, "utc": "2026-09-23T10:23:46Z"} +{"event": "transfer", "phase": 1, "tick": 40, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5956250001872831, "seconds": 0.1645787500001461, "mbps": 0.04977556337007498, "utc": "2026-09-23T10:23:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:23:51Z"} +{"event": "transfer", "phase": 1, "tick": 41, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6705420000798767, "seconds": 0.1644955840001785, "mbps": 0.04980072899702348, "utc": "2026-09-23T10:23:51Z"} +{"event": "transfer", "phase": 1, "tick": 41, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5868749999535794, "seconds": 0.17623904199990648, "mbps": 0.04648232257188704, "utc": "2026-09-23T10:23:51Z"} +{"event": "transfer", "phase": 1, "tick": 42, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.694042000304762, "seconds": 0.4852464170003259, "mbps": 0.01688214423228703, "utc": "2026-09-23T10:23:56Z"} +{"event": "transfer", "phase": 1, "tick": 42, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5425419999482983, "seconds": 0.16384329199991043, "mbps": 0.049998995381541025, "utc": "2026-09-23T10:23:56Z"} +{"event": "transfer", "phase": 1, "tick": 43, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1844579998978588, "seconds": 0.17879033300005176, "mbps": 0.04581903206141256, "utc": "2026-09-23T10:24:01Z"} +{"event": "transfer", "phase": 1, "tick": 43, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5895419999433216, "seconds": 0.40511758399998143, "mbps": 0.020221289629334813, "utc": "2026-09-23T10:24:01Z"} +{"event": "transfer", "phase": 1, "tick": 44, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4150419999859878, "seconds": 0.4633721250002054, "mbps": 0.017679095392275416, "utc": "2026-09-23T10:24:06Z"} +{"event": "transfer", "phase": 1, "tick": 44, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5607079997389519, "seconds": 0.427554582999619, "mbps": 0.019160126743413483, "utc": "2026-09-23T10:24:06Z"} +{"event": "transfer", "phase": 1, "tick": 45, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6737079997947149, "seconds": 0.15976737500022864, "mbps": 0.05127454838629148, "utc": "2026-09-23T10:24:11Z"} +{"event": "transfer", "phase": 1, "tick": 45, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9069580000868882, "seconds": 0.16541220799990697, "mbps": 0.04952476059085438, "utc": "2026-09-23T10:24:11Z"} +{"event": "transfer", "phase": 1, "tick": 46, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.7914999998538406, "seconds": 0.4908315420002509, "mbps": 0.016690043933639074, "utc": "2026-09-23T10:24:16Z"} +{"event": "transfer", "phase": 1, "tick": 46, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.6989999999168504, "seconds": 0.16163054199978433, "mbps": 0.05068349025279474, "utc": "2026-09-23T10:24:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:24:21Z"} +{"event": "transfer", "phase": 1, "tick": 47, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.46762500005570473, "seconds": 0.17617554099979316, "mbps": 0.04649907673625148, "utc": "2026-09-23T10:24:21Z"} +{"event": "transfer", "phase": 1, "tick": 47, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4262500001459557, "seconds": 0.17485212500014313, "mbps": 0.04685101768133097, "utc": "2026-09-23T10:24:21Z"} +{"event": "transfer", "phase": 1, "tick": 48, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6021250001140288, "seconds": 0.1651900840001872, "mbps": 0.049591354405938294, "utc": "2026-09-23T10:24:26Z"} +{"event": "transfer", "phase": 1, "tick": 48, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5211249999774736, "seconds": 0.4708157919999394, "mbps": 0.01739958629085461, "utc": "2026-09-23T10:24:26Z"} +{"event": "transfer", "phase": 1, "tick": 49, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4727499997206905, "seconds": 0.1609494999997878, "mbps": 0.05089795246341741, "utc": "2026-09-23T10:24:31Z"} +{"event": "transfer", "phase": 1, "tick": 49, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9027500000229338, "seconds": 0.16495287500038103, "mbps": 0.04966266880756748, "utc": "2026-09-23T10:24:31Z"} +{"event": "transfer", "phase": 1, "tick": 50, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1306250003144669, "seconds": 0.1638394999999946, "mbps": 0.05000015258835794, "utc": "2026-09-23T10:24:36Z"} +{"event": "transfer", "phase": 1, "tick": 50, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.041541999711626, "seconds": 0.17175245899989022, "mbps": 0.04769655146541591, "utc": "2026-09-23T10:24:36Z"} +{"event": "transfer", "phase": 1, "tick": 51, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8336670002790925, "seconds": 0.4655162500002916, "mbps": 0.01759766710613189, "utc": "2026-09-23T10:24:41Z"} +{"event": "transfer", "phase": 1, "tick": 51, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8230420003201289, "seconds": 0.182456208000076, "mbps": 0.04489844489148096, "utc": "2026-09-23T10:24:41Z"} +{"event": "transfer", "phase": 1, "tick": 52, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.38616700021520955, "seconds": 0.16301987500037285, "mbps": 0.05025154141469722, "utc": "2026-09-23T10:24:46Z"} +{"event": "transfer", "phase": 1, "tick": 52, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.45933299998068833, "seconds": 0.16159816700019292, "mbps": 0.050693644315843146, "utc": "2026-09-23T10:24:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:24:51Z"} +{"event": "transfer", "phase": 1, "tick": 53, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6463340000664175, "seconds": 0.16877824999983204, "mbps": 0.048537059721902275, "utc": "2026-09-23T10:24:51Z"} +{"event": "transfer", "phase": 1, "tick": 53, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5809590002172627, "seconds": 0.4542871250000644, "mbps": 0.01803264840490216, "utc": "2026-09-23T10:24:51Z"} +{"event": "transfer", "phase": 1, "tick": 54, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 2.043790999778139, "seconds": 0.16880499999979293, "mbps": 0.048529368205977606, "utc": "2026-09-23T10:24:56Z"} +{"event": "transfer", "phase": 1, "tick": 54, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.217916999848967, "seconds": 0.4155414169999858, "mbps": 0.019714039719896995, "utc": "2026-09-23T10:24:56Z"} +{"event": "transfer", "phase": 1, "tick": 55, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5576250000558503, "seconds": 0.16953320799984795, "mbps": 0.04832091657232928, "utc": "2026-09-23T10:25:01Z"} +{"event": "transfer", "phase": 1, "tick": 55, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.529082999946695, "seconds": 0.17361475000006976, "mbps": 0.0471849310038272, "utc": "2026-09-23T10:25:01Z"} +{"event": "transfer", "phase": 1, "tick": 56, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.104334000046947, "seconds": 0.16543524999997317, "mbps": 0.04951786272877956, "utc": "2026-09-23T10:25:06Z"} +{"event": "transfer", "phase": 1, "tick": 56, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6843340001978504, "seconds": 0.17363495900008274, "mbps": 0.04717943925103294, "utc": "2026-09-23T10:25:06Z"} +{"event": "transfer", "phase": 1, "tick": 57, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.46495800006596255, "seconds": 0.4803418749997945, "mbps": 0.017054519762624284, "utc": "2026-09-23T10:25:11Z"} +{"event": "transfer", "phase": 1, "tick": 57, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5672080001204449, "seconds": 0.17290662499999598, "mbps": 0.04737817304571291, "utc": "2026-09-23T10:25:11Z"} +{"event": "transfer", "phase": 1, "tick": 58, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.2722920000669546, "seconds": 0.17368325000006735, "mbps": 0.047166321450092766, "utc": "2026-09-23T10:25:16Z"} +{"event": "transfer", "phase": 1, "tick": 58, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7415830000354617, "seconds": 0.1627143329997125, "mbps": 0.050345902840744056, "utc": "2026-09-23T10:25:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:25:21Z"} +{"event": "transfer", "phase": 1, "tick": 59, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6467080002039438, "seconds": 0.16280633299993497, "mbps": 0.05031745294578481, "utc": "2026-09-23T10:25:21Z"} +{"event": "transfer", "phase": 1, "tick": 59, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4677080000874412, "seconds": 0.16064041700019516, "mbps": 0.050995883557685535, "utc": "2026-09-23T10:25:21Z"} +{"event": "transfer", "phase": 1, "tick": 60, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8450830000583665, "seconds": 0.1638714999999138, "mbps": 0.0499903888107713, "utc": "2026-09-23T10:25:26Z"} +{"event": "transfer", "phase": 1, "tick": 60, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6267500002650195, "seconds": 0.15948895800011087, "mbps": 0.05136405744148322, "utc": "2026-09-23T10:25:26Z"} +{"event": "transfer", "phase": 1, "tick": 61, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.074249999874155, "seconds": 0.16764174999980241, "mbps": 0.04886610883034599, "utc": "2026-09-23T10:25:31Z"} +{"event": "transfer", "phase": 1, "tick": 61, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.5801659997123352, "seconds": 0.1733834999999999, "mbps": 0.047247863839408044, "utc": "2026-09-23T10:25:31Z"} +{"event": "transfer", "phase": 1, "tick": 62, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8562499997424311, "seconds": 0.16690887499999008, "mbps": 0.04908067351122274, "utc": "2026-09-23T10:25:36Z"} +{"event": "transfer", "phase": 1, "tick": 62, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.3017500000387372, "seconds": 0.16675958399991941, "mbps": 0.049124612831871535, "utc": "2026-09-23T10:25:36Z"} +{"event": "transfer", "phase": 1, "tick": 63, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5895419999433216, "seconds": 0.17170341700011704, "mbps": 0.047710174573837486, "utc": "2026-09-23T10:25:41Z"} +{"event": "transfer", "phase": 1, "tick": 63, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8530410000275879, "seconds": 0.16689620800025295, "mbps": 0.049084398610108534, "utc": "2026-09-23T10:25:41Z"} +{"event": "transfer", "phase": 1, "tick": 64, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7237910003823345, "seconds": 0.46334112500017, "mbps": 0.017680278218336426, "utc": "2026-09-23T10:25:46Z"} +{"event": "transfer", "phase": 1, "tick": 64, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6437500001084118, "seconds": 0.17145012499986478, "mbps": 0.04778065924423479, "utc": "2026-09-23T10:25:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:25:51Z"} +{"event": "transfer", "phase": 1, "tick": 65, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.149249999798485, "seconds": 0.47408091699981014, "mbps": 0.017279750578957136, "utc": "2026-09-23T10:25:51Z"} +{"event": "transfer", "phase": 1, "tick": 65, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6603750002796005, "seconds": 0.16750208300027225, "mbps": 0.048906854489604676, "utc": "2026-09-23T10:25:51Z"} +{"event": "transfer", "phase": 1, "tick": 66, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6477920001088933, "seconds": 0.47260020799967606, "mbps": 0.01733388995885845, "utc": "2026-09-23T10:25:56Z"} +{"event": "transfer", "phase": 1, "tick": 66, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5790830000478309, "seconds": 0.4682138749999467, "mbps": 0.017496277742732276, "utc": "2026-09-23T10:25:56Z"} +{"event": "transfer", "phase": 1, "tick": 67, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5947499998910644, "seconds": 0.17160649999959787, "mbps": 0.04773711951481556, "utc": "2026-09-23T10:26:01Z"} +{"event": "transfer", "phase": 1, "tick": 67, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5843330000061542, "seconds": 0.47116462499980116, "mbps": 0.01738670427560952, "utc": "2026-09-23T10:26:01Z"} +{"event": "transfer", "phase": 1, "tick": 68, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6207080000422138, "seconds": 0.19514075000006414, "mbps": 0.041979955493649114, "utc": "2026-09-23T10:26:06Z"} +{"event": "transfer", "phase": 1, "tick": 68, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5664579998665431, "seconds": 0.1963957500001925, "mbps": 0.04171169691804416, "utc": "2026-09-23T10:26:06Z"} +{"event": "transfer", "phase": 1, "tick": 69, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4687080001749564, "seconds": 0.4615891250000459, "mbps": 0.017747385188069988, "utc": "2026-09-23T10:26:11Z"} +{"event": "transfer", "phase": 1, "tick": 69, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8347920002051978, "seconds": 0.1646387920000052, "mbps": 0.049757410756510786, "utc": "2026-09-23T10:26:11Z"} +{"event": "transfer", "phase": 1, "tick": 70, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6927080003151787, "seconds": 0.15880266700014545, "mbps": 0.05158603539065561, "utc": "2026-09-23T10:26:16Z"} +{"event": "transfer", "phase": 1, "tick": 70, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9371249998366693, "seconds": 0.17579049999994822, "mbps": 0.04660092553353232, "utc": "2026-09-23T10:26:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:26:21Z"} +{"event": "transfer", "phase": 1, "tick": 71, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5287079998197441, "seconds": 0.1638856249996934, "mbps": 0.04998608023135236, "utc": "2026-09-23T10:26:21Z"} +{"event": "transfer", "phase": 1, "tick": 71, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.574041000163561, "seconds": 0.172522625000056, "mbps": 0.04748362714743844, "utc": "2026-09-23T10:26:21Z"} +{"event": "transfer", "phase": 1, "tick": 72, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.45087499984219903, "seconds": 0.15991445899999235, "mbps": 0.05122738776235607, "utc": "2026-09-23T10:26:26Z"} +{"event": "transfer", "phase": 1, "tick": 72, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 0.5465830004141026, "seconds": 3.350575041000411, "mbps": 25.03632330973055, "utc": "2026-09-23T10:26:26Z"} +{"event": "transfer", "phase": 1, "tick": 72, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5756249997830309, "seconds": 0.15099804199962819, "mbps": 0.0542523591135054, "utc": "2026-09-23T10:26:26Z"} +{"event": "transfer", "phase": 1, "tick": 72, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 0.443459000052826, "seconds": 3.1004607919999216, "mbps": 27.05600413217614, "utc": "2026-09-23T10:26:26Z"} +{"event": "transfer", "phase": 1, "tick": 73, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8438330000899441, "seconds": 0.43394404099990425, "mbps": 0.01887801012573833, "utc": "2026-09-23T10:26:31Z"} +{"event": "transfer", "phase": 1, "tick": 73, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.785708999956114, "seconds": 0.4768039169998701, "mbps": 0.017181066908060302, "utc": "2026-09-23T10:26:31Z"} +{"event": "transfer", "phase": 1, "tick": 74, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 3.502375000152824, "seconds": 0.4875597089999246, "mbps": 0.01680204464967647, "utc": "2026-09-23T10:26:36Z"} +{"event": "transfer", "phase": 1, "tick": 74, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 2.6662499999474676, "seconds": 0.17065541600004508, "mbps": 0.048003164458594365, "utc": "2026-09-23T10:26:36Z"} +{"event": "transfer", "phase": 1, "tick": 75, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9244170000783924, "seconds": 0.47354437500007407, "mbps": 0.01729932912833928, "utc": "2026-09-23T10:26:41Z"} +{"event": "transfer", "phase": 1, "tick": 75, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9186249999402207, "seconds": 0.4933475409998209, "mbps": 0.01660492719472777, "utc": "2026-09-23T10:26:41Z"} +{"event": "transfer", "phase": 1, "tick": 76, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5544589998862648, "seconds": 0.1653594169997632, "mbps": 0.049540571372549844, "utc": "2026-09-23T10:26:46Z"} +{"event": "transfer", "phase": 1, "tick": 76, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6188749998727872, "seconds": 0.4747561660001338, "mbps": 0.017255173469400902, "utc": "2026-09-23T10:26:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:26:51Z"} +{"event": "transfer", "phase": 1, "tick": 77, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4668750000055297, "seconds": 0.15716362500006653, "mbps": 0.052124020427732766, "utc": "2026-09-23T10:26:51Z"} +{"event": "transfer", "phase": 1, "tick": 77, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.348917000086658, "seconds": 0.40144516700001986, "mbps": 0.020406273816218578, "utc": "2026-09-23T10:26:51Z"} +{"event": "transfer", "phase": 1, "tick": 78, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6655420002061874, "seconds": 0.46059966700022414, "mbps": 0.017785510035976674, "utc": "2026-09-23T10:26:56Z"} +{"event": "transfer", "phase": 1, "tick": 78, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5427090000011958, "seconds": 0.42659275000005437, "mbps": 0.019203326826344225, "utc": "2026-09-23T10:26:56Z"} +{"event": "transfer", "phase": 1, "tick": 79, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 2.1448329998747795, "seconds": 0.1831133749997207, "mbps": 0.044737310969297006, "utc": "2026-09-23T10:27:01Z"} +{"event": "transfer", "phase": 1, "tick": 79, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 2.0176660000288393, "seconds": 0.17569483299985222, "mbps": 0.04662630004609692, "utc": "2026-09-23T10:27:01Z"} +{"event": "transfer", "phase": 1, "tick": 80, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7494579999729467, "seconds": 0.16261995800005025, "mbps": 0.050375120623247664, "utc": "2026-09-23T10:27:06Z"} +{"event": "transfer", "phase": 1, "tick": 80, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9622500001569279, "seconds": 0.16912662499998987, "mbps": 0.04843708079671365, "utc": "2026-09-23T10:27:06Z"} +{"event": "transfer", "phase": 1, "tick": 81, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 2.548166999986279, "seconds": 0.43245008400026563, "mbps": 0.01894322675167978, "utc": "2026-09-23T10:27:11Z"} +{"event": "transfer", "phase": 1, "tick": 81, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9042909996423987, "seconds": 0.4805897499995808, "mbps": 0.017045723509515436, "utc": "2026-09-23T10:27:11Z"} +{"event": "transfer", "phase": 1, "tick": 82, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4269999999451102, "seconds": 0.42805408300000636, "mbps": 0.019137768626306687, "utc": "2026-09-23T10:27:16Z"} +{"event": "transfer", "phase": 1, "tick": 82, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.40854100006981753, "seconds": 0.4781719580000754, "mbps": 0.017131912197993652, "utc": "2026-09-23T10:27:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:27:21Z"} +{"event": "transfer", "phase": 1, "tick": 83, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6793330003347364, "seconds": 0.17085595800017472, "mbps": 0.04794682079504434, "utc": "2026-09-23T10:27:21Z"} +{"event": "transfer", "phase": 1, "tick": 83, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5436249998638232, "seconds": 0.1707278750000114, "mbps": 0.04798279132800928, "utc": "2026-09-23T10:27:21Z"} +{"event": "transfer", "phase": 1, "tick": 84, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7993330000317656, "seconds": 0.16850916600014898, "mbps": 0.048614566165455696, "utc": "2026-09-23T10:27:26Z"} +{"event": "transfer", "phase": 1, "tick": 84, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8055829998738773, "seconds": 0.4211091669999405, "mbps": 0.019453387961989338, "utc": "2026-09-23T10:27:26Z"} +{"event": "transfer", "phase": 1, "tick": 85, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7111250001798908, "seconds": 0.1693177080001078, "mbps": 0.04838241727200078, "utc": "2026-09-23T10:27:31Z"} +{"event": "transfer", "phase": 1, "tick": 85, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6466669997280405, "seconds": 0.17344349999984843, "mbps": 0.04723151919793569, "utc": "2026-09-23T10:27:31Z"} +{"event": "transfer", "phase": 1, "tick": 86, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5595000002358574, "seconds": 0.17406337500005975, "mbps": 0.04706331817360882, "utc": "2026-09-23T10:27:36Z"} +{"event": "transfer", "phase": 1, "tick": 86, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6661669999630249, "seconds": 0.171944084000188, "mbps": 0.04764339551217733, "utc": "2026-09-23T10:27:36Z"} +{"event": "transfer", "phase": 1, "tick": 87, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7032089997665025, "seconds": 0.1693184169998858, "mbps": 0.04838221467665579, "utc": "2026-09-23T10:27:41Z"} +{"event": "transfer", "phase": 1, "tick": 87, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5756669997936115, "seconds": 0.16581899999982852, "mbps": 0.04940326500587069, "utc": "2026-09-23T10:27:41Z"} +{"event": "transfer", "phase": 1, "tick": 88, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.043500000378117, "seconds": 0.16158554200001163, "mbps": 0.050697605111225924, "utc": "2026-09-23T10:27:46Z"} +{"event": "transfer", "phase": 1, "tick": 88, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6526659999508411, "seconds": 0.4744463749998431, "mbps": 0.017266440280005742, "utc": "2026-09-23T10:27:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:27:51Z"} +{"event": "transfer", "phase": 1, "tick": 89, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1111250000794826, "seconds": 0.17492800000036368, "mbps": 0.04683069605770927, "utc": "2026-09-23T10:27:51Z"} +{"event": "transfer", "phase": 1, "tick": 89, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.75816600019607, "seconds": 0.15921104100016237, "mbps": 0.05145371796163085, "utc": "2026-09-23T10:27:51Z"} +{"event": "transfer", "phase": 1, "tick": 90, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7909999999355932, "seconds": 0.1738608750001731, "mbps": 0.047118133967701724, "utc": "2026-09-23T10:27:56Z"} +{"event": "transfer", "phase": 1, "tick": 90, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7546250003542809, "seconds": 0.17196058300032746, "mbps": 0.04763882429954543, "utc": "2026-09-23T10:27:56Z"} +{"event": "transfer", "phase": 1, "tick": 91, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.04383300003974, "seconds": 0.17600125000035405, "mbps": 0.046545123969196356, "utc": "2026-09-23T10:28:01Z"} +{"event": "transfer", "phase": 1, "tick": 91, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.87416700034737, "seconds": 0.16355041700035144, "mbps": 0.050088530193000955, "utc": "2026-09-23T10:28:01Z"} +{"event": "transfer", "phase": 1, "tick": 92, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.9133330001750437, "seconds": 0.47022270800016486, "mbps": 0.017421532096653078, "utc": "2026-09-23T10:28:06Z"} +{"event": "transfer", "phase": 1, "tick": 92, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.2465419999898586, "seconds": 0.17773562500042317, "mbps": 0.04609092859116171, "utc": "2026-09-23T10:28:06Z"} +{"event": "transfer", "phase": 1, "tick": 93, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5760419999205624, "seconds": 0.48232116700000915, "mbps": 0.016984533461289798, "utc": "2026-09-23T10:28:11Z"} +{"event": "transfer", "phase": 1, "tick": 93, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8812910000415286, "seconds": 0.16726308300030723, "mbps": 0.04897673684506313, "utc": "2026-09-23T10:28:11Z"} +{"event": "transfer", "phase": 1, "tick": 94, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 2.057083000181592, "seconds": 0.15854562499998792, "mbps": 0.051669669219826304, "utc": "2026-09-23T10:28:16Z"} +{"event": "transfer", "phase": 1, "tick": 94, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.304083999912109, "seconds": 0.16242766699997446, "mbps": 0.05043475752195153, "utc": "2026-09-23T10:28:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:28:21Z"} +{"event": "transfer", "phase": 1, "tick": 95, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9902080000756541, "seconds": 0.16318995800020275, "mbps": 0.050199167279581146, "utc": "2026-09-23T10:28:21Z"} +{"event": "transfer", "phase": 1, "tick": 95, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9887080000225978, "seconds": 0.17520100000001548, "mbps": 0.04675772398558956, "utc": "2026-09-23T10:28:21Z"} +{"event": "transfer", "phase": 1, "tick": 96, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0378330002822622, "seconds": 0.16889491700021608, "mbps": 0.048503531932755084, "utc": "2026-09-23T10:28:26Z"} +{"event": "transfer", "phase": 1, "tick": 96, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6544159996337839, "seconds": 0.17243491599992922, "mbps": 0.047507779688908035, "utc": "2026-09-23T10:28:26Z"} +{"event": "transfer", "phase": 1, "tick": 97, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.746958000036102, "seconds": 0.1828786249998302, "mbps": 0.044794737493283346, "utc": "2026-09-23T10:28:31Z"} +{"event": "transfer", "phase": 1, "tick": 97, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7257080001181748, "seconds": 0.4132891250001194, "mbps": 0.019821474857335368, "utc": "2026-09-23T10:28:31Z"} +{"event": "transfer", "phase": 1, "tick": 98, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9862080000857532, "seconds": 0.16760683300026358, "mbps": 0.04887628895169875, "utc": "2026-09-23T10:28:36Z"} +{"event": "transfer", "phase": 1, "tick": 98, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5334160000529664, "seconds": 0.40839929100002337, "mbps": 0.020058800738710223, "utc": "2026-09-23T10:28:36Z"} +{"event": "transfer", "phase": 1, "tick": 99, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6942079999134876, "seconds": 0.16455162500005827, "mbps": 0.04978376846778085, "utc": "2026-09-23T10:28:41Z"} +{"event": "transfer", "phase": 1, "tick": 99, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.909166999917943, "seconds": 0.1820307079997292, "mbps": 0.045003395800735924, "utc": "2026-09-23T10:28:41Z"} +{"event": "transfer", "phase": 1, "tick": 100, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.36649999992732774, "seconds": 0.45715895800003636, "mbps": 0.017919368868627415, "utc": "2026-09-23T10:28:46Z"} +{"event": "transfer", "phase": 1, "tick": 100, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4369169996607525, "seconds": 0.4315027919997192, "mbps": 0.01898481342851967, "utc": "2026-09-23T10:28:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:28:51Z"} +{"event": "transfer", "phase": 1, "tick": 101, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1553750000530272, "seconds": 0.16073024999968766, "mbps": 0.05096738168462949, "utc": "2026-09-23T10:28:51Z"} +{"event": "transfer", "phase": 1, "tick": 101, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6620419999308069, "seconds": 0.17722954200007734, "mbps": 0.046222542289233164, "utc": "2026-09-23T10:28:51Z"} +{"event": "transfer", "phase": 1, "tick": 102, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.017582999793376, "seconds": 0.1649268750002193, "mbps": 0.049670497909992575, "utc": "2026-09-23T10:28:56Z"} +{"event": "transfer", "phase": 1, "tick": 102, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8837079999466368, "seconds": 0.17258616700019047, "mbps": 0.0474661448387747, "utc": "2026-09-23T10:28:56Z"} +{"event": "transfer", "phase": 1, "tick": 103, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1965419998887228, "seconds": 0.173672291999992, "mbps": 0.04716929744901609, "utc": "2026-09-23T10:29:01Z"} +{"event": "transfer", "phase": 1, "tick": 103, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0829159996319504, "seconds": 0.1700998329997674, "mbps": 0.04815995322000818, "utc": "2026-09-23T10:29:01Z"} +{"event": "transfer", "phase": 1, "tick": 104, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.38654200034216046, "seconds": 0.16365025000004607, "mbps": 0.050057974246893566, "utc": "2026-09-23T10:29:06Z"} +{"event": "transfer", "phase": 1, "tick": 104, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.44066700002076686, "seconds": 0.16442470800029696, "mbps": 0.049822195822207, "utc": "2026-09-23T10:29:06Z"} +{"event": "transfer", "phase": 1, "tick": 105, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9992089999286691, "seconds": 0.48803933399995003, "mbps": 0.016785532290724825, "utc": "2026-09-23T10:29:11Z"} +{"event": "transfer", "phase": 1, "tick": 105, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9606660000827105, "seconds": 0.4583672500002649, "mbps": 0.01787213200767565, "utc": "2026-09-23T10:29:11Z"} +{"event": "transfer", "phase": 1, "tick": 106, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.3808329999847047, "seconds": 0.16491758299980575, "mbps": 0.049673296509624744, "utc": "2026-09-23T10:29:16Z"} +{"event": "transfer", "phase": 1, "tick": 106, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7675829997424444, "seconds": 0.16281120799976634, "mbps": 0.05031594630765074, "utc": "2026-09-23T10:29:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:29:21Z"} +{"event": "transfer", "phase": 1, "tick": 107, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6097089999457239, "seconds": 0.16313395900033356, "mbps": 0.05021639914950663, "utc": "2026-09-23T10:29:21Z"} +{"event": "transfer", "phase": 1, "tick": 107, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.47220800024661, "seconds": 0.1635265419999996, "mbps": 0.05009584315676424, "utc": "2026-09-23T10:29:21Z"} +{"event": "transfer", "phase": 1, "tick": 108, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.8766250000226137, "seconds": 0.17477195799983747, "mbps": 0.04687250800272901, "utc": "2026-09-23T10:29:26Z"} +{"event": "transfer", "phase": 1, "tick": 108, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 2.391917000295507, "seconds": 0.46861712500003705, "mbps": 0.017481222010397833, "utc": "2026-09-23T10:29:26Z"} +{"event": "transfer", "phase": 1, "tick": 108, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 1.3559170001826715, "seconds": 2.3482518750001873, "mbps": 35.72277782169058, "utc": "2026-09-23T10:29:26Z"} +{"event": "transfer", "phase": 1, "tick": 108, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 1.7010410001603304, "seconds": 8.626400665999881, "mbps": 9.724343123851042, "utc": "2026-09-23T10:29:31Z"} +{"event": "transfer", "phase": 1, "tick": 109, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0302089999640884, "seconds": 0.4817411250000987, "mbps": 0.017004983745156327, "utc": "2026-09-23T10:29:31Z"} +{"event": "transfer", "phase": 1, "tick": 109, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9259170001314487, "seconds": 0.16976700000031997, "mbps": 0.04825437216882292, "utc": "2026-09-23T10:29:31Z"} +{"event": "transfer", "phase": 1, "tick": 110, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8375419997719291, "seconds": 0.18703066699981719, "mbps": 0.04380030361549214, "utc": "2026-09-23T10:29:36Z"} +{"event": "transfer", "phase": 1, "tick": 110, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7559999999102729, "seconds": 0.17679770799986727, "mbps": 0.04633544231244305, "utc": "2026-09-23T10:29:36Z"} +{"event": "transfer", "phase": 1, "tick": 111, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.6060829998423287, "seconds": 0.17490158299960967, "mbps": 0.04683776933007108, "utc": "2026-09-23T10:29:41Z"} +{"event": "transfer", "phase": 1, "tick": 111, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0560840000835015, "seconds": 0.1648229170000377, "mbps": 0.04970182635463323, "utc": "2026-09-23T10:29:41Z"} +{"event": "transfer", "phase": 1, "tick": 112, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.2867499999629217, "seconds": 0.42256508400032544, "mbps": 0.019386362740736265, "utc": "2026-09-23T10:29:46Z"} +{"event": "transfer", "phase": 1, "tick": 112, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8227079997595865, "seconds": 0.15928883300011876, "mbps": 0.05142858947302284, "utc": "2026-09-23T10:29:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:29:51Z"} +{"event": "transfer", "phase": 1, "tick": 113, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9646670000620361, "seconds": 0.4866702089998398, "mbps": 0.016832754190636512, "utc": "2026-09-23T10:29:51Z"} +{"event": "transfer", "phase": 1, "tick": 113, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.3727499999731663, "seconds": 0.4043894579999687, "mbps": 0.020257699200458962, "utc": "2026-09-23T10:29:51Z"} +{"event": "transfer", "phase": 1, "tick": 114, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6570830000782735, "seconds": 0.47621987499996976, "mbps": 0.017202137983007366, "utc": "2026-09-23T10:29:56Z"} +{"event": "transfer", "phase": 1, "tick": 114, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6348340002659825, "seconds": 0.1671620840002106, "mbps": 0.0490063284924689, "utc": "2026-09-23T10:29:56Z"} +{"event": "transfer", "phase": 1, "tick": 115, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9738329999890993, "seconds": 0.16447912500007078, "mbps": 0.04980571242701148, "utc": "2026-09-23T10:30:01Z"} +{"event": "transfer", "phase": 1, "tick": 115, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9654169998611906, "seconds": 0.4696329169996716, "mbps": 0.017443411020539108, "utc": "2026-09-23T10:30:01Z"} +{"event": "transfer", "phase": 1, "tick": 116, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9119999999711581, "seconds": 0.18619745800015153, "mbps": 0.04399630418151752, "utc": "2026-09-23T10:30:06Z"} +{"event": "transfer", "phase": 1, "tick": 116, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7772919998387806, "seconds": 0.16372358399985387, "mbps": 0.050035552605587424, "utc": "2026-09-23T10:30:06Z"} +{"event": "transfer", "phase": 1, "tick": 117, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.7674169998826983, "seconds": 0.48529704200018386, "mbps": 0.016880383128312776, "utc": "2026-09-23T10:30:11Z"} +{"event": "transfer", "phase": 1, "tick": 117, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 2.2416250003516325, "seconds": 0.1654665420001038, "mbps": 0.04950849821950628, "utc": "2026-09-23T10:30:11Z"} +{"event": "transfer", "phase": 1, "tick": 118, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.3491250001607114, "seconds": 0.16485991600029593, "mbps": 0.049690671927706764, "utc": "2026-09-23T10:30:16Z"} +{"event": "transfer", "phase": 1, "tick": 118, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0354159999224066, "seconds": 0.1686103329998332, "mbps": 0.04858539719512982, "utc": "2026-09-23T10:30:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:30:21Z"} +{"event": "transfer", "phase": 1, "tick": 119, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6013750003148743, "seconds": 0.17650162500012812, "mbps": 0.04641317041695255, "utc": "2026-09-23T10:30:21Z"} +{"event": "transfer", "phase": 1, "tick": 119, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4071250000379223, "seconds": 0.1666586660003304, "mbps": 0.04915435960578107, "utc": "2026-09-23T10:30:21Z"} +{"event": "transfer", "phase": 1, "tick": 120, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7027500000731379, "seconds": 0.1744518750001589, "mbps": 0.046958509330969005, "utc": "2026-09-23T10:30:26Z"} +{"event": "transfer", "phase": 1, "tick": 120, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6263749996833212, "seconds": 0.4767039999996996, "mbps": 0.017184668053981427, "utc": "2026-09-23T10:30:26Z"} +{"event": "transfer", "phase": 1, "tick": 121, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6455829998230911, "seconds": 0.16178404099991894, "mbps": 0.05063540228917947, "utc": "2026-09-23T10:30:31Z"} +{"event": "transfer", "phase": 1, "tick": 121, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6362499998431304, "seconds": 0.1666765420000047, "mbps": 0.04914908781824721, "utc": "2026-09-23T10:30:31Z"} +{"event": "transfer", "phase": 1, "tick": 122, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7030000001577719, "seconds": 0.16930812500004322, "mbps": 0.04838515576259502, "utc": "2026-09-23T10:30:36Z"} +{"event": "transfer", "phase": 1, "tick": 122, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6807499999013089, "seconds": 0.16508779099967796, "mbps": 0.04962208259250365, "utc": "2026-09-23T10:30:36Z"} +{"event": "transfer", "phase": 1, "tick": 123, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8667080001032446, "seconds": 0.1689813329999197, "mbps": 0.04847872752905726, "utc": "2026-09-23T10:30:41Z"} +{"event": "transfer", "phase": 1, "tick": 123, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.2422919999153237, "seconds": 0.1725436249998893, "mbps": 0.047477847993545146, "utc": "2026-09-23T10:30:41Z"} +{"event": "transfer", "phase": 1, "tick": 124, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7602499999848078, "seconds": 0.15937004199986404, "mbps": 0.05140238339152216, "utc": "2026-09-23T10:30:46Z"} +{"event": "transfer", "phase": 1, "tick": 124, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.702374999946187, "seconds": 0.18343291700011832, "mbps": 0.04465937812020247, "utc": "2026-09-23T10:30:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:30:51Z"} +{"event": "transfer", "phase": 1, "tick": 125, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.167750000149681, "seconds": 0.166438959000061, "mbps": 0.049219245597402456, "utc": "2026-09-23T10:30:51Z"} +{"event": "transfer", "phase": 1, "tick": 125, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6389159998434479, "seconds": 0.16752454099969327, "mbps": 0.0489002981361101, "utc": "2026-09-23T10:30:51Z"} +{"event": "transfer", "phase": 1, "tick": 126, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8422079999945709, "seconds": 0.1723695000000589, "mbps": 0.04752580938041359, "utc": "2026-09-23T10:30:56Z"} +{"event": "transfer", "phase": 1, "tick": 126, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7566249996671104, "seconds": 0.17194274999974368, "mbps": 0.047643765148645184, "utc": "2026-09-23T10:30:56Z"} +{"event": "transfer", "phase": 1, "tick": 127, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.66079099997296, "seconds": 0.16978037499984566, "mbps": 0.04825057077419841, "utc": "2026-09-23T10:31:01Z"} +{"event": "transfer", "phase": 1, "tick": 127, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5969580001874419, "seconds": 0.4782380420001573, "mbps": 0.01712954487212731, "utc": "2026-09-23T10:31:01Z"} +{"event": "transfer", "phase": 1, "tick": 128, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5965829996057437, "seconds": 0.17072204199985208, "mbps": 0.04798443073921936, "utc": "2026-09-23T10:31:06Z"} +{"event": "transfer", "phase": 1, "tick": 128, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7269590000760218, "seconds": 0.1713795000000573, "mbps": 0.04780034951669984, "utc": "2026-09-23T10:31:06Z"} +{"event": "transfer", "phase": 1, "tick": 129, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.7945419999705337, "seconds": 0.17338316699988354, "mbps": 0.047247954583765926, "utc": "2026-09-23T10:31:11Z"} +{"event": "transfer", "phase": 1, "tick": 129, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9491250002611196, "seconds": 0.1729689580001832, "mbps": 0.047361099325066894, "utc": "2026-09-23T10:31:11Z"} +{"event": "transfer", "phase": 1, "tick": 130, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.40820799995344714, "seconds": 0.46480620800002725, "mbps": 0.017624549455242042, "utc": "2026-09-23T10:31:16Z"} +{"event": "transfer", "phase": 1, "tick": 130, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4688750000241271, "seconds": 0.4356037920001654, "mbps": 0.018806080549447764, "utc": "2026-09-23T10:31:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:31:21Z"} +{"event": "transfer", "phase": 1, "tick": 131, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9959160001926648, "seconds": 0.43856483299987303, "mbps": 0.01867910827223662, "utc": "2026-09-23T10:31:21Z"} +{"event": "transfer", "phase": 1, "tick": 131, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9536249999655411, "seconds": 0.16186945799972818, "mbps": 0.050608682460737936, "utc": "2026-09-23T10:31:21Z"} +{"event": "transfer", "phase": 1, "tick": 132, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.48066699991977657, "seconds": 0.16142620799973884, "mbps": 0.05074764563640901, "utc": "2026-09-23T10:31:26Z"} +{"event": "transfer", "phase": 1, "tick": 132, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.425333999828581, "seconds": 0.17156116700016355, "mbps": 0.0477497334813081, "utc": "2026-09-23T10:31:26Z"} +{"event": "transfer", "phase": 1, "tick": 133, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.622458000179904, "seconds": 0.1674824169999738, "mbps": 0.04891259719521054, "utc": "2026-09-23T10:31:31Z"} +{"event": "transfer", "phase": 1, "tick": 133, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7915000001048611, "seconds": 0.1662452079999639, "mbps": 0.04927660832185779, "utc": "2026-09-23T10:31:31Z"} +{"event": "transfer", "phase": 1, "tick": 134, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4619589999492746, "seconds": 0.17380845899970154, "mbps": 0.04713234354154228, "utc": "2026-09-23T10:31:36Z"} +{"event": "transfer", "phase": 1, "tick": 134, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.46733299996049027, "seconds": 0.46391412499997386, "mbps": 0.017658440557291637, "utc": "2026-09-23T10:31:36Z"} +{"event": "transfer", "phase": 1, "tick": 135, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.9501249998938874, "seconds": 0.1667044169998917, "mbps": 0.04914086949480962, "utc": "2026-09-23T10:31:41Z"} +{"event": "transfer", "phase": 1, "tick": 135, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9587080003257142, "seconds": 0.7198559160001423, "mbps": 0.01138005511647192, "utc": "2026-09-23T10:31:41Z"} +{"event": "transfer", "phase": 1, "tick": 136, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5165829998077243, "seconds": 0.16984374999992724, "mbps": 0.04823256669735277, "utc": "2026-09-23T10:31:46Z"} +{"event": "transfer", "phase": 1, "tick": 136, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5039170000600279, "seconds": 0.17201875000000655, "mbps": 0.047622715546995244, "utc": "2026-09-23T10:31:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:31:51Z"} +{"event": "transfer", "phase": 1, "tick": 137, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.044833999912953, "seconds": 0.4951529169998139, "mbps": 0.016544384004917576, "utc": "2026-09-23T10:31:51Z"} +{"event": "transfer", "phase": 1, "tick": 137, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0176669998145371, "seconds": 0.4824550419998559, "mbps": 0.016979820474137458, "utc": "2026-09-23T10:31:51Z"} +{"event": "transfer", "phase": 1, "tick": 138, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9714170000734157, "seconds": 0.16201933299998927, "mbps": 0.050561867206307676, "utc": "2026-09-23T10:31:56Z"} +{"event": "transfer", "phase": 1, "tick": 138, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6291249997047998, "seconds": 0.15957929199976206, "mbps": 0.05133498148376429, "utc": "2026-09-23T10:31:56Z"} +{"event": "transfer", "phase": 1, "tick": 139, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8900839998204901, "seconds": 0.6681540419999692, "mbps": 0.012260645726963032, "utc": "2026-09-23T10:32:01Z"} +{"event": "transfer", "phase": 1, "tick": 139, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.807249999979831, "seconds": 0.48915900000019974, "mbps": 0.016747110857607963, "utc": "2026-09-23T10:32:01Z"} +{"event": "transfer", "phase": 1, "tick": 140, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9027090000017779, "seconds": 0.16593999999986409, "mbps": 0.049367241171548205, "utc": "2026-09-23T10:32:06Z"} +{"event": "transfer", "phase": 1, "tick": 140, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8591659998273826, "seconds": 0.16575954099971568, "mbps": 0.04942098627079361, "utc": "2026-09-23T10:32:06Z"} +{"event": "transfer", "phase": 1, "tick": 141, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4837920000682061, "seconds": 0.4133417500001997, "mbps": 0.01981895126731341, "utc": "2026-09-23T10:32:11Z"} +{"event": "transfer", "phase": 1, "tick": 141, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4380000000310247, "seconds": 0.15911495799991826, "mbps": 0.05148478875257101, "utc": "2026-09-23T10:32:11Z"} +{"event": "transfer", "phase": 1, "tick": 142, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.743333000173152, "seconds": 0.16909045800002787, "mbps": 0.04844744107321922, "utc": "2026-09-23T10:32:16Z"} +{"event": "transfer", "phase": 1, "tick": 142, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.661209000099916, "seconds": 0.1831647089998114, "mbps": 0.044724772827326884, "utc": "2026-09-23T10:32:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:32:21Z"} +{"event": "transfer", "phase": 1, "tick": 143, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6779999998798303, "seconds": 0.4898134159998335, "mbps": 0.016724735853300483, "utc": "2026-09-23T10:32:21Z"} +{"event": "transfer", "phase": 1, "tick": 143, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9266669999306032, "seconds": 0.22526858300034291, "mbps": 0.036365479335338693, "utc": "2026-09-23T10:32:21Z"} +{"event": "transfer", "phase": 1, "tick": 144, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9668330003478331, "seconds": 0.2505421670002761, "mbps": 0.032697090865311196, "utc": "2026-09-23T10:32:26Z"} +{"event": "transfer", "phase": 1, "tick": 144, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 0.6317500001387089, "seconds": 4.367064458000186, "mbps": 19.20880280260714, "utc": "2026-09-23T10:32:26Z"} +{"event": "transfer", "phase": 1, "tick": 144, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7648330001757131, "seconds": 1.607681500000126, "mbps": 0.005095536647028256, "utc": "2026-09-23T10:32:26Z"} +{"event": "transfer", "phase": 1, "tick": 144, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 0.7524590000684839, "seconds": 3.0557750420002776, "mbps": 27.45165427658218, "utc": "2026-09-23T10:32:26Z"} +{"event": "transfer", "phase": 1, "tick": 145, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4883330002485309, "seconds": 0.5931221660002848, "mbps": 0.013811657141803848, "utc": "2026-09-23T10:32:31Z"} +{"event": "transfer", "phase": 1, "tick": 145, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7673340001019824, "seconds": 3.250670667000122, "mbps": 0.0025200953400671554, "utc": "2026-09-23T10:32:31Z"} +{"event": "transfer", "phase": 1, "tick": 146, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7213750000119035, "seconds": 0.48300583300033395, "mbps": 0.016960457701127463, "utc": "2026-09-23T10:32:36Z"} +{"event": "transfer", "phase": 1, "tick": 146, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7029589996818686, "seconds": 0.25358008399962273, "mbps": 0.03230537615884766, "utc": "2026-09-23T10:32:36Z"} +{"event": "transfer", "phase": 1, "tick": 147, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4967919999216974, "seconds": 0.4643568339997728, "mbps": 0.017641605334926563, "utc": "2026-09-23T10:32:41Z"} +{"event": "transfer", "phase": 1, "tick": 147, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4411250001794542, "seconds": 0.47393600000032166, "mbps": 0.017285034266218306, "utc": "2026-09-23T10:32:41Z"} +{"event": "transfer", "phase": 1, "tick": 148, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1976659998254036, "seconds": 0.48081291600010445, "mbps": 0.017037811854451558, "utc": "2026-09-23T10:32:46Z"} +{"event": "transfer", "phase": 1, "tick": 148, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0442919997331046, "seconds": 0.16707150000002002, "mbps": 0.049032899088109094, "utc": "2026-09-23T10:32:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:32:51Z"} +{"event": "transfer", "phase": 1, "tick": 149, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.35841599992636475, "seconds": 0.16431554099972345, "mbps": 0.04985529640202315, "utc": "2026-09-23T10:32:51Z"} +{"event": "transfer", "phase": 1, "tick": 149, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3100419999100268, "seconds": 0.1613784169999235, "mbps": 0.05076267416852827, "utc": "2026-09-23T10:32:51Z"} +{"event": "transfer", "phase": 1, "tick": 150, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8302080000248679, "seconds": 0.40992800000003626, "mbps": 0.01998399718974863, "utc": "2026-09-23T10:32:56Z"} +{"event": "transfer", "phase": 1, "tick": 150, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7199169999694277, "seconds": 8.326135374999922, "mbps": 0.0009838898397685585, "utc": "2026-09-23T10:33:01Z"} +{"event": "transfer", "phase": 1, "tick": 151, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5287080002744915, "seconds": 2.166723333000391, "mbps": 0.0037808241944097443, "utc": "2026-09-23T10:33:01Z"} +{"event": "transfer", "phase": 1, "tick": 151, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6140000000414148, "seconds": 2.446864750000259, "mbps": 0.0033479578305254235, "utc": "2026-09-23T10:33:01Z"} +{"event": "transfer", "phase": 1, "tick": 152, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4859579996482353, "seconds": 0.4234212079995814, "mbps": 0.01934716505746708, "utc": "2026-09-23T10:33:06Z"} +{"event": "transfer", "phase": 1, "tick": 152, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8561250001548615, "seconds": 0.4700356670000474, "mbps": 0.017428464636065958, "utc": "2026-09-23T10:33:06Z"} +{"event": "transfer", "phase": 1, "tick": 153, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1994999999842548, "seconds": 0.17320904100006373, "mbps": 0.047295452666336196, "utc": "2026-09-23T10:33:11Z"} +{"event": "transfer", "phase": 1, "tick": 153, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0844580001503346, "seconds": 0.16296995800030345, "mbps": 0.050266933246584905, "utc": "2026-09-23T10:33:11Z"} +{"event": "transfer", "phase": 1, "tick": 154, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0390409997853567, "seconds": 0.16482820800001718, "mbps": 0.049700230921634156, "utc": "2026-09-23T10:33:16Z"} +{"event": "transfer", "phase": 1, "tick": 154, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.0551659997872775, "seconds": 0.427689332999762, "mbps": 0.019154090055373343, "utc": "2026-09-23T10:33:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:33:21Z"} +{"event": "transfer", "phase": 1, "tick": 155, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.637416000245139, "seconds": 0.48255304100030116, "mbps": 0.016976372137285707, "utc": "2026-09-23T10:33:21Z"} +{"event": "transfer", "phase": 1, "tick": 155, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9173749999717984, "seconds": 0.48790345899988097, "mbps": 0.016790206851150853, "utc": "2026-09-23T10:33:21Z"} +{"event": "transfer", "phase": 1, "tick": 156, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5121670001244638, "seconds": 0.17525387500018041, "mbps": 0.04674361693852171, "utc": "2026-09-23T10:33:26Z"} +{"event": "transfer", "phase": 1, "tick": 156, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.4653329997381661, "seconds": 0.1671154169998772, "mbps": 0.049020013515605323, "utc": "2026-09-23T10:33:26Z"} +{"event": "transfer", "phase": 1, "tick": 157, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7870829999774287, "seconds": 0.4755607910001345, "mbps": 0.017225978581564105, "utc": "2026-09-23T10:33:31Z"} +{"event": "transfer", "phase": 1, "tick": 157, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8210000000872242, "seconds": 0.17887100000007194, "mbps": 0.04579836865672303, "utc": "2026-09-23T10:33:31Z"} +{"event": "transfer", "phase": 1, "tick": 158, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6224999997357372, "seconds": 0.4832029999997758, "mbps": 0.01695353712622604, "utc": "2026-09-23T10:33:36Z"} +{"event": "transfer", "phase": 1, "tick": 158, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.57479199995214, "seconds": 0.4832576250000784, "mbps": 0.016951620784045926, "utc": "2026-09-23T10:33:36Z"} +{"event": "transfer", "phase": 1, "tick": 159, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.2269999997442937, "seconds": 0.4718416669998078, "mbps": 0.017361756226593143, "utc": "2026-09-23T10:33:41Z"} +{"event": "transfer", "phase": 1, "tick": 159, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.1222919997635472, "seconds": 0.47889920799980246, "mbps": 0.017105895902845968, "utc": "2026-09-23T10:33:41Z"} +{"event": "transfer", "phase": 1, "tick": 160, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4571250001390581, "seconds": 0.15726983300010033, "mbps": 0.05208881985647416, "utc": "2026-09-23T10:33:46Z"} +{"event": "transfer", "phase": 1, "tick": 160, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3904159998455725, "seconds": 0.417397875000006, "mbps": 0.01962635770486345, "utc": "2026-09-23T10:33:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:33:51Z"} +{"event": "transfer", "phase": 1, "tick": 161, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0026660002040444, "seconds": 0.47786891599980663, "mbps": 0.017142776451279613, "utc": "2026-09-23T10:33:51Z"} +{"event": "transfer", "phase": 1, "tick": 161, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8542079999642738, "seconds": 0.1653748749999977, "mbps": 0.049535940692321694, "utc": "2026-09-23T10:33:51Z"} +{"event": "transfer", "phase": 1, "tick": 162, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8119999997688865, "seconds": 0.16560420799987696, "mbps": 0.04946734203762555, "utc": "2026-09-23T10:33:56Z"} +{"event": "transfer", "phase": 1, "tick": 162, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7843339999453747, "seconds": 0.1665920840000581, "mbps": 0.049174005170600686, "utc": "2026-09-23T10:33:56Z"} +{"event": "transfer", "phase": 1, "tick": 163, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.5332499999894935, "seconds": 0.15592108300006657, "mbps": 0.05253939904968786, "utc": "2026-09-23T10:34:01Z"} +{"event": "transfer", "phase": 1, "tick": 163, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.43016700010412023, "seconds": 0.16537079199997606, "mbps": 0.049537163733249734, "utc": "2026-09-23T10:34:01Z"} +{"event": "transfer", "phase": 1, "tick": 164, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.4005840000900207, "seconds": 0.47728937500005486, "mbps": 0.017163591793760456, "utc": "2026-09-23T10:34:06Z"} +{"event": "transfer", "phase": 1, "tick": 164, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5030829997849651, "seconds": 0.4828136659998563, "mbps": 0.016967208214861175, "utc": "2026-09-23T10:34:06Z"} +{"event": "transfer", "phase": 1, "tick": 165, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.0232909999103867, "seconds": 0.4801852499999768, "mbps": 0.0170600825410618, "utc": "2026-09-23T10:34:11Z"} +{"event": "transfer", "phase": 1, "tick": 165, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.6372499999306456, "seconds": 0.1653931669998201, "mbps": 0.04953046216237525, "utc": "2026-09-23T10:34:11Z"} +{"event": "transfer", "phase": 1, "tick": 166, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8632080002826115, "seconds": 0.16760941600023216, "mbps": 0.048875535727590944, "utc": "2026-09-23T10:34:16Z"} +{"event": "transfer", "phase": 1, "tick": 166, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8860840002853365, "seconds": 0.1759582920003595, "mbps": 0.04655648737476528, "utc": "2026-09-23T10:34:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:34:21Z"} +{"event": "transfer", "phase": 1, "tick": 167, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.6457500003307359, "seconds": 0.18181433400013702, "mbps": 0.045056953540273816, "utc": "2026-09-23T10:34:21Z"} +{"event": "transfer", "phase": 1, "tick": 167, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5739580001318245, "seconds": 0.42345287499983897, "mbps": 0.019345718221899226, "utc": "2026-09-23T10:34:21Z"} +{"event": "transfer", "phase": 1, "tick": 168, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9595419996912824, "seconds": 0.4592435829999886, "mbps": 0.01783802823435467, "utc": "2026-09-23T10:34:26Z"} +{"event": "transfer", "phase": 1, "tick": 168, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8393329999307753, "seconds": 0.4753677499998048, "mbps": 0.017232973839734322, "utc": "2026-09-23T10:34:26Z"} +{"event": "transfer", "phase": 1, "tick": 169, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8660000003146706, "seconds": 0.4261479589999908, "mbps": 0.01922337025671447, "utc": "2026-09-23T10:34:31Z"} +{"event": "transfer", "phase": 1, "tick": 169, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6899999998495332, "seconds": 0.1678332080000473, "mbps": 0.04881036415628599, "utc": "2026-09-23T10:34:31Z"} +{"event": "transfer", "phase": 1, "tick": 170, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9029590000864118, "seconds": 0.1748587500001122, "mbps": 0.04684924260292804, "utc": "2026-09-23T10:34:36Z"} +{"event": "transfer", "phase": 1, "tick": 170, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5682089999936579, "seconds": 0.16192695900008403, "mbps": 0.050590711087186845, "utc": "2026-09-23T10:34:36Z"} +{"event": "transfer", "phase": 1, "tick": 171, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7524160000684788, "seconds": 0.1672924999998031, "mbps": 0.04896812469183998, "utc": "2026-09-23T10:34:41Z"} +{"event": "transfer", "phase": 1, "tick": 171, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7185829999798443, "seconds": 0.4013137080000888, "mbps": 0.02041295833333006, "utc": "2026-09-23T10:34:41Z"} +{"event": "transfer", "phase": 1, "tick": 172, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7326669997382851, "seconds": 0.41353633399967293, "mbps": 0.019809625724462893, "utc": "2026-09-23T10:34:46Z"} +{"event": "transfer", "phase": 1, "tick": 172, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3992500001004373, "seconds": 0.15814616600027875, "mbps": 0.05180018085285457, "utc": "2026-09-23T10:34:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:34:51Z"} +{"event": "transfer", "phase": 1, "tick": 173, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7347910000135016, "seconds": 0.17248825000024226, "mbps": 0.04749309010896971, "utc": "2026-09-23T10:34:51Z"} +{"event": "transfer", "phase": 1, "tick": 173, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.1428749999140564, "seconds": 0.18187499999976353, "mbps": 0.04504192439868399, "utc": "2026-09-23T10:34:51Z"} +{"event": "transfer", "phase": 1, "tick": 174, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.690875000145752, "seconds": 0.167064499999924, "mbps": 0.04903495356586065, "utc": "2026-09-23T10:34:56Z"} +{"event": "transfer", "phase": 1, "tick": 174, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.577333000364888, "seconds": 0.41085541600023134, "mbps": 0.01993888769862386, "utc": "2026-09-23T10:34:56Z"} +{"event": "transfer", "phase": 1, "tick": 175, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.1075829997935216, "seconds": 0.17493587499984642, "mbps": 0.046828587904037364, "utc": "2026-09-23T10:35:01Z"} +{"event": "transfer", "phase": 1, "tick": 175, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9588750003786117, "seconds": 0.1698690420003004, "mbps": 0.04822538529407562, "utc": "2026-09-23T10:35:01Z"} +{"event": "transfer", "phase": 1, "tick": 176, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.8240409997597453, "seconds": 0.16902674999982992, "mbps": 0.04846570143488083, "utc": "2026-09-23T10:35:06Z"} +{"event": "transfer", "phase": 1, "tick": 176, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7384590003312042, "seconds": 0.16865987500023039, "mbps": 0.04857112576413809, "utc": "2026-09-23T10:35:06Z"} +{"event": "transfer", "phase": 1, "tick": 177, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.563749999855645, "seconds": 0.16775162499970975, "mbps": 0.04883410220326733, "utc": "2026-09-23T10:35:11Z"} +{"event": "transfer", "phase": 1, "tick": 177, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.5169159999240946, "seconds": 0.17046345800008567, "mbps": 0.04805722056862113, "utc": "2026-09-23T10:35:11Z"} +{"event": "transfer", "phase": 1, "tick": 178, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9902920000968152, "seconds": 0.15920220799989693, "mbps": 0.05145657276314475, "utc": "2026-09-23T10:35:16Z"} +{"event": "transfer", "phase": 1, "tick": 178, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9797499997148407, "seconds": 0.48006729200005793, "mbps": 0.01706427439759635, "utc": "2026-09-23T10:35:16Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:35:21Z"} +{"event": "transfer", "phase": 1, "tick": 179, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.5772920000927115, "seconds": 0.48763583299978563, "mbps": 0.016799421711085782, "utc": "2026-09-23T10:35:21Z"} +{"event": "transfer", "phase": 1, "tick": 179, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.9269160000258125, "seconds": 0.16068908299985196, "mbps": 0.05098043903833559, "utc": "2026-09-23T10:35:21Z"} +{"event": "transfer", "phase": 1, "tick": 180, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9059580002030998, "seconds": 0.1659429999999702, "mbps": 0.04936634868600345, "utc": "2026-09-23T10:35:26Z"} +{"event": "transfer", "phase": 1, "tick": 180, "mode": "stock", "port": 32181, "size": 10485760, "success": true, "socks_handshake_ms": 0.9366660001433047, "seconds": 1.3318272910000815, "mbps": 62.98570435285882, "utc": "2026-09-23T10:35:26Z"} +{"event": "transfer", "phase": 1, "tick": 180, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8889169998838042, "seconds": 0.16153562499994223, "mbps": 0.050713271453296634, "utc": "2026-09-23T10:35:26Z"} +{"event": "transfer", "phase": 1, "tick": 180, "mode": "modified", "port": 32182, "size": 10485760, "success": true, "socks_handshake_ms": 0.6972500000301807, "seconds": 3.514096417000019, "mbps": 23.871308594205697, "utc": "2026-09-23T10:35:26Z"} +{"event": "transfer", "phase": 1, "tick": 181, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.49274999992121593, "seconds": 0.17323045800003456, "mbps": 0.04728960538797609, "utc": "2026-09-23T10:35:31Z"} +{"event": "transfer", "phase": 1, "tick": 181, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.3973749999204301, "seconds": 0.17558074999988094, "mbps": 0.04665659532725287, "utc": "2026-09-23T10:35:31Z"} +{"event": "transfer", "phase": 1, "tick": 182, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.924707999729435, "seconds": 0.18207924999978786, "mbps": 0.044991397976483015, "utc": "2026-09-23T10:35:36Z"} +{"event": "transfer", "phase": 1, "tick": 182, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8294159997603856, "seconds": 0.4215712079999321, "mbps": 0.019432067096957245, "utc": "2026-09-23T10:35:36Z"} +{"event": "transfer", "phase": 1, "tick": 183, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7576660000268021, "seconds": 0.17200162500012084, "mbps": 0.047627457008003526, "utc": "2026-09-23T10:35:41Z"} +{"event": "transfer", "phase": 1, "tick": 183, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6739579998793488, "seconds": 0.17053416599992488, "mbps": 0.048037294767100266, "utc": "2026-09-23T10:35:41Z"} +{"event": "transfer", "phase": 1, "tick": 184, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7107500000529399, "seconds": 0.17038604100025623, "mbps": 0.04807905595968205, "utc": "2026-09-23T10:35:46Z"} +{"event": "transfer", "phase": 1, "tick": 184, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.6963329997233814, "seconds": 0.1609581249999792, "mbps": 0.050895225077957754, "utc": "2026-09-23T10:35:46Z"} +{"event": "health", "phase": 1, "healthy": true, "local_transfers": [true, true], "utc": "2026-09-23T10:35:51Z"} +{"event": "transfer", "phase": 1, "tick": 185, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.7757080002193106, "seconds": 0.4724336660001427, "mbps": 0.01734000049013765, "utc": "2026-09-23T10:35:51Z"} +{"event": "transfer", "phase": 1, "tick": 185, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7855829999243724, "seconds": 0.17188133299987385, "mbps": 0.04766078931914038, "utc": "2026-09-23T10:35:51Z"} +{"event": "transfer", "phase": 1, "tick": 186, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9056250000867294, "seconds": 0.16817954199996166, "mbps": 0.04870984843092192, "utc": "2026-09-23T10:35:56Z"} +{"event": "transfer", "phase": 1, "tick": 186, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.2709170000562153, "seconds": 0.1716691249998803, "mbps": 0.04771970498484053, "utc": "2026-09-23T10:35:56Z"} +{"event": "transfer", "phase": 1, "tick": 187, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.916916999813111, "seconds": 0.4818930419996832, "mbps": 0.01699962291633459, "utc": "2026-09-23T10:36:01Z"} +{"event": "transfer", "phase": 1, "tick": 187, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8275830000457063, "seconds": 0.1733297920000041, "mbps": 0.04726250407085128, "utc": "2026-09-23T10:36:01Z"} +{"event": "transfer", "phase": 1, "tick": 188, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.9130409998761024, "seconds": 0.41265341600001193, "mbps": 0.019852010627726787, "utc": "2026-09-23T10:36:06Z"} +{"event": "transfer", "phase": 1, "tick": 188, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.8171250001396402, "seconds": 0.48201525000013135, "mbps": 0.016995312907626407, "utc": "2026-09-23T10:36:06Z"} +{"event": "transfer", "phase": 1, "tick": 189, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 0.604000000294036, "seconds": 0.43997183300007237, "mbps": 0.01861937375431634, "utc": "2026-09-23T10:36:11Z"} +{"event": "transfer", "phase": 1, "tick": 189, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 0.7320830000026035, "seconds": 0.16823245800014774, "mbps": 0.04869452718804599, "utc": "2026-09-23T10:36:11Z"} +{"event": "transfer", "phase": 1, "tick": 190, "mode": "stock", "port": 32181, "size": 1024, "success": true, "socks_handshake_ms": 1.4180419998410798, "seconds": 0.4748823340000854, "mbps": 0.017250589069077744, "utc": "2026-09-23T10:36:16Z"} +{"event": "transfer", "phase": 1, "tick": 190, "mode": "modified", "port": 32182, "size": 1024, "success": true, "socks_handshake_ms": 1.74925000010262, "seconds": 0.162964374999774, "mbps": 0.05026865534268677, "utc": "2026-09-23T10:36:16Z"} +{"event": "cleanup", "remote_exit": 255, "capture_retrieved": true, "utc": "2026-09-23T10:36:30Z"} diff --git a/docs/measurements/printable-salt-2026-09-23/ssh-path.json b/docs/measurements/printable-salt-2026-09-23/ssh-path.json new file mode 100644 index 000000000..0e0b2def7 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/ssh-path.json @@ -0,0 +1,7 @@ +{ + "last_matched_request_utc": "2026-09-23T10:50:38.585912+00:00", + "first_unseen_request_utc": "2026-09-23T10:50:43.584421+00:00", + "subsequent_unseen_packets": 10, + "first_unseen_payload_bytes": 52, + "explanation": "After this point, captured client SSH payloads were absent from the server capture. This supports forward-path loss, without identifying its cause or actor." +} diff --git a/docs/measurements/printable-salt-2026-09-23/synthetic-encodings.json b/docs/measurements/printable-salt-2026-09-23/synthetic-encodings.json new file mode 100644 index 000000000..9da80ae83 --- /dev/null +++ b/docs/measurements/printable-salt-2026-09-23/synthetic-encodings.json @@ -0,0 +1,102 @@ +[ + { + "mode": "raw", + "synthetic": true, + "source_bytes": 1048576, + "wire_bytes": 1048576, + "overhead_fraction": 0.0, + "codec_roundtrip_mib_s": null, + "historical_exemption_samples": 2000, + "historical_exemption_passes": { + "popcount": 0, + "prefix": 1, + "half": 4, + "run": 0, + "any": 5 + }, + "byte_entropy": 7.9998218311327545, + "alphabet_size": 256, + "printable_fraction": 0.37133216857910156, + "ones_per_byte": 3.9997339248657227 + }, + { + "mode": "printable6", + "synthetic": true, + "source_bytes": 1048576, + "wire_bytes": 1048576, + "overhead_fraction": 0.0, + "codec_roundtrip_mib_s": null, + "historical_exemption_samples": 2000, + "historical_exemption_passes": { + "popcount": 0, + "prefix": 2000, + "half": 54, + "run": 0, + "any": 2000 + }, + "byte_entropy": 7.999821825117097, + "alphabet_size": 256, + "printable_fraction": 0.3713359832763672, + "ones_per_byte": 3.999736785888672 + }, + { + "mode": "base64", + "synthetic": true, + "source_bytes": 1048576, + "wire_bytes": 1398336, + "overhead_fraction": 0.33355712890625, + "codec_roundtrip_mib_s": 418.4611676388659, + "historical_exemption_samples": 2000, + "historical_exemption_passes": { + "popcount": 0, + "prefix": 2000, + "half": 2000, + "run": 2000, + "any": 2000 + }, + "byte_entropy": 6.0012302038144885, + "alphabet_size": 66, + "printable_fraction": 0.9999542313149343, + "ones_per_byte": 3.7805248523959905 + }, + { + "mode": "base85", + "synthetic": true, + "source_bytes": 1048576, + "wire_bytes": 1310784, + "overhead_fraction": 0.25006103515625, + "codec_roundtrip_mib_s": 12.200986906081184, + "historical_exemption_samples": 2000, + "historical_exemption_passes": { + "popcount": 0, + "prefix": 2000, + "half": 2000, + "run": 2000, + "any": 2000 + }, + "byte_entropy": 6.408921116110362, + "alphabet_size": 86, + "printable_fraction": 0.9999511742590694, + "ones_per_byte": 3.799169809823739 + }, + { + "mode": "lowpop85", + "synthetic": true, + "source_bytes": 1048576, + "wire_bytes": 1310784, + "overhead_fraction": 0.25006103515625, + "codec_roundtrip_mib_s": 8.75479461798384, + "historical_exemption_samples": 2000, + "historical_exemption_passes": { + "popcount": 2000, + "prefix": 13, + "half": 173, + "run": 0, + "any": 2000 + }, + "byte_entropy": 6.408921116110362, + "alphabet_size": 86, + "printable_fraction": 0.4492898906303403, + "ones_per_byte": 2.444301273131195 + } +] diff --git a/docs/printable-salt.md b/docs/printable-salt.md new file mode 100644 index 000000000..6baa6d7e1 --- /dev/null +++ b/docs/printable-salt.md @@ -0,0 +1,149 @@ +# Experimental printable TCP salt + +`ss-local --printable-salt` chooses a prefix length uniformly from 6–12 bytes +for each outgoing TCP salt, then replaces that prefix with independent, uniformly +sampled printable ASCII bytes (`0x20`–`0x7e`). +It is disabled by default and accepts only `chacha20-ietf-poly1305` and +`aes-256-gcm`, including when the cipher comes from a configuration file or URL. +Other ciphers fail at startup. Enable it with the CLI flag or the +`printable_salt` configuration key; either one turns it on, and the key is +ignored by the other binaries. + +```sh +ss-local -c client.json --printable-salt +``` + +```json +{ "server": "example.com", "server_port": 8388, "password": "...", + "method": "chacha20-ietf-poly1305", "printable_salt": true } +``` + +The salt remains 32 bytes. The remaining 20–26 bytes retain their original secure +random values. Length sampling uses libsodium `6 + randombytes_uniform(7)`; +character sampling uses `randombytes_uniform(95)` immediately +before key derivation and transmission on the first nonempty TCP encryption call. +Empty writes do not consume the salt; later writes do not change it. For a selected length `L`, the conditional salt entropy +is `(32 - L) * 8 + L * log2(95)`, at least **238.84 bits** (at `L = 12`). +This is also a conservative min-entropy bound for the mixture; the random length +is not an independent secret field whose entropy can simply be added. Salt uniqueness +remains essential. There are no extra framing bytes, messages, or round trips. + +UDP salt generation, server responses, authenticated framing, replay rejection, +and AEAD-2022 are unchanged. No SIP003 plugin or fixed protocol marker is added. +This is not TLS impersonation, nor a promise of censorship resistance. + +The prefix introduces a statistical fingerprint: every enabled connection starts +with six printable bytes, versus `(95 / 256)^6`, approximately 0.26%, for a +uniformly random salt. The bytes vary independently, but the printable property +is fixed. The constrained span now varies; the untouched tail may also start +with printable bytes, so there is no explicit boundary marker. The 6–12 range +is an experimental tradeoff, not an optimized or measured defense. Increasing +the span can strengthen other ASCII statistics even as the boundary varies. A classifier could combine it with subsequent encrypted bytes, packet +lengths, endpoint information, or probing. High salt entropy does not imply low +detectability. + +## Rationale and limits + +The [USENIX Security 2023 study](https://gfw.report/publications/usenixsecurity23/en/) +reported an exemption for six leading printable bytes in the first TCP payload. +Its [follow-up](https://github.com/gfw-report/usenixsecurity23-artifact) reports that +the measured dynamic blocking stopped in March 2023. This is historical evidence; +present-day behavior must be measured on the route of interest. +[Outline prefixing](https://developer.getoutline.org/vpn/advanced/prefixing/) +provides related deployment precedent. The +[AEAD specification](https://shadowsocks.org/doc/aead.html) describes salt-based +key derivation and the requirement for unique salts. + +An application write does not determine TCP packet boundaries. Packet captures +must establish whether the actual first transmitted payload contains all six +bytes. This experiment does not establish protection against every active probe, +long-term blocking, or other classifiers. + +## Local reproduction + +Build an independent stock checkout from the base revision before applying this +change, then configure/build this branch with the same toolchain: + +```sh +cmake -S . -B build-printable -G Ninja -DSS_DEPENDENCY_MODE=system \ + -DWITH_STATIC=OFF -DWITH_DOC_MAN=OFF -DWITH_DOC_HTML=OFF +cmake --build build-printable --parallel +ctest --test-dir build-printable --output-on-failure +python3 tests/interop.py --self --bin build-printable/bin \ + --server-bin build-printable-stock/bin/ss-server --printable-salt +python3 tests/interop.py --bin build-printable/bin --printable-salt +python3 tests/interop.py --self --bin build-printable/bin +python3 tests/stress_test.py --bin build-printable/bin --size 10 +uvx ruff==0.15.6 check --select E9,F63,F7,F82 tests scripts +python3 scripts/check_cli_docs.py +python3 -m unittest discover -s tests -p test_cli_docs.py +``` + +The crypto tests exercise disabled/enabled behavior, empty first writes, unchanged +salt tails, exact framing length, subsequent writes, byte-at-a-time decryption, +tampering, and replay rejection. CLI tests check cipher rejection and local-only +exposure. Interoperability tests verify concurrent bidirectional TCP and UDP; +the default full suite covers all supported AEAD-2022 variants too. + +## Route experiment + +`tests/printable_salt_experiment.py` runs two 30-minute phases against isolated +instances of a stock remote `ssserver`. It requires Linux with Python, tcpdump, +`/usr/local/bin/ssserver` and `/usr/local/bin/sslocal`, verified SSH host trust, +two unused reachable high ports, and local passwordless access to tcpdump through +sudo. Inspect listeners and firewall rules first. The runner does not modify +firewalls or existing services. Its remote echo origin binds to loopback only. + +```sh +python3 tests/printable_salt_experiment.py \ + --host root@SERVER --host-key-alias VERIFIED_KNOWN_HOST \ + --address SERVER_IPV4 --interface en0 \ + --stock-bin build-printable-stock/bin/ss-local \ + --modified-bin build-printable/bin/ss-local \ + --ports 32181 32182 --output build-artifacts/printable-salt/route +python3 tests/check_printable_pcap.py \ + build-artifacts/printable-salt/route/client.pcap --ports 32181 32182 \ + --events build-artifacts/printable-salt/route/events.jsonl +``` + +Fresh credentials are generated for each run. Proxy environment variables are +removed from child processes. Clients swap server ports between phases. Each +mode attempts a verified 1 KiB echo transfer every five seconds and ten 10 MiB +echo transfers per phase. Upload and download run concurrently. Every 30 seconds, +an SSH round trip verifies management health, process health, local listeners, +and a verified transfer through each server using server-local stock clients. +The run stops on a failed health check. Remote processes have a 65-minute watchdog +and are stopped when their controlling SSH input closes or no control command +arrives for 60 seconds. Normal cleanup removes +experimental processes and temporary configs and retrieves packet captures. + +JSONL results record transfer success, error/timeout/reset messages, integrity +failures, elapsed time, and effective payload throughput. `socks_handshake_ms` is +local SOCKS setup time, **not** remote connection latency. Use small-transfer +completion time for an end-to-end latency measure. Throughput is one-way payload +bytes divided by bidirectional echo completion time; it is not link capacity. +Large tests share the route with each other and the scheduled small tests. + +Captures use a 160-byte snapshot to retain TCP headers and salt prefixes while +limiting size. Both packet captures and the raw results remain in a private local +output directory; do not publish raw captures without reviewing address metadata. +The packet checker accepts a first payload only after observing its SYN, checks +its sequence number, and evaluates bytes in the packet itself. + +Call a result promising only when modified traffic repeatedly succeeds while +stock traffic fails, including after crossover, with healthy server-local +controls. Persistent port blocking makes crossover inconclusive. If both work, +report compatibility and measured performance only. If both fail, investigate +captured failures before choosing another modification. A one-hour run cannot +establish long-term GFW resistance. + +## Additional experiments + +See [outer-transport experiments](encoding-experiments.md) for Base85, +low-popcount encoding, and verified TLS prototypes. These require matching relays +at both endpoints and are separate from the production CLI flag. + +Recorded results: [2026-09-23 measurements and limitations](measurements/printable-salt-2026-09-23/README.md). + +The archived 2026-09-23 measurements used the original fixed six-byte prefix. +They do not evaluate this variable-length revision. diff --git a/src/aead.c b/src/aead.c index 5d194f91e..832a840e2 100644 --- a/src/aead.c +++ b/src/aead.c @@ -592,6 +592,15 @@ aead_encrypt(buffer_t *plaintext, cipher_ctx_t *cipher_ctx, size_t capacity) ciphertext->len = out_len; if (!cipher_ctx->init) { + if (cipher_ctx->printable_salt) { + /* Only ss-local TCP opts in, after ctx_init. Keep UDP salt + * generation untouched and derive the key from the final salt. */ + /* Vary the constrained span without adding a delimiter or marker. */ + size_t prefix_len = 6 + randombytes_uniform(7); + for (size_t i = 0; i < prefix_len; i++) { + cipher_ctx->salt[i] = 0x20 + randombytes_uniform(95); + } + } memcpy(ciphertext->data, cipher_ctx->salt, salt_len); aead_cipher_ctx_set_key(cipher_ctx, 1); cipher_ctx->init = 1; diff --git a/src/common.h b/src/common.h index 73cccbe2e..69e473881 100644 --- a/src/common.h +++ b/src/common.h @@ -61,6 +61,7 @@ enum { GETOPT_VAL_REUSE_PORT, GETOPT_VAL_FAST_OPEN, GETOPT_VAL_NODELAY, + GETOPT_VAL_PRINTABLE_SALT, GETOPT_VAL_ACL, GETOPT_VAL_MTU, GETOPT_VAL_MPTCP, diff --git a/src/crypto.h b/src/crypto.h index ef9a06a7a..f2dbe1200 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -116,6 +116,7 @@ typedef struct { typedef struct cipher_ctx { uint32_t init; uint64_t counter; + uint8_t printable_salt; /* opt-in client TCP salt prefix; never used by UDP */ cipher_evp_t *evp; aes256gcm_ctx *aes256gcm_ctx; cipher_t *cipher; diff --git a/src/jconf.c b/src/jconf.c index bed2887a5..0a5d6fbc6 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -451,6 +451,11 @@ read_jconf(const char *file) value, json_boolean, "invalid config file: option 'no_delay' must be a boolean"); conf.no_delay = value->u.boolean; + } else if (strcmp(name, "printable_salt") == 0) { + check_json_value_type( + value, json_boolean, + "invalid config file: option 'printable_salt' must be a boolean"); + conf.printable_salt = value->u.boolean; } else if (strcmp(name, "tcp_tproxy") == 0) { check_json_value_type( value, json_boolean, diff --git a/src/jconf.h b/src/jconf.h index d39c043d3..1a92f1fb5 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -86,6 +86,7 @@ typedef struct { int mptcp; int ipv6_first; int no_delay; + int printable_salt; int tcp_tproxy; char *workdir; char *acl; diff --git a/src/local.c b/src/local.c index 3aec66a1e..fba046d01 100644 --- a/src/local.c +++ b/src/local.c @@ -102,6 +102,7 @@ static int mode = TCP_ONLY; static int ipv6first = 0; int fast_open = 0; static int no_delay = 0; +static int printable_salt = 0; static int udp_fd = 0; static int ret_val = 0; @@ -1265,6 +1266,7 @@ new_server(int fd) server->d_ctx = ss_malloc(sizeof(cipher_ctx_t)); crypto->ctx_init(crypto->cipher, server->e_ctx, 1); crypto->ctx_init(crypto->cipher, server->d_ctx, 0); + server->e_ctx->printable_salt = printable_salt; cipher_ctx_pair(server->e_ctx, server->d_ctx); ss_io_init(&server->recv_ctx->io, server_recv_cb, fd, SS_READ); @@ -1653,6 +1655,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`. \snippet{doc} utils.c cli_long_password \snippet{doc} utils.c cli_long_key \snippet{doc} utils.c cli_long_server_url +\snippet{doc} utils.c cli_long_printable_salt \snippet{doc} utils.c cli_long_help [cli-options] */ static struct option long_options[] = { @@ -1684,6 +1687,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`. { "tcp-outgoing-sndbuf", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_SNDBUF }, { "tcp-outgoing-rcvbuf", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_RCVBUF }, { "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN }, + { "printable-salt", no_argument, NULL, GETOPT_VAL_PRINTABLE_SALT }, { "no-delay", no_argument, NULL, GETOPT_VAL_NODELAY }, { "acl", required_argument, NULL, GETOPT_VAL_ACL }, { "mtu", required_argument, NULL, GETOPT_VAL_MTU }, @@ -1740,6 +1744,9 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`. if (mptcp) LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream"); break; + case GETOPT_VAL_PRINTABLE_SALT: + printable_salt = 1; + break; case GETOPT_VAL_NODELAY: no_delay = 1; LOGI("enable TCP no-delay"); @@ -1981,6 +1988,9 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`. if (no_delay == 0) { no_delay = conf->no_delay; } + if (printable_salt == 0) { + printable_salt = conf->printable_salt; + } #ifdef HAVE_SETRLIMIT if (nofile == 0) { nofile = conf->nofile; @@ -2081,6 +2091,13 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`. if (method == NULL) { method = "chacha20-ietf-poly1305"; } + if (printable_salt && strcmp(method, "chacha20-ietf-poly1305") != 0 + && strcmp(method, "aes-256-gcm") != 0) { + FATAL("--printable-salt (printable_salt) requires chacha20-ietf-poly1305 or aes-256-gcm"); + } + if (printable_salt) { + LOGI("enable experimental printable TCP salt"); + } if (timeout == NULL) { timeout = "60"; diff --git a/src/utils.c b/src/utils.c index 52aca2e3e..6648b2401 100644 --- a/src/utils.c +++ b/src/utils.c @@ -427,6 +427,16 @@ Enable UDP relay and disable TCP relay. Resolve hostname to IPv6 address first. [cli_short_6] */ +/* [cli_long_printable_salt] +\par `--printable-salt` +Experimental client TCP salt camouflage, disabled by default. Config key: `"printable_salt": true` +(ss-local only). Randomly choose 6-12 leading +salt bytes and sample each as printable ASCII (0x20-0x7e). Requires chacha20-ietf-poly1305 or +aes-256-gcm. Adds no framing bytes; leaves UDP and server responses unchanged. +The 32-byte salt retains at least 238 bits of entropy. Salt uniqueness +remains essential. This is not TLS impersonation or proven censorship resistance. +[cli_long_printable_salt] */ + /* [cli_long_fast_open] \par `--fast-open` Enable TCP Fast Open where supported by the operating system. @@ -678,6 +688,9 @@ usage(void) cli_help_option("--fast-open", "Enable TCP Fast Open where supported."); cli_help_option("--reuse-port", "Enable port reuse where supported."); cli_help_option("--no-delay", "Enable TCP_NODELAY."); +#ifdef MODULE_LOCAL + cli_help_option("--printable-salt", "Experimental printable TCP salt (chacha20-ietf-poly1305/aes-256-gcm only)."); +#endif #if !defined(MODULE_MANAGER) && (!defined(MODULE_REMOTE) || defined(__linux__)) cli_help_option("--mptcp", "Enable Multipath TCP where supported."); #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d8da7e3f6..d11fd6364 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -222,5 +222,21 @@ if(SS_BUILD_EXECUTABLES AND NOT CMAKE_CROSSCOMPILING) COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_cli.py --bin-dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set_tests_properties(test_cli PROPERTIES LABELS "integration" TIMEOUT 60) + if(UNIX) + add_test(NAME test_experiment_supervisor + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/experiments/test_supervisor.py + --bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set_tests_properties(test_experiment_supervisor PROPERTIES + LABELS "integration" TIMEOUT 30) + endif() + add_test(NAME test_experimental_transports + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/experiments/test_transport.py) + set_tests_properties(test_experimental_transports PROPERTIES + LABELS "integration" TIMEOUT 30) + add_test(NAME test_printable_salt_interop + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/interop.py + --self --printable-salt --bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set_tests_properties(test_printable_salt_interop PROPERTIES + LABELS "integration" TIMEOUT 90) endif() endif() diff --git a/tests/check_printable_pcap.py b/tests/check_printable_pcap.py new file mode 100644 index 000000000..f503fa75b --- /dev/null +++ b/tests/check_printable_pcap.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Summarize actual first TCP payloads in a tcpdump pcap (IPv4). + +Requires a captured SYN before accepting a flow's first payload. Never treats +application writes or socket recv boundaries as TCP packet boundaries. +""" +import argparse +from collections import Counter +import json +from pathlib import Path +import socket +import struct + + +def initial_payloads(path, ports, require_sequence=False): + with Path(path).open('rb') as stream: + header = stream.read(24) + formats = {b'\xd4\xc3\xb2\xa1': ('<', 1e6), b'\xa1\xb2\xc3\xd4': ('>', 1e6), + b'\x4d\x3c\xb2\xa1': ('<', 1e9), b'\xa1\xb2\x3c\x4d': ('>', 1e9)} + endian, scale = formats[header[:4]] + link = struct.unpack(endian + 'I', header[20:24])[0] + offset = {0: 4, 1: 14, 113: 16, 276: 20}[link] + flows = {} + while raw := stream.read(16): + sec, frac, length, _ = struct.unpack(endian + 'IIII', raw) + packet = stream.read(length) + ip = packet[offset:] + if len(ip) < 20 or ip[0] >> 4 != 4 or ip[9] != 6: + continue + ihl = (ip[0] & 15) * 4 + total_length = int.from_bytes(ip[2:4], 'big') + tcp = ip[ihl:total_length] + if len(tcp) < 20: + continue + src, dst, seq = struct.unpack('!HHI', tcp[:8]) + if dst not in ports: + continue + flow = (socket.inet_ntoa(ip[12:16]), src, socket.inet_ntoa(ip[16:20]), dst) + flags = tcp[13] + if flags & 2 and not flags & 16: + flows.setdefault(flow, (seq + 1) & 0xffffffff) + payload = tcp[(tcp[12] >> 4) * 4:] + if payload and flow in flows: + expected = flows[flow] + if require_sequence and seq != expected: + continue + flows.pop(flow) + # Require sequence correspondence: dropped first data cannot pass. + yield dict(time=sec + frac / scale, source=flow[0], port=dst, + sequence_ok=seq == expected, prefix=payload[:6].hex(), + payload_hex=payload.hex(), + payload_complete=len(ip) >= total_length, + printable=len(payload) >= 6 and all(0x20 <= b <= 0x7e for b in payload[:6])) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('pcap') + parser.add_argument('--ports', nargs='+', type=int, required=True) + parser.add_argument('--events', help='crossover JSONL to attribute port/mode by phase') + args = parser.parse_args() + events = [json.loads(line) for line in Path(args.events).read_text().splitlines()] if args.events else [] + boundary = None + ports = args.ports + if events: + from datetime import datetime + boundary = next((datetime.fromisoformat(e['utc'].replace('Z', '+00:00')).timestamp() + for e in events if e['event'] == 'phase_complete' and e['phase'] == 1), None) + counts = Counter() + for flow in initial_payloads(args.pcap, ports): + if flow['source'].startswith('127.'): + continue + phase = 2 if boundary is not None and flow['time'] >= boundary else 1 + mode = 'modified' if flow['port'] == ports[1 if phase == 1 else 0] else 'stock' + counts[f"phase{phase}/{mode}/total"] += 1 + counts[f"phase{phase}/{mode}/printable"] += flow['printable'] + counts[f"phase{phase}/{mode}/sequence_ok"] += flow['sequence_ok'] + print(json.dumps(dict(counts), indent=2, sort_keys=True)) + + +if __name__ == '__main__': + main() diff --git a/tests/experiments/analyze.py b/tests/experiments/analyze.py new file mode 100644 index 000000000..8376d4722 --- /dev/null +++ b/tests/experiments/analyze.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Summarize transport screening and captured first TCP payloads.""" +import argparse +from collections import Counter, defaultdict +from datetime import datetime +import json +import hashlib +from pathlib import Path +import statistics +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from check_printable_pcap import initial_payloads # noqa: E402 +from benchmark import exemptions # noqa: E402 + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('directory') + args = parser.parse_args() + root = Path(args.directory) + protocol = json.loads((root / 'protocol.json').read_text()) + events = [json.loads(line) for line in (root / 'events.jsonl').read_text().splitlines()] + phases = [(datetime.fromisoformat(e['utc'].replace('Z', '+00:00')).timestamp(), e) + for e in events if e['event'] == 'phase_start'] + summary = dict(protocol=protocol, complete=any(e['event'] == 'complete' for e in events), + aborts=[e for e in events if e['event'] == 'aborted'], + completed_phases=sum(e['event'] == 'phase_complete' for e in events), + outcome_logging_limit='Runs before the durable-outcome fix can omit in-flight outcomes at abort.', + health_checks=sum(e['event'] in ('health', 'phase_start') for e in events), + health_failures=sum(e.get('healthy') is False for e in events), modes={}) + for mode in protocol['modes']: + records = [e for e in events if e.get('mode') == mode and e['event'] == 'transfer'] + small = [e['seconds'] * 1000 for e in records if e['size'] == 1024 and e['success']] + large = [e['mbps'] for e in records if e['size'] > 1024 and e['success']] + summary['modes'][mode] = dict(recorded_outcomes=len(records), success=sum(e['success'] for e in records), + errors=[e for e in records if not e['success']], + small_median_ms=statistics.median(small) if small else None, + small_p95_ms=sorted(small)[min(len(small) - 1, int(len(small) * .95))] if small else None, + large_median_mbps=statistics.median(large) if large else None) + expected_source = next((e.get('client_address') for e in events if e['event'] == 'start'), None) + for filename in ('client.pcap', 'remote-server.pcap'): + counts = defaultdict(Counter) + flows = list(initial_payloads(root / filename, protocol['ports'])) + external = [f for f in flows if not f['source'].startswith('127.')] + source = expected_source if filename.startswith('remote-') else None + if source is None and external: + source = Counter(f['source'] for f in external).most_common(1)[0][0] + unexpected = [f for f in external if f['source'] != source] + replays = [] + for probe in unexpected: + matches = [f for f in external if f['source'] == source and f['time'] < probe['time'] + and f['port'] == probe['port'] and f['payload_hex'] == probe['payload_hex'] + and f['payload_complete'] and probe['payload_complete']] + if matches: + original_phase = [event for stamp, event in phases if stamp <= matches[-1]['time']][-1] + replay_mode = original_phase['port_modes'][protocol['ports'].index(probe['port'])] + replays.append(dict(mode=replay_mode, phase=original_phase['phase'], port=probe['port'], delay_seconds=probe['time'] - matches[-1]['time'], + payload_bytes=len(bytes.fromhex(probe['payload_hex'])), + payload_sha256=hashlib.sha256(bytes.fromhex(probe['payload_hex'])).hexdigest())) + summary[filename + '/unsolicited'] = dict(connections=len(unexpected), exact_replays=replays) + for flow in flows: + if flow['source'] != source: + continue + previous = [event for stamp, event in phases if stamp <= flow['time']] + if not previous: + continue + phase = previous[-1] + mode = phase['port_modes'][protocol['ports'].index(flow['port'])] + values = counts[mode] + values['connections'] += 1 + values['sequence_ok'] += flow['sequence_ok'] + values['complete_first_payload'] += flow['payload_complete'] + payload = bytes.fromhex(flow['payload_hex']) + rules = exemptions(payload) + rules['tls_header'] = len(payload) >= 3 and payload[0] in (22, 23) and payload[1] == 3 and payload[2] <= 9 + if flow['payload_complete']: + values['historical_exemption'] += any(rules.values()) + for rule, passed in rules.items(): + values[rule] += passed + summary[filename] = {mode: dict(values) for mode, values in counts.items()} + stream_counts = defaultdict(Counter) + for flow in initial_payloads(root / filename, protocol['ports'], require_sequence=True): + if flow['source'] != source: + continue + previous = [event for stamp, event in phases if stamp <= flow['time']] + if not previous: + continue + mode = previous[-1]['port_modes'][protocol['ports'].index(flow['port'])] + payload = bytes.fromhex(flow['payload_hex']) + rules = exemptions(payload) + tls = len(payload) >= 3 and payload[0] in (22, 23) and payload[1] == 3 and payload[2] <= 9 + stream_counts[mode]['connections'] += 1 + stream_counts[mode]['complete_first_payload'] += flow['payload_complete'] + if flow['payload_complete']: + stream_counts[mode]['historical_exemption'] += any(rules.values()) or tls + summary[filename + '/stream_start'] = {mode: dict(values) for mode, values in stream_counts.items()} + (root / 'summary.json').write_text(json.dumps(summary, indent=2) + '\n') + print(json.dumps(summary, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/tests/experiments/benchmark.py b/tests/experiments/benchmark.py new file mode 100644 index 000000000..5172f3751 --- /dev/null +++ b/tests/experiments/benchmark.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""Synthetic uniform-ciphertext screening; not a live censorship measurement.""" +import argparse +from collections import Counter +import json +import math +import os +import statistics +import time + +from transport import BLOCK, decode, encode + + +def exemptions(data): + printable = [0x20 <= value <= 0x7e for value in data] + popcount = sum(value.bit_count() for value in data) / len(data) + longest = run = 0 + for value in printable: + run = run + 1 if value else 0 + longest = max(run, longest) + return dict(popcount=popcount <= 3.4 or popcount >= 4.6, + prefix=len(data) >= 6 and all(printable[:6]), + half=sum(printable) > len(data) / 2, run=longest > 20) + + +def statistics_for(data): + counts = Counter(data) + total = len(data) + return dict(byte_entropy=-sum(n / total * math.log2(n / total) for n in counts.values()), + alphabet_size=len(counts), printable_fraction=sum(0x20 <= b <= 0x7e for b in data) / total, + ones_per_byte=sum(b.bit_count() for b in data) / total) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output', required=True) + args = parser.parse_args() + payload = os.urandom(1024 * 1024) + results = [] + for mode in ('raw', 'printable_variable', 'base85', 'lowpop85'): + def transform(data): + if mode == 'printable_variable': + import secrets + length = 6 + secrets.randbelow(7) + return bytes(32 + secrets.randbelow(95) for _ in range(length)) + data[length:] + return encode(mode, data) + timings = [] + for _ in range(5): + start = time.perf_counter() + if mode == 'printable_variable': + wire = transform(payload) + else: + frames = [transform(payload[i:i + BLOCK]) for i in range(0, len(payload), BLOCK)] + wire = b''.join(frames) + if mode != 'raw': + recovered = b''.join(decode(mode, frame[:-1]) for frame in frames) + assert recovered == payload + timings.append(time.perf_counter() - start) + passes = Counter() + for _ in range(2000): + sample = transform(os.urandom(100)) + rules = exemptions(sample) + passes.update({key: int(value) for key, value in rules.items()}) + passes['any'] += any(rules.values()) + results.append(dict(mode=mode, synthetic=True, source_bytes=len(payload), wire_bytes=len(wire), + overhead_fraction=len(wire) / len(payload) - 1, + codec_roundtrip_mib_s=1 / statistics.median(timings) if mode not in ('raw', 'printable_variable') else None, + historical_exemption_samples=2000, historical_exemption_passes=dict(passes), + **statistics_for(wire))) + with open(args.output, 'w') as output: + json.dump(results, output, indent=2) + output.write('\n') + for row in results: + print(row['mode'], 'overhead', round(row['overhead_fraction'] * 100, 2), + 'entropy', round(row['byte_entropy'], 3), 'ones/byte', round(row['ones_per_byte'], 3), + 'historical exemptions', row['historical_exemption_passes']['any'], '/ 2000') + + +if __name__ == '__main__': + main() diff --git a/tests/experiments/local_interop.py b/tests/experiments/local_interop.py new file mode 100644 index 000000000..42b0322a0 --- /dev/null +++ b/tests/experiments/local_interop.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Exercise each outer transport around independently built stock Shadowsocks.""" +import argparse +import concurrent.futures +import json +from pathlib import Path +import subprocess +import sys +import tempfile +import threading +import time + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from interop import TCPHandler, TCPOrigin, free_port, peers, tcp_case # noqa: E402 +from transport import MODES # noqa: E402 + + +def certificate(directory): + cert, key = directory / 'certificate.pem', directory / 'key.pem' + subprocess.run(['openssl', 'req', '-x509', '-newkey', 'rsa:2048', '-nodes', '-keyout', str(key), + '-out', str(cert), '-days', '1', '-subj', '/CN=experiment.invalid', + '-addext', 'subjectAltName=DNS:experiment.invalid'], check=True, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + key.chmod(0o600) + return cert, key + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--bin', required=True) + parser.add_argument('--output', required=True) + args = parser.parse_args() + binary = Path(args.bin).resolve() + results = [] + with tempfile.TemporaryDirectory(prefix='ss-encoding-') as temp, TCPOrigin(('127.0.0.1', 0), TCPHandler) as origin: + cert, key = certificate(Path(temp)) + threading.Thread(target=origin.serve_forever, daemon=True).start() + try: + for method in ('chacha20-ietf-poly1305', 'aes-256-gcm'): + for mode in MODES: + server, remote, bridge, local = [free_port() for _ in range(4)] + common = [sys.executable, str(Path(__file__).with_name('transport.py')), '--mode', mode] + commands = [ + [str(binary / 'ss-server'), '-s', '127.0.0.1', '-p', str(server), '-m', method, '-k', 'local-encoding-test'], + common + ['--role', 'server', '--listen-port', str(remote), '--target-port', str(server), + '--certificate', str(cert), '--key', str(key)], + common + ['--role', 'client', '--listen-port', str(bridge), '--target-port', str(remote), + '--certificate', str(cert)], + [str(binary / 'ss-local'), '-s', '127.0.0.1', '-p', str(bridge), '-l', str(local), '-m', method, '-k', 'local-encoding-test'], + ] + with peers(commands, [server, remote, bridge, local]): + with concurrent.futures.ThreadPoolExecutor(max_workers=4) as pool: + pending = [pool.submit(tcp_case, local, origin.server_address[1], size) + for size in (1, 16383, 65536, 1048576)] + for task in pending: + task.result(timeout=30) + start = time.monotonic() + tcp_case(local, origin.server_address[1], 10 * 1024 * 1024) + duration = time.monotonic() - start + result = dict(mode=mode, cipher=method, concurrent_transfers=4, success=True, + large_bytes=10 * 1024 * 1024, large_seconds=duration, + echo_mbps=10 * 1024 * 1024 * 8 / duration / 1e6) + results.append(result) + print(json.dumps(result), flush=True) + finally: + origin.shutdown() + Path(args.output).write_text(json.dumps(results, indent=2) + '\n') + + +if __name__ == '__main__': + main() diff --git a/tests/experiments/route_screen.py b/tests/experiments/route_screen.py new file mode 100644 index 000000000..082b77880 --- /dev/null +++ b/tests/experiments/route_screen.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +"""Eight-minute, four-port Latin-square screening of experimental outer transports. + +Run after the original salt crossover completes, on unused high ports. This is +compatibility/performance screening, not evidence of lasting censorship resistance. +""" +import argparse +import base64 +import concurrent.futures +import json +import os +from pathlib import Path +import select +import shlex +import subprocess +import sys +import tempfile +import time +import threading + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +from interop import free_port, peers # noqa: E402 +from printable_salt_experiment import transfer # noqa: E402 +from local_interop import certificate # noqa: E402 +from transport import MODES # noqa: E402 + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--host', required=True) + parser.add_argument('--host-key-alias', required=True) + parser.add_argument('--address', required=True) + parser.add_argument('--stock-bin', required=True) + parser.add_argument('--output', required=True) + parser.add_argument('--interface', default='en0') + parser.add_argument('--ports', nargs=len(MODES), type=int, default=list(range(32200, 32200 + len(MODES)))) + parser.add_argument('--phase-seconds', type=int, default=120) + parser.add_argument('--large-bytes', type=int, default=10 * 1024 * 1024) + args = parser.parse_args() + out = Path(args.output).resolve() + out.mkdir(mode=0o700, parents=True, exist_ok=True) + if (out / 'events.jsonl').exists(): + parser.error('use a fresh output directory') + env = {key: value for key, value in os.environ.items() if not key.lower().endswith('_proxy')} + ssh = ['ssh', '-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=yes', '-o', + 'HostKeyAlias=' + args.host_key_alias, '-o', 'ConnectTimeout=8', '-o', + 'ServerAliveInterval=5', '-o', 'ServerAliveCountMax=2', args.host] + directory = subprocess.check_output(ssh + ['mktemp -d /tmp/ss-encoding.XXXXXXXX'], env=env, text=True).strip() + root = Path(__file__).parent + remote = capture = None + log_lock = threading.Lock() + def emit(record): + record['utc'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + with log_lock, (out / 'events.jsonl').open('a') as output: + output.write(json.dumps(record) + '\n') + def measured_transfer(meta, proxy, origin, size): + emit(dict(meta, event='attempt', size=size)) + result = transfer(proxy, origin, size) + emit(dict(**meta, **result)) + return result + def upload(name, content): + subprocess.run(ssh + ['umask 077; cat > ' + shlex.quote(directory + '/' + name)], + input=content, check=True, env=env) + def exchange(record): + remote.stdin.write(json.dumps(record) + '\n') + remote.stdin.flush() + assert select.select([remote.stdout], [], [], 12)[0], 'management health timeout' + line = remote.stdout.readline() + assert line, 'remote supervisor stopped' + return json.loads(line) + # Persist the schedule before observing outcomes. + (out / 'protocol.json').write_text(json.dumps(dict(modes=MODES, ports=args.ports, + phases=len(MODES), phase_seconds=args.phase_seconds, small_interval_seconds=5, + small_bytes=1024, large_per_phase=1, large_bytes=args.large_bytes, + rotation=f'mode i uses port (i + phase_index) modulo {len(MODES)}', + acceptance='screening only; all-success is compatibility, not censorship resistance'), indent=2) + '\n') + with tempfile.TemporaryDirectory(prefix='ss-encoding-cert-') as temporary: + cert, key = certificate(Path(temporary)) + password = base64.b64encode(os.urandom(32)).decode() + try: + for name in ('transport.py', 'route_server.py'): + upload(name, (root / name).read_bytes()) + upload('certificate.pem', cert.read_bytes()) + upload('key.pem', key.read_bytes()) + with (out / 'remote.log').open('w') as remote_log, (out / 'capture.log').open('w') as capture_log: + remote = subprocess.Popen(ssh + ['python3 -u ' + shlex.quote(directory + '/route_server.py')], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=remote_log, text=True, env=env) + ready = exchange(dict(ports=args.ports, password=password)) + assert ready['ready'] + capture = subprocess.Popen(['sudo', '-n', 'tcpdump', '-i', args.interface, + '-U', '-s', '0', '-w', str(out / 'client.pcap'), 'host ' + args.address + + ' and tcp and (' + ' or '.join('port ' + str(port) for port in args.ports) + ' or port 22)'], + stderr=capture_log, stdout=subprocess.DEVNULL, env=env, start_new_session=True) + time.sleep(1) + assert capture.poll() is None + emit(dict(event='start', **ready)) + with concurrent.futures.ThreadPoolExecutor(max_workers=15) as pool: + for phase in range(len(MODES)): + mapping = [MODES[(index - phase) % len(MODES)] for index in range(len(MODES))] + health = exchange(dict(event='phase', modes=mapping)) + emit(dict(event='phase_start', phase=phase + 1, port_modes=mapping, **health)) + assert health['healthy'], 'server-local phase control failed' + commands, ports, proxies = [], [], [] + for index, mode in enumerate(MODES): + bridge, proxy = free_port(), free_port() + port = args.ports[(index + phase) % len(MODES)] + commands.append([sys.executable, str(root / 'transport.py'), '--role', 'client', + '--mode', mode, '--listen-port', str(bridge), '--target-host', args.address, + '--target-port', str(port), '--certificate', str(cert)]) + commands.append([str(Path(args.stock_bin).resolve()), '-s', '127.0.0.1', + '-p', str(bridge), '-b', '127.0.0.1', '-l', str(proxy), '-k', password, + '-m', 'chacha20-ietf-poly1305']) + ports.extend((bridge, proxy)) + proxies.append((mode, proxy, port)) + with peers(commands, ports, env): + start = time.monotonic() + pending = [] + for tick in range((args.phase_seconds + 4) // 5): + time.sleep(max(0, start + tick * 5 - time.monotonic())) + if tick % 6 == 0: + health = exchange(dict(event='health')) + emit(dict(event='health', phase=phase + 1, **health)) + assert health['healthy'], 'server-local/management health failed' + for mode, proxy, port in proxies: + for size in ([1024, args.large_bytes] if tick == 0 else [1024]): + meta = dict(event='transfer', phase=phase + 1, tick=tick, mode=mode, port=port) + pending.append((meta, pool.submit(measured_transfer, meta, proxy, ready['origin'], size))) + remaining = [] + for meta, future in pending: + if future.done(): + future.result() + else: + remaining.append((meta, future)) + pending = remaining + for meta, future in pending: + future.result() + time.sleep(max(0, start + args.phase_seconds - time.monotonic())) + emit(dict(event='phase_complete', phase=phase + 1)) + emit(dict(event='complete')) + except BaseException as error: + emit(dict(event='aborted', reason=type(error).__name__ + ': ' + str(error).replace(password, ''))) + raise + finally: + if remote is not None and remote.poll() is None: + try: + remote.stdin.write(json.dumps(dict(event='stop')) + '\n') + remote.stdin.flush() + remote.wait(timeout=15) + except (BrokenPipeError, subprocess.TimeoutExpired): + remote.terminate() + remote.wait(timeout=15) + if capture is not None and capture.poll() is None: + subprocess.run(['sudo', '-n', 'kill', '-INT', '--', '-' + str(capture.pid)], check=False) + capture.wait(timeout=10) + copied = True + for name in ('server.pcap', 'capture.log'): + with (out / ('remote-' + name)).open('wb') as output: + result = subprocess.run(ssh + ['cat ' + shlex.quote(directory + '/' + name)], stdout=output, env=env) + copied &= result.returncode == 0 + if copied: + subprocess.run(ssh + ['rm -rf -- ' + shlex.quote(directory)], check=True, env=env) + emit(dict(event='cleanup', remote_exit=remote.returncode if remote else None, captures_retrieved=copied)) + + +if __name__ == '__main__': + main() diff --git a/tests/experiments/route_server.py b/tests/experiments/route_server.py new file mode 100644 index 000000000..427129ad5 --- /dev/null +++ b/tests/experiments/route_server.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +"""Private remote supervisor for route_screen.py; JSON commands on SSH stdin.""" +import asyncio +import contextlib +import json +import os +from pathlib import Path +import signal +import socket +import subprocess +import sys +import tempfile + +from transport import serve + + +def free_port(): + with socket.socket() as sock: + sock.bind(('127.0.0.1', 0)) + return sock.getsockname()[1] + + +async def echo(reader, writer): + try: + while data := await asyncio.wait_for(reader.read(65536), 30): + writer.write(data) + await writer.drain() + except (OSError, TimeoutError): + pass + finally: + writer.close() + with contextlib.suppress(OSError): + await writer.wait_closed() + + +def stop(processes): + for process in reversed(processes): + if process.poll() is None: + process.send_signal(signal.SIGINT) + for process in processes: + try: + process.wait(timeout=5) + except subprocess.TimeoutExpired: + process.kill() + process.wait() + + +async def check_control(port, origin_port): + writer = None + try: + reader, writer = await asyncio.open_connection('127.0.0.1', port) + writer.write(bytes([5, 1, 0])) + await writer.drain() + assert await reader.readexactly(2) == bytes([5, 0]) + writer.write(bytes([5, 1, 0, 1, 127, 0, 0, 1]) + origin_port.to_bytes(2, 'big')) + await writer.drain() + header = await reader.readexactly(4) + assert header[:3] == bytes([5, 0, 0]) + await reader.readexactly(6 if header[3] == 1 else 18) + data = os.urandom(1024) + writer.write(data) + await writer.drain() + assert await reader.readexactly(len(data)) == data + return True + except (OSError, AssertionError, asyncio.IncompleteReadError): + return False + finally: + if writer: + writer.close() + with contextlib.suppress(OSError): + await writer.wait_closed() + + +async def main(): + reader = asyncio.StreamReader() + loop = asyncio.get_running_loop() + pipe, _ = await loop.connect_read_pipe(lambda: asyncio.StreamReaderProtocol(reader), sys.stdin) + cfg = json.loads(await asyncio.wait_for(reader.readline(), 30)) + directory = Path(__file__).parent + processes, phase_processes, servers, controls = [], [], [], [] + # A controller disconnect or a bounded lifetime closes all owned resources. + task = asyncio.current_task() + loop.call_later(1200, task.cancel) + loop.add_signal_handler(signal.SIGTERM, task.cancel) + with tempfile.TemporaryDirectory(prefix='ss-encoding-config-') as temp, contextlib.ExitStack() as stack: + def spawn(binary, config, name): + path = Path(temp) / (name + '.json') + path.write_text(json.dumps(config)) + log = stack.enter_context((Path(temp) / (name + '.log')).open('wb')) + return subprocess.Popen([binary, '-c', str(path)], stdout=log, stderr=log) + origin = await asyncio.start_server(echo, '127.0.0.1', 0) + origin_port = origin.sockets[0].getsockname()[1] + backend = free_port() + common = dict(server='127.0.0.1', server_port=backend, password=cfg['password'], + method='chacha20-ietf-poly1305', mode='tcp_only') + try: + processes.append(spawn(cfg.get('server_binary', '/usr/local/bin/ssserver'), common, 'backend')) + capture_log = stack.enter_context((directory / 'capture.log').open('wb')) + if cfg.get('capture', True): + processes.append(subprocess.Popen(['tcpdump', '-i', 'any', '-U', '-s', '0', '-w', + str(directory / 'server.pcap'), 'tcp and (' + ' or '.join('port ' + str(p) for p in cfg['ports']) + + ' or (host ' + os.environ['SSH_CONNECTION'].split()[0] + ' and port 22))'], + stdout=subprocess.DEVNULL, stderr=capture_log)) + await asyncio.sleep(1) + assert all(p.poll() is None for p in processes) + print(json.dumps(dict(ready=True, origin=origin_port, backend=backend, client_address=os.environ['SSH_CONNECTION'].split()[0])), flush=True) + # Missing control commands also stop the service if the SSH + # connection is blackholed and never delivers EOF. + while line := await asyncio.wait_for(reader.readline(), cfg.get('control_timeout', 60)): + command = json.loads(line) + if command['event'] == 'stop': + break + if command['event'] == 'phase': + stop(phase_processes) + phase_processes.clear() + for server in servers: + server.close() + await server.wait_closed() + servers.clear() + controls.clear() + for index, mode in enumerate(command['modes']): + port = cfg['ports'][index] + server = await serve('server', mode, ('0.0.0.0', port), ('127.0.0.1', backend), + str(directory / 'certificate.pem'), str(directory / 'key.pem')) + servers.append(server) + client = await serve('client', mode, ('127.0.0.1', 0), ('127.0.0.1', port), + str(directory / 'certificate.pem')) + servers.append(client) + control_port = free_port() + config = dict(common, server_port=client.sockets[0].getsockname()[1], + local_address='127.0.0.1', local_port=control_port) + phase_processes.append(spawn('/usr/local/bin/sslocal', config, 'control-' + str(index))) + controls.append(control_port) + await asyncio.sleep(.4) + checks = await asyncio.gather(*(asyncio.wait_for(check_control(port, origin_port), 5) + for port in controls), return_exceptions=True) + healthy = all(p.poll() is None for p in processes + phase_processes) + values = [result is True for result in checks] + print(json.dumps(dict(healthy=healthy and all(values), local_transfers=values)), flush=True) + finally: + pipe.close() + stop(phase_processes) + stop(processes) + for server in servers + [origin]: + server.close() + await server.wait_closed() + + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/tests/experiments/test_supervisor.py b/tests/experiments/test_supervisor.py new file mode 100644 index 000000000..54c5e5471 --- /dev/null +++ b/tests/experiments/test_supervisor.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Run the real supervisor/backend and verify cleanup on lost control input.""" +import argparse +import json +import os +from pathlib import Path +import shutil +import signal +import socket +import subprocess +import sys +import tempfile +import unittest + +BINARY = None + + +class SupervisorTests(unittest.TestCase): + def check_cleanup(self, trigger): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + for name in ('route_server.py', 'transport.py'): + shutil.copy(Path(__file__).with_name(name), root / name) + env = dict(os.environ, SSH_CONNECTION='127.0.0.1 1 127.0.0.1 22') + with (root / 'log').open('w+') as log: + process = subprocess.Popen([sys.executable, str(root / 'route_server.py')], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=log, text=True, env=env) + try: + process.stdin.write(json.dumps(dict(password='supervisor-test-only', ports=[], + capture=False, server_binary=str(BINARY), control_timeout=.3 if trigger == 'timeout' else 60)) + '\n') + process.stdin.flush() + import select + self.assertTrue(select.select([process.stdout], [], [], 5)[0], 'supervisor startup timeout') + ready = json.loads(process.stdout.readline()) + self.assertTrue(ready['ready']) + for port in (ready['origin'], ready['backend']): + with socket.create_connection(('127.0.0.1', port), .5): + pass + if trigger == 'eof': + process.stdin.close() + elif trigger == 'signal': + process.send_signal(signal.SIGTERM) + process.wait(timeout=5) + if trigger == 'eof': + self.assertEqual(process.returncode, 0) + for port in (ready['origin'], ready['backend']): + with self.assertRaises(OSError): + socket.create_connection(('127.0.0.1', port), .2) + finally: + if process.poll() is None: + process.kill() + process.wait() + if not process.stdin.closed: + process.stdin.close() + process.stdout.close() + + def test_control_eof(self): + self.check_cleanup('eof') + + def test_control_silence(self): + self.check_cleanup('timeout') + + def test_termination_signal(self): + self.check_cleanup('signal') + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--bin', required=True) + args = parser.parse_args() + BINARY = Path(args.bin).resolve() / 'ss-server' + unittest.main(argv=[__file__]) diff --git a/tests/experiments/test_transport.py b/tests/experiments/test_transport.py new file mode 100644 index 000000000..c88ba617f --- /dev/null +++ b/tests/experiments/test_transport.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +"""Codec boundaries, fragmentation, bad records and relay half-close tests.""" +import asyncio +import os +from pathlib import Path +import shutil +import tempfile +import unittest + +from transport import BLOCK, MODES, decode, encode, read_record, serve + + +class CodecTests(unittest.IsolatedAsyncioTestCase): + async def test_fragmented_records(self): + for mode in MODES[1:]: + for size in (0, 1, 2, 3, 4, 5, 31, 32, BLOCK): + with self.subTest(mode=mode, size=size): + data = os.urandom(size) + wire = encode(mode, data) + reader = asyncio.StreamReader() + task = asyncio.create_task(read_record(reader, mode)) + for index in range(0, len(wire), 7): + reader.feed_data(wire[index:index + 7]) + await asyncio.sleep(0) + reader.feed_eof() + self.assertEqual(await task, data) + + async def test_coalesced_records(self): + for mode in MODES[1:]: + reader = asyncio.StreamReader() + reader.feed_data(encode(mode, b'one') + encode(mode, b'two') + encode(mode, b'')) + for expected in (b'one', b'two', b''): + self.assertEqual(await read_record(reader, mode), expected) + + async def test_invalid_and_truncated(self): + for mode in MODES[1:]: + reader = asyncio.StreamReader() + reader.feed_data(encode(mode, b'something')[:-1]) + reader.feed_eof() + with self.assertRaises(asyncio.IncompleteReadError): + await read_record(reader, mode) + for mode, invalid in [('base85', b'/'), ('lowpop85', b'\xff')]: + with self.assertRaises(ValueError): + decode(mode, invalid) + reader = asyncio.StreamReader() + reader.feed_data((BLOCK + 1).to_bytes(2, 'big')) + with self.assertRaises(ValueError): + await read_record(reader, 'tls') + + async def test_empty_client_does_not_connect_upstream(self): + calls = [] + async def connected(reader, writer): + calls.append(True) + writer.close() + await writer.wait_closed() + target = await asyncio.start_server(connected, '127.0.0.1', 0) + async with target: + for mode in MODES[:-1]: + client = await serve('client', mode, ('127.0.0.1', 0), target.sockets[0].getsockname()[:2]) + async with client: + _, writer = await asyncio.open_connection(*client.sockets[0].getsockname()[:2]) + writer.close() + await writer.wait_closed() + await asyncio.sleep(.03) + self.assertEqual(calls, []) + + async def test_tls_half_close_and_certificate_verification(self): + if not shutil.which('openssl'): + self.skipTest('openssl CLI is needed for temporary test certificates') + from local_interop import certificate + calls = [] + async def reverse(reader, writer): + calls.append(True) + data = await reader.read() + writer.write(data[::-1]) + await writer.drain() + writer.close() + await writer.wait_closed() + with tempfile.TemporaryDirectory() as temp: + good, bad = Path(temp) / 'good', Path(temp) / 'bad' + good.mkdir() + bad.mkdir() + cert, key = certificate(good) + wrong, _ = certificate(bad) + origin = await asyncio.start_server(reverse, '127.0.0.1', 0) + server = await serve('server', 'tls', ('127.0.0.1', 0), + origin.sockets[0].getsockname()[:2], str(cert), str(key)) + async with origin, server: + for trusted, succeeds in ((cert, True), (wrong, False)): + client = await serve('client', 'tls', ('127.0.0.1', 0), + server.sockets[0].getsockname()[:2], str(trusted)) + async with client: + reader, writer = await asyncio.open_connection(*client.sockets[0].getsockname()[:2]) + writer.write(b'certificate-and-half-close-test') + writer.write_eof() + result = await asyncio.wait_for(reader.read(), 5) + self.assertEqual(result, b'tset-esolc-flah-dna-etacifitrec' if succeeds else b'') + writer.close() + await writer.wait_closed() + self.assertEqual(len(calls), 1, 'bad certificate must not reach the backend') + + async def test_half_close_and_concurrent_relay(self): + async def reverse(reader, writer): + data = await reader.read() + writer.write(data[::-1]) + await writer.drain() + writer.close() + await writer.wait_closed() + origin = await asyncio.start_server(reverse, '127.0.0.1', 0) + target = origin.sockets[0].getsockname()[:2] + async with origin: + for mode in MODES[:-1]: + server = await serve('server', mode, ('127.0.0.1', 0), target) + remote = server.sockets[0].getsockname()[:2] + client = await serve('client', mode, ('127.0.0.1', 0), remote) + address = client.sockets[0].getsockname()[:2] + async def check(): + reader, writer = await asyncio.open_connection(*address) + data = os.urandom(BLOCK * 3 + 7) + writer.write(data) + writer.write_eof() + self.assertEqual(await asyncio.wait_for(reader.read(), 5), data[::-1]) + writer.close() + await writer.wait_closed() + async with server, client: + await asyncio.gather(*(check() for _ in range(4))) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/experiments/transport.py b/tests/experiments/transport.py new file mode 100644 index 000000000..ab69c72cd --- /dev/null +++ b/tests/experiments/transport.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +"""Experimental TCP outer transports. Not a production plugin or crypto scheme. + +Run a client relay in front of stock ss-local's remote connection and a server +relay in front of an unchanged ss-server. TLS uses a verified experiment CA. +""" +import argparse +import asyncio +from base64 import b85decode, b85encode +import contextlib +import ssl + +MODES = ('raw', 'base85', 'lowpop85', 'tls') +B85 = b'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~' +LOW = bytes(sorted(range(256), key=lambda value: (value.bit_count(), value))[:85]) +TO_LOW = bytes.maketrans(B85, LOW) +FROM_LOW = bytes.maketrans(LOW, B85) +BLOCK = 16384 + + +def encode(mode, data): + if mode == 'raw': + return data + if mode == 'tls': + return len(data).to_bytes(2, 'big') + data + result = b85encode(data) + return result.translate(TO_LOW) + b'\xff' if mode == 'lowpop85' else result + b'\n' + + +def decode(mode, data): + if mode == 'lowpop85': + if any(value not in LOW for value in data): + raise ValueError('invalid low-popcount symbol') + data = data.translate(FROM_LOW) + return b85decode(data) + + +async def read_record(reader, mode): + if mode == 'raw': + return await reader.read(BLOCK) + if mode == 'tls': + length = int.from_bytes(await reader.readexactly(2), 'big') + if length > BLOCK: + raise ValueError('oversized TLS record') + return await reader.readexactly(length) + delimiter = b'\xff' if mode == 'lowpop85' else b'\n' + frame = await reader.readuntil(delimiter) + if len(frame) > (BLOCK * 5 + 3) // 4 + 1: + raise ValueError('oversized encoded record') + return decode(mode, frame[:-1]) + + +async def pump(reader, writer, mode, encoding, initial=None): + while True: + if initial is not None: + data, initial = initial, None + else: + data = await asyncio.wait_for(reader.read(BLOCK) if encoding else read_record(reader, mode), 30) + if encoding: + writer.write(encode(mode, data)) + elif data: + writer.write(data) + await writer.drain() + if not data: + if (not encoding or mode == 'raw') and writer.can_write_eof(): + writer.write_eof() + return + + +def tls_context(role, certificate, key=None): + if role == 'server': + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(certificate, key) + else: + context = ssl.create_default_context(cafile=certificate) + context.minimum_version = ssl.TLSVersion.TLSv1_3 + return context + + +async def relay(reader, writer, role, mode, target, context=None): + upstream = None + tasks = [] + try: + initial = None + if role == 'client': + # Readiness probes and idle connections must not emit empty outer + # records or TLS handshakes that contaminate the route experiment. + initial = await asyncio.wait_for(reader.read(BLOCK), 30) + if not initial: + return + kwargs = {} + if mode == 'tls' and role == 'client': + kwargs = dict(ssl=context, server_hostname='experiment.invalid', ssl_handshake_timeout=10) + remote_reader, upstream = await asyncio.wait_for(asyncio.open_connection(*target, **kwargs), 10) + tasks = [asyncio.create_task(pump(reader, upstream, mode, role == 'client', initial)), + asyncio.create_task(pump(remote_reader, writer, mode, role != 'client'))] + done, _ = await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) + for task in done: + task.result() + except (OSError, ValueError, asyncio.IncompleteReadError, asyncio.LimitOverrunError, TimeoutError): + pass + finally: + for task in tasks: + task.cancel() + if tasks: + await asyncio.gather(*tasks, return_exceptions=True) + for peer in (writer, upstream): + if peer is not None: + peer.close() + with contextlib.suppress(OSError, TimeoutError): + await asyncio.wait_for(peer.wait_closed(), 3) + + +async def serve(role, mode, listen, target, certificate=None, key=None): + context = tls_context(role, certificate, key) if mode == 'tls' else None + kwargs = dict(ssl=context, ssl_handshake_timeout=10) if mode == 'tls' and role == 'server' else {} + return await asyncio.start_server( + lambda reader, writer: relay(reader, writer, role, mode, target, context), *listen, **kwargs) + + +async def main(args): + server = await serve(args.role, args.mode, (args.listen_host, args.listen_port), + (args.target_host, args.target_port), args.certificate, args.key) + async with server: + await server.serve_forever() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--role', choices=('client', 'server'), required=True) + parser.add_argument('--mode', choices=MODES, required=True) + parser.add_argument('--listen-host', default='127.0.0.1') + parser.add_argument('--listen-port', type=int, required=True) + parser.add_argument('--target-host', default='127.0.0.1') + parser.add_argument('--target-port', type=int, required=True) + parser.add_argument('--certificate') + parser.add_argument('--key') + asyncio.run(main(parser.parse_args())) diff --git a/tests/interop.py b/tests/interop.py index 1d03a0e4d..c9a040831 100644 --- a/tests/interop.py +++ b/tests/interop.py @@ -179,12 +179,16 @@ def peers(commands, ports, environment=None): def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--self", action="store_true", help="use this build for both peers") + parser.add_argument("--printable-salt", action="store_true", help="enable experimental C client TCP prefix") + parser.add_argument("--server-bin", help="independent stock ss-server executable (requires --self)") parser.add_argument("--method", help="run one cipher") parser.add_argument("--bin", default=os.environ.get("SS_BIN_DIR", "build/bin"), help="program directory") parser.add_argument("--plugin", help="SIP003 fixture executable (requires --self)") parser.add_argument("--isolate-windows-runtime", action="store_true", help="remove MSYS2/toolchain DLL directories from child PATH") args = parser.parse_args() + if args.server_bin and not args.self: + parser.error("--server-bin requires --self") if args.plugin and not args.self: parser.error("--plugin requires --self") environment = None @@ -197,6 +201,8 @@ def main(): binary_dir = Path(args.bin).resolve() suffix = ".exe" if os.name == "nt" else "" local, server = [str(binary_dir / (name + suffix)) for name in ("ss-local", "ss-server")] + if args.server_bin: + server = str(Path(args.server_bin).resolve()) rust_local, rust_server = shutil.which("sslocal"), shutil.which("ssserver") missing = [p for p in (local, server) if not os.path.isfile(p)] if not args.self: @@ -207,6 +213,8 @@ def main(): methods = ["2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305"] + if args.printable_salt: + methods = ["aes-256-gcm", "chacha20-ietf-poly1305"] if args.method: methods = [args.method] failures = 0 @@ -224,6 +232,8 @@ def main(): server_port, local_port = free_port(), free_port() c_server = [server, "-s", "127.0.0.1", "-p", str(server_port), "-k", psk, "-m", method, "-u"] c_local = [local, "-s", "127.0.0.1", "-p", str(server_port), "-l", str(local_port), "-k", psk, "-m", method, "-u"] + if args.printable_salt: + c_local.append("--printable-salt") commands = [c_server, c_local] plugin_temp = tempfile.TemporaryDirectory(prefix="ss-plugin-") if args.plugin else None markers = [] diff --git a/tests/printable_salt_experiment.py b/tests/printable_salt_experiment.py new file mode 100644 index 000000000..2a139b7ce --- /dev/null +++ b/tests/printable_salt_experiment.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 +"""One-hour two-port crossover. Requires previously verified SSH host trust. + +Uses an existing stock ssserver (Rust) on the remote host, with isolated ports, +configs, echo origin and packet capture. Does not change firewall rules. +Results contain no password; captures/configs live in private directories. +""" +import argparse +import base64 +import concurrent.futures +import json +import os +from pathlib import Path +import shlex +import subprocess +import time +import threading + +from interop import peers, receive, socks + +REMOTE = r''' +import contextlib, json, os, signal, socketserver, subprocess, sys, tempfile, threading, time +class Echo(socketserver.BaseRequestHandler): + def handle(self): + self.request.settimeout(30) + try: + while True: + data = self.request.recv(65536) + if not data: break + self.request.sendall(data) + except OSError: pass +class Origin(socketserver.ThreadingTCPServer): + allow_reuse_address = True + daemon_threads = True +cfg = json.loads(sys.stdin.readline()) +processes = [] +controls = [] +def stop(*args): raise SystemExit() +signal.signal(signal.SIGTERM, stop) +signal.signal(signal.SIGINT, stop) +with tempfile.TemporaryDirectory(prefix='ss-printable-') as tmp, contextlib.ExitStack() as stack: + origin = stack.enter_context(Origin(('127.0.0.1', 0), Echo)) + threading.Thread(target=origin.serve_forever, daemon=True).start() + try: + for port in cfg['ports']: + path = tmp + '/' + str(port) + '.json' + with open(path, 'w') as f: + json.dump(dict(server='0.0.0.0', server_port=port, + password=cfg['password'], method='chacha20-ietf-poly1305', + mode='tcp_only'), f) + log = stack.enter_context(open(tmp + '/' + str(port) + '.log', 'wb')) + processes.append(subprocess.Popen(['/usr/local/bin/ssserver', '-c', path], stdout=log, stderr=log)) + for index, port in enumerate(cfg['ports']): + import socket + with socket.socket() as reserve: + reserve.bind(('127.0.0.1', 0)) + local_port = reserve.getsockname()[1] + path = tmp + '/control-' + str(port) + '.json' + with open(path, 'w') as f: + json.dump(dict(server='127.0.0.1', server_port=port, + local_address='127.0.0.1', local_port=local_port, + password=cfg['password'], method='chacha20-ietf-poly1305'), f) + log = stack.enter_context(open(tmp + '/control-' + str(port) + '.log', 'wb')) + processes.append(subprocess.Popen(['/usr/local/bin/sslocal', '-c', path], stdout=log, stderr=log)) + controls.append(local_port) + capture = subprocess.Popen(['tcpdump', '-i', 'any', '-U', '-s', '160', '-w', + cfg['capture'], 'tcp and (' + ' or '.join('port '+str(p) for p in cfg['ports']) + ')'], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + processes.append(capture) + time.sleep(1) + assert all(p.poll() is None for p in processes) + print(json.dumps(dict(ready=True, origin=origin.server_address[1])), flush=True) + # stdin closes if the controlling SSH process dies. Bound lifetime too. + def watchdog(): + time.sleep(3900) + os.kill(os.getpid(), signal.SIGTERM) + threading.Thread(target=watchdog, daemon=True).start() + import select + while select.select([sys.stdin], [], [], 60)[0]: + line = sys.stdin.readline() + if not line or line.strip() == 'stop': break + healthy = all(p.poll() is None for p in processes) + import socket + for port in cfg['ports']: + try: + with socket.create_connection(('127.0.0.1', port), 2): pass + except OSError: healthy = False + # Verify each server locally through an independent Rust client. + import struct + def exact(sock, count): + data = b'' + while len(data) < count: + part = sock.recv(count - len(data)) + if not part: raise OSError('short control read') + data += part + return data + verified = [] + for port in controls: + try: + with socket.create_connection(('127.0.0.1', port), 2) as sock: + sock.settimeout(2) + sock.sendall(bytes([5, 1, 0])) + assert exact(sock, 2) == bytes([5, 0]) + sock.sendall(bytes([5, 1, 0, 1, 127, 0, 0, 1]) + struct.pack('!H', origin.server_address[1])) + head = exact(sock, 4) + assert head[:3] == bytes([5, 0, 0]) + exact(sock, 6 if head[3] == 1 else 18) + payload = os.urandom(1024) + sock.sendall(payload) + assert exact(sock, 1024) == payload + verified.append(True) + except (OSError, AssertionError): + verified.append(False) + print(json.dumps(dict(healthy=healthy and all(verified), local_transfers=verified)), flush=True) + finally: + for p in reversed(processes): + if p.poll() is None: p.send_signal(signal.SIGINT) + for p in processes: + try: p.wait(timeout=5) + except subprocess.TimeoutExpired: p.kill(); p.wait() + origin.shutdown() +''' + + +def transfer(proxy, origin, size): + start = time.monotonic() + result = dict(size=size, success=False) + try: + sock, _ = socks(proxy, 1, ('127.0.0.1', origin)) + result['socks_handshake_ms'] = (time.monotonic() - start) * 1000 + payload = os.urandom(size) + with sock, concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: + sock.settimeout(20) + upload = pool.submit(sock.sendall, payload) + assert receive(sock, size) == payload, 'integrity mismatch' + upload.result(timeout=25) + result['success'] = True + except (OSError, AssertionError, TimeoutError) as error: + result['error'] = type(error).__name__ + ': ' + str(error) + result['seconds'] = time.monotonic() - start + result['mbps'] = size * 8 / result['seconds'] / 1e6 if result['success'] else None + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--host', required=True) + parser.add_argument('--host-key-alias', required=True) + parser.add_argument('--address', required=True) + parser.add_argument('--stock-bin', required=True) + parser.add_argument('--modified-bin', required=True) + parser.add_argument('--output', required=True) + parser.add_argument('--interface', default='en0') + parser.add_argument('--ports', nargs=2, type=int, default=[32181, 32182]) + parser.add_argument('--phase-seconds', type=int, default=1800) + args = parser.parse_args() + out = Path(args.output).resolve() + out.mkdir(mode=0o700, parents=True, exist_ok=True) + if (out / 'events.jsonl').exists(): + parser.error('use a fresh output directory') + env = {k: v for k, v in os.environ.items() if not k.lower().endswith('_proxy')} + ssh = ['ssh', '-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=yes', '-o', + 'HostKeyAlias=' + args.host_key_alias, '-o', 'ConnectTimeout=8', + '-o', 'ServerAliveInterval=5', '-o', 'ServerAliveCountMax=2', args.host] + remote_dir = subprocess.check_output(ssh + ['mktemp -d /tmp/ss-printable-capture.XXXXXXXX'], env=env, text=True).strip() + capture_path = remote_dir + '/server.pcap' + password = base64.b64encode(os.urandom(32)).decode() + local_capture = None + remote = None + log_lock = threading.Lock() + def emit(record): + record['utc'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + with log_lock, (out / 'events.jsonl').open('a') as f: + f.write(json.dumps(record) + '\n') + def measured_transfer(meta, proxy, origin, size): + emit(dict(meta, event='attempt', size=size)) + result = transfer(proxy, origin, size) + emit(dict(**meta, **result)) + return result + try: + remote_log = (out / 'remote.log').open('w') + remote = subprocess.Popen(ssh + ['python3 -u -c ' + shlex.quote(REMOTE)], env=env, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=remote_log, text=True) + remote.stdin.write(json.dumps(dict(ports=args.ports, password=password, capture=capture_path)) + '\n') + remote.stdin.flush() + ready = json.loads(remote.stdout.readline()) + assert ready['ready'] + origin = ready['origin'] + capture_log = (out / 'capture.log').open('w') + local_capture = subprocess.Popen(['sudo', '-n', 'tcpdump', '-i', args.interface, + '-U', '-s', '160', '-w', str(out / 'client.pcap'), 'host ' + args.address + ' and tcp and (' + + ' or '.join('port ' + str(p) for p in args.ports) + ')'], stderr=capture_log, env=env, start_new_session=True) + time.sleep(1) + assert local_capture.poll() is None, 'local capture unavailable' + emit(dict(event='start', ports=args.ports, phase_seconds=args.phase_seconds, origin=origin)) + with concurrent.futures.ThreadPoolExecutor(max_workers=6) as pool: + for phase in (0, 1): + commands = [] + local_ports = [32183, 32184] + for mode, binary in enumerate((args.stock_bin, args.modified_bin)): + command = [str(Path(binary).resolve()), '-s', args.address, '-p', str(args.ports[mode ^ phase]), + '-b', '127.0.0.1', '-l', str(local_ports[mode]), '-k', password, + '-m', 'chacha20-ietf-poly1305'] + if mode: + command.append('--printable-salt') + commands.append(command) + with peers(commands, local_ports, env): + start = time.monotonic() + pending = [] + for tick in range((args.phase_seconds + 4) // 5): + time.sleep(max(0, start + tick * 5 - time.monotonic())) + if tick % 6 == 0: + # Round-trip SSH is the management health control. + remote.stdin.write('health\n') + remote.stdin.flush() + import select + assert select.select([remote.stdout], [], [], 8)[0], 'management health timeout' + line = remote.stdout.readline() + assert line, 'management connection closed' + health = json.loads(line) + emit(dict(event='health', phase=phase + 1, **health)) + assert health['healthy'], 'server health failed' + for mode, proxy in enumerate(local_ports): + sizes = [1024] + # Ten evenly spaced large transfers per phase/mode. + if tick in {int(i * (args.phase_seconds // 5) / 10) for i in range(10)}: + sizes.append(10 * 1024 * 1024) + for size in sizes: + meta = dict(event='transfer', phase=phase + 1, tick=tick, + mode='modified' if mode else 'stock', port=args.ports[mode ^ phase]) + pending.append((meta, pool.submit(measured_transfer, meta, proxy, origin, size))) + remaining = [] + for meta, future in pending: + if future.done(): + future.result() + else: + remaining.append((meta, future)) + pending = remaining + for meta, future in pending: + future.result() + time.sleep(max(0, start + args.phase_seconds - time.monotonic())) + emit(dict(event='phase_complete', phase=phase + 1)) + emit(dict(event='complete')) + except BaseException as error: + emit(dict(event='aborted', reason=type(error).__name__ + ': ' + str(error).replace(password, ''))) + raise + finally: + if remote is not None: + if remote.poll() is None: + try: + remote.stdin.write('stop\n') + remote.stdin.flush() + remote.wait(timeout=15) + except (BrokenPipeError, subprocess.TimeoutExpired): + remote.terminate() + remote.wait(timeout=15) + remote_log.close() + if local_capture is not None: + subprocess.run(['sudo', '-n', 'kill', '-INT', '--', '-' + str(local_capture.pid)], check=False) + local_capture.wait(timeout=10) + capture_log.close() + # Keep the remote capture if retrieval fails. + with (out / 'server.pcap').open('wb') as f: + copied = subprocess.run(ssh + ['cat ' + shlex.quote(capture_path)], stdout=f, env=env) + if copied.returncode == 0: + subprocess.run(ssh + ['rm -rf -- ' + shlex.quote(remote_dir)], check=True, env=env) + emit(dict(event='cleanup', remote_exit=remote.returncode if remote else None, + capture_retrieved=copied.returncode == 0)) + + +if __name__ == '__main__': + main() diff --git a/tests/test_cli.py b/tests/test_cli.py index 398714f4a..22c85d957 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -52,6 +52,42 @@ def test_help_and_version(self): self.assertIn('--outbound-address', help_result.stdout) self.assertNotIn('--server-port', help_result.stdout) + def test_printable_salt_is_local_only_and_rejects_other_ciphers(self): + for name in self.binaries: + help_result = self.run_cli(name, '--help') + self.assertEqual('--printable-salt' in help_result.stdout, name == 'local') + if name != 'local': + self.assertEqual(self.run_cli(name, '--printable-salt').returncode, 2) + for method in ('aes-128-gcm', 'aes-256-cfb', '2022-blake3-aes-256-gcm', + '2022-blake3-chacha20-poly1305'): + with self.subTest(method=method): + result = self.run_cli('local', '-s', '127.0.0.1', '-p', '8388', + '-l', '1080', '-k', 'test-password', '-m', method, + '--printable-salt') + self.assertNotEqual(result.returncode, 0) + self.assertIn('requires chacha20-ietf-poly1305', result.stderr) + with tempfile.TemporaryDirectory() as directory: + config = Path(directory) / 'client.json' + config.write_text(json.dumps(dict(server='127.0.0.1', server_port=8388, + local_port=1080, password='test-password', + method='aes-128-gcm'))) + result = self.run_cli('local', '-c', str(config), '--printable-salt') + self.assertNotEqual(result.returncode, 0) + self.assertIn('requires chacha20-ietf-poly1305', result.stderr) + # The config key alone enables it, so the cipher check still applies. + config.write_text(json.dumps(dict(server='127.0.0.1', server_port=8388, + local_port=1080, password='test-password', + method='aes-128-gcm', printable_salt=True))) + result = self.run_cli('local', '-c', str(config)) + self.assertNotEqual(result.returncode, 0) + self.assertIn('requires chacha20-ietf-poly1305', result.stderr) + config.write_text(json.dumps(dict(server='127.0.0.1', server_port=8388, + local_port=1080, password='test-password', + method='aes-128-gcm', printable_salt='yes'))) + result = self.run_cli('local', '-c', str(config)) + self.assertNotEqual(result.returncode, 0) + self.assertIn("option 'printable_salt' must be a boolean", result.stderr) + def test_long_aliases_accept_their_arguments(self): for name in self.binaries: args = ['--config', 'not-loaded-before-help.json', '--cipher', 'aes-128-gcm', diff --git a/tests/test_crypto.c b/tests/test_crypto.c index c09e54483..e0a4ad712 100644 --- a/tests/test_crypto.c +++ b/tests/test_crypto.c @@ -173,6 +173,125 @@ test_aead_repeat_salt_rejection_releases_context(void) ss_free(crypto); } +/* A nonprintable sentinel exposes the selected span without adding wire state. + * Retain the random tail so every test connection still has a fresh salt. */ +static void +test_printable_salt_lengths(const char *method) +{ + crypto_t *crypto = crypto_init("password", NULL, method); + assert(crypto != NULL); + unsigned seen = 0; + buffer_t buf = {0}; + balloc(&buf, 2048); + for (int sample = 0; sample < 512; sample++) { + cipher_ctx_t enc; + crypto->ctx_init(crypto->cipher, &enc, 1); + enc.printable_salt = 1; + memset(enc.salt, 0xff, 12); + uint8_t tail[20]; + memcpy(tail, enc.salt + 12, sizeof(tail)); + buf.data[0] = 'x'; + buf.len = 1; + assert(crypto->encrypt(&buf, &enc, 2048) == CRYPTO_OK); + assert(buf.len == 32 + 2 + 32 + 1); + size_t length = 0; + while (length < 12 && enc.salt[length] != 0xff) { + assert(enc.salt[length] >= 0x20 && enc.salt[length] <= 0x7e); + length++; + } + assert(length >= 6 && length <= 12); + for (size_t i = length; i < 12; i++) + assert(enc.salt[i] == 0xff); + assert(memcmp(tail, enc.salt + 12, sizeof(tail)) == 0); + assert(memcmp(buf.data, enc.salt, 32) == 0); + seen |= 1u << (length - 6); + crypto->ctx_release(&enc); + } + /* Probability of missing a length with unbiased sampling is < 4e-34. */ + assert(seen == 0x7f); + bfree(&buf); + ppbloom_free(); + ss_free(crypto->cipher); + ss_free(crypto); +} + +/* Exercise empty first writes, exact wire overhead, fragmented input, tampering + * and replay with the receiver's independent bloom filter. */ +static void +test_printable_salt(const char *method, int enabled) +{ + crypto_t *crypto = crypto_init("password", NULL, method); + assert(crypto != NULL); + cipher_ctx_t enc, dec; + crypto->ctx_init(crypto->cipher, &enc, 1); + crypto->ctx_init(crypto->cipher, &dec, 0); + assert(enc.printable_salt == 0); + enc.printable_salt = enabled; + uint8_t original[32]; + memcpy(original, enc.salt, 32); + buffer_t buf = {0}, fragment = {0}; + balloc(&buf, 2048); + balloc(&fragment, 2048); + assert(crypto->encrypt(&buf, &enc, 2048) == CRYPTO_OK); + assert(enc.init == 0 && buf.len == 0); + assert(memcmp(original, enc.salt, 32) == 0); + memcpy(buf.data, "payload", 7); + buf.len = 7; + assert(crypto->encrypt(&buf, &enc, 2048) == CRYPTO_OK); + assert(buf.len == 32 + 2 + 32 + 7); + assert(memcmp(buf.data, enc.salt, 32) == 0); + assert(memcmp(original + 12, enc.salt + 12, 20) == 0); + if (enabled) { + for (int i = 0; i < 6; i++) + assert(enc.salt[i] >= 0x20 && enc.salt[i] <= 0x7e); + } else { + assert(memcmp(original, enc.salt, 32) == 0); + } + uint8_t wire[73]; + memcpy(wire, buf.data, sizeof(wire)); + ppbloom_free(); + ppbloom_init(10000, 1e-15); + for (size_t i = 0; i < sizeof(wire); i++) { + fragment.data[0] = wire[i]; + fragment.len = 1; + int result = crypto->decrypt(&fragment, &dec, 2048); + if (i + 1 < sizeof(wire)) { + assert(result == CRYPTO_NEED_MORE); + } else { + assert(result == CRYPTO_OK); + assert(fragment.len == 7 && memcmp(fragment.data, "payload", 7) == 0); + } + } + memcpy(original, enc.salt, 32); + memcpy(buf.data, "next", 4); + buf.len = 4; + assert(crypto->encrypt(&buf, &enc, 2048) == CRYPTO_OK); + assert(buf.len == 2 + 32 + 4); + assert(memcmp(original, enc.salt, 32) == 0); + assert(crypto->decrypt(&buf, &dec, 2048) == CRYPTO_OK); + assert(buf.len == 4 && memcmp(buf.data, "next", 4) == 0); + crypto->ctx_release(&dec); + crypto->ctx_init(crypto->cipher, &dec, 0); + memcpy(buf.data, wire, sizeof(wire)); + buf.len = sizeof(wire); + assert(crypto->decrypt(&buf, &dec, 2048) == CRYPTO_ERROR); + crypto->ctx_release(&dec); + ppbloom_free(); + ppbloom_init(10000, 1e-15); + crypto->ctx_init(crypto->cipher, &dec, 0); + memcpy(buf.data, wire, sizeof(wire)); + buf.data[sizeof(wire) - 1] ^= 1; + buf.len = sizeof(wire); + assert(crypto->decrypt(&buf, &dec, 2048) == CRYPTO_ERROR); + crypto->ctx_release(&dec); + crypto->ctx_release(&enc); + bfree(&buf); + bfree(&fragment); + ppbloom_free(); + ss_free(crypto->cipher); + ss_free(crypto); +} + /* * Round-trip a multi-segment stream through a stream cipher. * @@ -232,6 +351,12 @@ main(void) return 1; } + test_printable_salt_lengths("chacha20-ietf-poly1305"); + test_printable_salt_lengths("aes-256-gcm"); + test_printable_salt("chacha20-ietf-poly1305", 0); + test_printable_salt("chacha20-ietf-poly1305", 1); + test_printable_salt("aes-256-gcm", 0); + test_printable_salt("aes-256-gcm", 1); test_crypto_md5(); test_crypto_derive_key(); test_crypto_hkdf();