Skip to content

Repository files navigation

S3TP

S3TP is an experimental private transport SDK with UDP and TCP carriers behind one multiplexed connection API. PreferUdp now performs typed, network-only UDP-to-TCP fallback. This is a research implementation, not a production-ready security product.

The design uses standard cryptographic primitives and treats protocol details as public. Security must come from authenticated key agreement, packet protection, strict state machines, resource limits, and independent review.

Start with docs/ARCHITECTURE.md, docs/SDK.md, and docs/HANDOFF.md. Read docs/protocol.md, docs/threat-model.md, and SECURITY.md before changing protocol or security behavior.

Embedding

Applications should depend on the s3tp crate. The compatibility API mirrors Tokio: S3tpListener::bind/accept and S3tpStream::connect; S3tpStream implements AsyncRead + AsyncWrite. See docs/SDK.md for the migration example and current limitations. New applications can use S3tpConnection::connect with TransportMode, or the explicit connect_tcp/connect_udp entry points, plus open_bi, accept_bi, open_uni, and accept_uni for multiplexed streams.

Diagnostics

The s3p binary is a local diagnostic tool, not a production daemon. Generate a Noise identity keypair or exercise both authenticated carriers end to end:

.\scripts\cargo.ps1 run -p s3p -- keygen
.\scripts\cargo.ps1 run -p s3p -- self-test --carrier both --bytes 1048576
.\scripts\cargo.ps1 run -p s3p -- load-test --carrier both --constrained --rate-kbps 3000
.\scripts\cargo.ps1 run -p s3p -- slo --help

Protect generated private keys and never commit them. self-test uses ephemeral loopback-only keys and verifies the echoed payload hash. load-test is also loopback-only; its default 3 Mbps aggregate application pacing and bounded workload make it suitable for small development machines without consuming public bandwidth. For bounded cross-host diagnostics, s3p slo server/run records measurement-only JSONL with a fixed workload, authenticated peers, a global connection cap, deadlines, and evidence-size limits. Formal qualification is derived later from verified environment, netem, RSS, outage, and allocation evidence; the CLI never promotes a row merely because an operator supplied a profile name. See docs/SLO.md. For bounded UDP diagnosis, RUST_LOG=s3tp::udp_stream=debug emits one coarse reliability summary when a pump exits, including current/peak congestion windows, loss/congestion/PTO counters, RTT/PTO snapshots, and the route-queue-drop count. It never includes peer keys, CIDs, transcripts, packet contents, or application data.

On this Windows workspace, use scripts/cargo.ps1 test --workspace so the isolated Rust and MinGW installations are selected consistently.

Maturity

v1.0.0-rc.1 carries TCP and UDP traffic through the target 36-byte packet header, bounded Initial/Retry/Handshake bodies, protected frames, and independent directional connection IDs. Packaged immutable wire and deterministic Noise/traffic-key vectors live under crates/s3p-core/vectors/v1 and crates/s3p-crypto/vectors/v1. The UDP SDK retains bounded ACK ranges, RTT/PTO, paced NewReno, ACK decimation, retransmission, reassembly, sliding connection credit, Retry anti-amplification, and half-close/EOF. Every initial or migrated UDP path must confirm an authenticated exact 1200-byte PING + PADDING probe; migration also requires PATH_CHALLENGE/PATH_RESPONSE and stays inside the candidate's 3x amplification budget. The dispatcher reserves a candidate only after AEAD verification, so forged ciphertext cannot occupy the migration slot. UDP authenticated peer close is retransmitted across three PTO; TCP sends or accepts one ordered close and terminates. Terminal protocol errors reach the SDK on both carriers, while locally detected authenticated failures emit stable close codes. Both carriers now negotiate the canonical D010 transport-parameter table and bind the carrier, version, Retry lineage, directional CIDs, nonces, cipher suite, and selected limits into all three Noise XX messages. Both carriers also implement D011 key update: directional traffic secrets advance inside s3p-crypto, packet numbers remain continuous across phase changes, TCP/UDP ACK any tracked update announcement including path-control probes, and one prior receive key is bounded to three PTO. Property suites cover codecs, Retry/amplification, ACK normalization, AEAD/replay, parser panic resistance, and generated stream-state accounting. Seven fuzz targets cover packets, frames, handshake bodies, TCP records, ACKs, transport parameters, and stream events; scheduled Linux CI is configured to run each under libFuzzer/ASan alongside RustSec, dependency-policy, and SBOM gates. Actual release-revision Linux runtime evidence remains a stable blocker. Both carriers now share a multiplexed connection state machine with QUIC-style bidirectional/unidirectional stream IDs, negotiated connection and per-stream credit, bounded sparse reassembly, RESET/STOP, immutable final sizes, stream retirement, and MAX_STREAMS credit recycling. Eight byte-weighted deficit-round-robin classes provide bounded control precedence and a 10 ms lower-priority opportunity; authenticated receive storage is capped per connection and across the process. Compatibility S3tpStream and UdpStream values wrap stream 0. Established connections and compatibility streams expose the exact authenticated peer static public key for application role/permission mapping. v1 uses fixed transcript-bound directional CIDs and deliberately omits stateless reset/CID rotation until a complete authenticated token lifecycle exists. TransportMode::Tcp and TransportMode::Udp select their carrier. PreferUdp gives UDP a bounded authentication window, then attempts TCP only for typed NetworkUnavailable or NoAuthenticatedResponse outcomes. Authorization, Noise, transcript, version, AEAD, protocol, and every post-authentication failure are terminal. Connection errors use privacy-safe stable categories, and dropping a connect future cannot leave a background fallback running. ResourceProfile::Constrained makes low-cost nodes a first-class RC baseline. It reduces negotiated windows and stream counts, per-connection receive/reassembly caps, and UDP dispatcher admission for low-cost nodes down to roughly 1 vCPU, 1 GiB RAM, and 3 Mbps links. The default Balanced profile remains available for ordinary desktops and servers; high-throughput hardware is an optional performance target, not a compatibility requirement. The target-hardware SLO topology is one heterogeneous two-node pair, including at least one real 1 vCPU/no-more-than-1152-MiB floor node. That compatibility gate does not require a third node, identical SKUs, higher bandwidth, or workloads beyond the bounded cases in docs/SLO.md. This experimental RC is not a target-v1 conformance or production-security claim. Linux sanitizer execution, cross-implementation vectors, constrained target-hardware SLOs, a 24-hour fault soak, and independent protocol/cryptographic review remain stable-release blockers.

Development

See docs/RUNBOOK.md for prerequisites, validation, benchmarks, and troubleshooting. AI contributors must also follow AGENTS.md. The fail-closed stable evidence format and verifier are documented in evidence/README.md; no prerelease tree can pass scripts/stable-gate.ps1.

License

Licensed under either Apache-2.0 or MIT, at your option. See LICENSE-APACHE and LICENSE-MIT.

About

Experimental, unaudited Rust transport SDK with multiplexed TCP/UDP, Noise XX authentication, bounded state, and typed network-only fallback.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages