Handshake anti-replay + authenticated endpoint (#34) #99
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
femboy/yip!99
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/handshake-anti-replay-34"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #34.
Adds a WireGuard-style anti-replay token to the Noise-IK handshake and makes endpoint learning authenticated, closing the on-path Init-replay endpoint-hijack and letting an Established responder safely rebuild on a genuine peer restart. This is the anchor that retires the #36 accepted-downgrade tradeoff.
Design
A 12-byte TAI64N wall-clock timestamp (8-byte BE
2^62+unix_secs‖ 4-byte BE nanos — byte-comparable = chronological) is prefixed to the msg1 cert payload and rides inside the encrypted Noise payload — no new cleartext field, no wire-format change, no anti-DPI fingerprint (yip-crypto / yip-wire untouched).Per-peer
last_accepted_init_ts+accept_fresh_init(ts > last)becomes the single "build a new session" discriminator, replacing the 9aaccept_rekey_initage gate (removed fromepoch.rs). Consequences:DispatchOut::None).peers[idx].endpoint = Some(src)is behind the gate on the cold-start arm; the rekey path never writes endpoint. Off-path replay can't hijack a peer's endpoint.#36 retired / inverted: on path escalation the peer now draws a fresh ephemeral (state→Idle →
begin_handshake) instead of preserving its in-flight one;retarget_handshakeis deleted; relay adoption is re-gated on!relay && last_accepted_init_ts.is_some() && new-ephemeral && accept_fresh_init. A replayed escalation Init can no longer downgrade a direct peer to relay.Tasks
handshake.rs, pure/unit-tested)[ts‖cert]into msg1 build + responder stripby_tageviction on rebuildTesting
yipdunit tests;clippy -D warnings+cargo fmtclean;#![forbid(unsafe_code)].YIP_USE_URING=1):run-netns-replay-hijack.sh(0% loss across the replay, freshness-gate refusal marker observed, restart reconverged) andrun-netns-pathswitch-rehandshake.sh(fresh-ephemeral rebuild, ≥98% convergence, relay-forwarded>0). Both wired into CI.Final whole-branch opus review: READY WITH FOLLOW-UPS, no Critical/Important — the admission tree, endpoint gating, #36 downgrade closure, and #41/#91 interactions all traced clean.
Follow-ups (non-blocking)
peers[idx].endpointis not relearned on the fresh-ts rebuild, so B's own initiator-role rekeys keep targeting the dead address until an A-initiated rekey recovers. Data plane never black-holes (direct egress is stamped fromDataPlane.peer_addr, notendpoint). Pre-existing; relearn endpoint on a fresh-ts rebuild.