Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ae47d7e
docs(reality.5b): design spec — byte-matching ServerHello emission + …
vxfemboy Jul 17, 2026
c2d9099
docs(reality.5b): implementation plan (3 tasks, subagent-driven)
vxfemboy Jul 17, 2026
f78548e
feat(reality.5b): server_key_share — server-side KEX (ML-KEM Encapsul…
vxfemboy Jul 17, 2026
ae9578e
feat(reality.5b): emit_server_hello — byte-matching ServerHello + ser…
vxfemboy Jul 18, 2026
93acae3
fix(yip-utls): guard ServerHello body against u24 ceiling not u32::MA…
vxfemboy Jul 18, 2026
24d7e58
feat(reality.5b): extract client ML-KEM ek from ClientHello (for grou…
vxfemboy Jul 18, 2026
4155d72
test(reality.5b): distinct x25519 in 0x001d vs 4588 tail proves non-c…
vxfemboy Jul 18, 2026
7a7eacf
docs(reality.5c): design spec — encrypted server-flight emission + se…
vxfemboy Jul 18, 2026
107d9bf
docs(reality.5c): drop suite arg from sign_certificate_verify (review)
vxfemboy Jul 18, 2026
4aebf32
docs(reality.5c): implementation plan (6 tasks, subagent-driven)
vxfemboy Jul 18, 2026
ef6ab12
feat(reality.5c): expose server_hs_traffic on HandshakeKeys (server F…
vxfemboy Jul 18, 2026
9bee527
feat(reality.5c): record_seal_padded (TLS record padding); record_sea…
vxfemboy Jul 18, 2026
b568122
feat(reality.5c): sign_certificate_verify — signing mirror of the 4b …
vxfemboy Jul 18, 2026
54c643b
feat(reality.5c): emit_server_flight — assemble+seal+frame the encryp…
vxfemboy Jul 18, 2026
b3fbc18
refactor(reality.5c): role-agnostic RealityStream (egress/ingress) + …
vxfemboy Jul 18, 2026
be6277c
feat(reality.5c): serve — server flight + drain + stream; verify roun…
vxfemboy Jul 18, 2026
bf9a269
fix(reality.5c): frame flight so Finished lands in the last record (c…
vxfemboy Jul 18, 2026
4540366
docs(reality.5d): design spec — wire hand-rolled server flight into t…
vxfemboy Jul 18, 2026
bccad1a
docs(reality.5d): implementation plan (4 tasks, subagent-driven)
vxfemboy Jul 18, 2026
0fc86b0
feat(reality.5d): extract group-4588 x25519 tail from ClientHello (fo…
vxfemboy Jul 18, 2026
163673e
refactor(reality.5d): genericize handle_connection pump over AsyncRea…
vxfemboy Jul 18, 2026
a866d56
feat(reality.5d): serve hand-rolled 5b+5c flight on the authed path; …
vxfemboy Jul 18, 2026
4d70812
test(reality.5d): netns money test — verify=on client tunnels through…
vxfemboy Jul 18, 2026
3eb76ce
refactor(yip-utls): Error::MessageTooLarge + u24_len helper (5c follo…
vxfemboy Jul 19, 2026
52c84cf
fix(yip-rendezvous): hoist CertVerify signing-key load pre-write; spl…
vxfemboy Jul 19, 2026
559d5ff
test(reality.5d): group-29 dest authed e2e test; drop stale log-dump …
vxfemboy Jul 19, 2026
14d90ed
style(reality.5): rustfmt the follow-up cleanups (build-test fix)
vxfemboy Jul 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,34 @@ jobs:
echo "::error::two UDP-blocked peers failed to tunnel via the REALITY relay under verify=on (ping failed, relay-forwarded stayed 0, a wrong pbk/relay key was wrongly accepted, or the client retry-stormed on a verify failure) — REALITY.4a/4b relay-dial regression"
exit 1
fi

- name: Run the REALITY.5d hand-rolled-flight verify=on money test under sudo
# REALITY.5d's headline money test: same topology and assertions as
# the 4a/4b relay-over-REALITY test above (verify=on tunnel;
# wrong-pbk fail-closed), but proving the relay's AUTHED path now
# hand-rolls the entire server flight (`tls_front::run_reality_conn`
# `Decision::Accept` — REALITY.5b `emit_server_hello` + REALITY.5c
# `emit_server_flight`/`serve`) instead of driving a BoringSSL
# `SslAcceptor`. A passing verify=on ping here proves the hand-rolled
# flight completed AND the client's REALITY.4b binding check
# verified against the relay's forged leaf; the wrong-pbk variant
# proves the relay still splices to `--reality-dest`
# pre-ServerHello-write (never entering the hand-rolled emit path)
# when the seal fails to open. See run-netns-reality-5d.sh for the
# full topology and assertion set. Same binary requirements as the
# 4a/4b test above (release yipd, debug yip-rendezvous-bin).
run: |
sudo bash bin/yipd/tests/run-netns-reality-5d.sh \
"$(pwd)/target/release/yipd" \
"$(pwd)/target/debug/yip-rendezvous" | tee /tmp/relay-reality-5d-money-test.log
# Honesty guard, same reasoning as the oracles above: this job
# always runs as sudo and always builds both binaries, so a SKIP
# here means the harness itself is broken.
if grep -q "^SKIP run-netns-reality-5d" /tmp/relay-reality-5d-money-test.log; then
echo "::error::REALITY.5d money test skipped — expected root + built yipd/yip-rendezvous binaries in this job"
exit 1
fi
if grep -q "\[FAIL\]" /tmp/relay-reality-5d-money-test.log; then
echo "::error::verify=on client failed to tunnel via the REALITY relay's hand-rolled 5b+5c authed flight (ping failed, relay-forwarded stayed 0, or a wrong pbk was wrongly accepted) — REALITY.5d wiring regression"
exit 1
fi
15 changes: 7 additions & 8 deletions bin/yip-rendezvous/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,13 @@ time = { version = "0.3", default-features = false, features = ["parsing", "macr
# DER parsing, not the validate/verify/ring/aws-lc-rs signature-checking
# features (this crate never chain-validates the forged/stolen certs).
x509-parser = { version = "0.18.1", default-features = false }

[dev-dependencies]
# REALITY.4b Task 3 test-only: parses the SPKI DER `boring` hands back for a
# presented leaf's public key, to compare it (as a SEC1 point) against
# `yip_utls::auth::derive_cert_key`'s `public_sec1` — the leaf-pubkey-match
# gate for `build_forged_acceptor_with_pkcs8`. Same version yip-utls already
# depends on for the identical derivation; dev-only here so it adds no
# footprint to the shipped binary.
# REALITY.5d: loads the REALITY.4b shared-secret-derived ECDSA-P256 signing
# key (`yip_utls::auth::derive_cert_key`'s PKCS#8 DER) on the authed
# connection path (`tls_front::run_reality_conn`'s `Decision::Accept` branch)
# to sign the hand-rolled `CertificateVerify`. Promoted from dev-dependency
# (REALITY.4b Task 3 test-only use) now that it is also a production
# dependency; same version yip-utls already depends on for the identical
# derivation.
p256 = { version = "0.13", features = ["ecdsa", "pkcs8"] }

[lints]
Expand Down
14 changes: 7 additions & 7 deletions bin/yip-rendezvous/src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ const CLASSIFY_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(3);
/// anything else (a censor probe, a browser, garbage, silence) is
/// transparently reverse-proxied to the decoy backend, so the relay looks
/// like an ordinary web server to everyone but a real yip client.
pub async fn handle_connection<S>(mut stream: tokio_boring::SslStream<S>, cfg: Arc<TlsFrontCfg>)
pub async fn handle_connection<St>(mut stream: St, cfg: Arc<TlsFrontCfg>)
where
S: AsyncRead + AsyncWrite + Unpin + Send,
St: AsyncRead + AsyncWrite + Unpin + Send,
{
let now_ms = u64::try_from(cfg.base.elapsed().as_millis()).unwrap_or(u64::MAX);
// The relay is blind to the real TCP peer identity, and the TLS-only
Expand Down Expand Up @@ -143,14 +143,14 @@ where
/// Read the first frame (up to CLASSIFY_TIMEOUT) and classify it. Returns
/// `None` on idle-timeout/read-error (caller treats as decoy). All bytes read
/// are accumulated in `buf` so they can be replayed to the decoy.
async fn read_and_classify<S>(
stream: &mut tokio_boring::SslStream<S>,
async fn read_and_classify<St>(
stream: &mut St,
cfg: &TlsFrontCfg,
buf: &mut Vec<u8>,
now_ms: u64,
) -> Option<Classify>
where
S: AsyncRead + AsyncWrite + Unpin + Send,
St: AsyncRead + AsyncWrite + Unpin + Send,
{
let deadline = tokio::time::sleep(CLASSIFY_TIMEOUT);
tokio::pin!(deadline);
Expand Down Expand Up @@ -180,9 +180,9 @@ where

/// Proxy this connection to the decoy backend: replay the buffered bytes, then
/// splice bidirectionally. The decoy's own behavior/timing governs from here.
async fn into_decoy<S>(mut stream: tokio_boring::SslStream<S>, cfg: &TlsFrontCfg, buffered: Vec<u8>)
async fn into_decoy<St>(mut stream: St, cfg: &TlsFrontCfg, buffered: Vec<u8>)
where
S: AsyncRead + AsyncWrite + Unpin + Send,
St: AsyncRead + AsyncWrite + Unpin + Send,
{
let Some(decoy_addr) = cfg.decoy else {
// No decoy configured: minimal static fallback (documented weaker
Expand Down
10 changes: 3 additions & 7 deletions bin/yip-rendezvous/src/conn_tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,9 @@ const CHANNEL_DEPTH: usize = 64;
/// malformed frame is seen (fail-closed teardown). `prefix` carries any bytes
/// already read past the first (Register) frame during classification — a
/// pipelined second frame in the same TLS read must not be lost.
pub async fn run_tunnel<S>(
mut stream: tokio_boring::SslStream<S>,
cfg: Arc<TlsFrontCfg>,
node: NodeId,
prefix: Vec<u8>,
) where
S: AsyncRead + AsyncWrite + Unpin + Send,
pub async fn run_tunnel<St>(mut stream: St, cfg: Arc<TlsFrontCfg>, node: NodeId, prefix: Vec<u8>)
where
St: AsyncRead + AsyncWrite + Unpin + Send,
{
let (tx, mut rx) = mpsc::channel::<Vec<u8>>(CHANNEL_DEPTH);
// Keep an identity handle so the exit-time removal below can tell
Expand Down
Loading
Loading