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.
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.
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 --helpProtect 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.
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.
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.
Licensed under either Apache-2.0 or MIT, at your option. See LICENSE-APACHE and
LICENSE-MIT.