9a follow-up: relay-path session rekey (relay-only sessions get no forward-secrecy rotation) #91

Closed
opened 2026-07-19 06:10:38 +00:00 by vxfemboy · 0 comments
vxfemboy commented 2026-07-19 06:10:38 +00:00 (Migrated from github.com)

Milestone 9a (#9, PR #90) rotates each peer's Noise-IK session ~every 120s, but relay-reached peers are deliberately gated out of rekey scheduling (drive_rekey_schedule returns early on relay).

Why they're gated out

Task 4 wired rekey completion only into the direct handshake handlers (handle_handshake_resp/handle_handshake_init), not the relay ones (relayed_handshake_init/relayed_handshake_resp). If relay peers were scheduled for rekey, the handshake would never complete → abandon after HANDSHAKE_TOTAL_MS → immediately restart (epoch still past the age threshold) → a continuous ~1 Hz [HandshakeInit] stream forever = wasted relay bandwidth + a constant-cadence DPI fingerprint. Gating relay peers out is the correct minimal fix; it leaves relay-only sessions without forward-secrecy rotation.

The work

Wire relay-path rekey completion so relay-reached peers rotate too:

  • relayed_handshake_init (Established arm) → accept_rekey_init gate + EpochSet::install_next (mirroring the direct handle_rekey_init, incl. the idempotent ephemeral-keyed cached-resp resend added in the 9a Critical fix — relay reordering makes idempotency more important here).
  • relayed_handshake_resp (currently drops anything against a non-Handshaking peer) → EpochSet::promote_from_rekey for an Established peer with a rekey in flight.
  • Remove the relay gate in drive_rekey_schedule once completion is wired.
  • Mind the relay dst-placeholder (server_addr()) + reordering semantics that differ from the direct path.
  • netns money test: a relay-forced topology (block direct/punch) that rotates loss-free over the relay.

Deferred from 9a to keep that milestone focused on the direct/punched path (the common case). See PR #90.

Milestone 9a (#9, PR #90) rotates each peer's Noise-IK session ~every 120s, but **relay-reached peers are deliberately gated out** of rekey scheduling (`drive_rekey_schedule` returns early on `relay`). ## Why they're gated out Task 4 wired rekey *completion* only into the **direct** handshake handlers (`handle_handshake_resp`/`handle_handshake_init`), not the relay ones (`relayed_handshake_init`/`relayed_handshake_resp`). If relay peers were scheduled for rekey, the handshake would never complete → abandon after `HANDSHAKE_TOTAL_MS` → immediately restart (epoch still past the age threshold) → a **continuous ~1 Hz `[HandshakeInit]` stream forever** = wasted relay bandwidth + a constant-cadence DPI fingerprint. Gating relay peers out is the correct minimal fix; it leaves relay-only sessions **without forward-secrecy rotation**. ## The work Wire relay-path rekey completion so relay-reached peers rotate too: - `relayed_handshake_init` (Established arm) → `accept_rekey_init` gate + `EpochSet::install_next` (mirroring the direct `handle_rekey_init`, incl. the **idempotent** ephemeral-keyed cached-resp resend added in the 9a Critical fix — relay reordering makes idempotency *more* important here). - `relayed_handshake_resp` (currently drops anything against a non-`Handshaking` peer) → `EpochSet::promote_from_rekey` for an Established peer with a rekey in flight. - Remove the relay gate in `drive_rekey_schedule` once completion is wired. - Mind the relay `dst`-placeholder (`server_addr()`) + reordering semantics that differ from the direct path. - netns money test: a relay-forced topology (block direct/punch) that rotates loss-free over the relay. Deferred from 9a to keep that milestone focused on the direct/punched path (the common case). See PR #90.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
femboy/yip#91
No description provided.