[PR #6714] [client] Recover from rosenpass key desync #29829

Closed
opened 2026-08-05 08:09:05 -04:00 by saavagebueno · 0 comments
Owner

Original Pull Request: https://github.com/netbirdio/netbird/pull/6714

State: closed
Merged: Yes


Describe your changes

Recovers WireGuard tunnels that stay down after the rosenpass-managed preshared keys desync between two peers. Because the rosenpass renewal exchange runs over the tunnel that the preshared key itself secures, a desync cannot self-repair: the dead tunnel blocks the very exchange that would fix it. Two independent mechanisms restore convergence:

  • On key expiry without a completed renewal, both ends derive an identical replacement key without communicating: first a ratchet step from the last shared key (preserving post-quantum secrecy against a renewal-blocking attacker), then a fall back to the rendezvous key (account preshared key, or the deterministic seed key) on repeated failure.
  • After repeated consecutive WireGuard handshake timeouts, the peer's rosenpass state is reset so the next connection configuration reprograms the rendezvous key.
  • The fallback key matches what a fresh connection programs for a not-yet-established peer, so a reconnect converges both ends.

Note: recovery requires both ends to run this change. A peer on an older version that latched a one-sided key cannot be recovered from the remote side until it restarts or upgrades. Expiry timers on the two ends are not synchronized, so there can be a brief window where the ends hold different keys before the next expiry converges them.

Stack

  • 0.74.4-branch - ⚠️ No PR associated with branch

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Internal recovery behavior with no user-facing configuration or API surface.

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • New Features

    • Improved connection recovery by automatically reacting to repeated handshake timeouts.
    • Added more resilient key handling during peer reconnection, including fallback behavior when synchronization is lost.
  • Bug Fixes

    • Handshake monitoring now resets timeout tracking after a successful check, reducing unnecessary disconnects.
    • Peer state is preserved more reliably when peers are re-added or recover after expiry.
**Original Pull Request:** https://github.com/netbirdio/netbird/pull/6714 **State:** closed **Merged:** Yes --- ## Describe your changes Recovers WireGuard tunnels that stay down after the rosenpass-managed preshared keys desync between two peers. Because the rosenpass renewal exchange runs over the tunnel that the preshared key itself secures, a desync cannot self-repair: the dead tunnel blocks the very exchange that would fix it. Two independent mechanisms restore convergence: - On key expiry without a completed renewal, both ends derive an identical replacement key without communicating: first a ratchet step from the last shared key (preserving post-quantum secrecy against a renewal-blocking attacker), then a fall back to the rendezvous key (account preshared key, or the deterministic seed key) on repeated failure. - After repeated consecutive WireGuard handshake timeouts, the peer's rosenpass state is reset so the next connection configuration reprograms the rendezvous key. - The fallback key matches what a fresh connection programs for a not-yet-established peer, so a reconnect converges both ends. Note: recovery requires both ends to run this change. A peer on an older version that latched a one-sided key cannot be recovered from the remote side until it restarts or upgrades. Expiry timers on the two ends are not synchronized, so there can be a brief window where the ends hold different keys before the next expiry converges them. ## Issue ticket number and link ## Stack - `0.74.4-branch` - :warning: No PR associated with branch <!-- branch-stack --> - \#6714 :point\_left: ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) - [x] This change does **not** modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — **OR** I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first). > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) Internal recovery behavior with no user-facing configuration or API surface. ### Docs PR URL (required if "docs added" is checked) Paste the PR link from <https://github.com/netbirdio/docs> here: <https://github.com/netbirdio/docs/pull/>\_\_ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved connection recovery by automatically reacting to repeated handshake timeouts. - Added more resilient key handling during peer reconnection, including fallback behavior when synchronization is lost. - **Bug Fixes** - Handshake monitoring now resets timeout tracking after a successful check, reducing unnecessary disconnects. - Peer state is preserved more reliably when peers are re-added or recover after expiry. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
saavagebueno added the pull-request label 2026-08-05 08:09:05 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#29829