[PR #6136] [client] Improve rosenpass support #27605

Open
opened 2026-08-05 07:08:57 -04:00 by saavagebueno · 0 comments
Owner

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

State: closed
Merged: Yes


Describe your changes

This PR bundles several related changes to the Rosenpass support in the
client agent:

  1. Bump cunicu.li/go-rosenpass from v0.4.0 to v0.5.42. The upstream
    library was pinned at a release from September 2023, ~40 releases behind
    the current upstream. The bump pulls in protocol fixes from upstream
    (resolves the recurring failed to load biscuit (ICR1): detected replay slog errors observed in production). Transitive bumps:

    • cilium/ebpf 0.15 → 0.19,
    • gopacket/gopacket 1.1.1 → 1.4.0,
    • wireguard/wgctrl updated. Wire-protocol interop between v0.4.0 and
      v0.5.42 verified end-to-end (cross-version handshake works), so no
      flag-day rollout is required.
  2. Fix nil-receiver crash on Android (#4341). When Engine.Run() had
    not completed before OnConnected fired, m.rpWgHandler was nil and
    m.rpWgHandler.AddPeer(...) in addPeer panicked. NewManager now
    pre-initializes rpWgHandler, and addPeer has explicit nil guards
    for both m.server and m.rpWgHandler as defense in depth.
    generateConfig keeps replacing the handler on each Run() so peer
    state from previous engine sessions is not retained.

  3. Normalize peer endpoint to IPv4-mapped IPv6. The Rosenpass UDP
    server binds on the IPv6 wildcard [::] and net.ResolveUDPAddr returns
    a 4-byte IPv4 for IPv4 hosts, which the kernel rejected with EDESTADDRREQ
    on Linux when the lib called sendto from the AF_INET6 socket. The
    initiator path in addPeer now converts the remote endpoint to
    IPv4-mapped IPv6 so its family matches the listening socket.

  4. Move rosenpassDetermKey into the rosenpass package as the
    exported DeterministicSeedKey, closing the // todo: move this logic into Rosenpass package left at conn.go:911. While moving:

    • Replace append(lk[:16], rk[:16]...) with append onto an empty
      slice so the //nolint:gocritic suppression is no longer needed.
    • Validate input length (>= 16 bytes) so the function returns an
      error instead of panicking on out-of-range slicing.
    • Wrap returned errors with package-scoped context.
    • Doc comment makes explicit that the seed is deterministic and not
      post-quantum safe; Rosenpass replaces it with a real PQ PSK on
      first rotation.
  5. Decouple rp.Server behind an rpServer interface so the manager
    can be exercised without spinning up a real UDP server, and add unit
    tests covering the initiator/responder tie-break, peer lifecycle,
    PSK rotation updateOnly semantics, error propagation, and the new
    nil-guard branches.

GitHub: https://github.com/netbirdio/netbird/issues/4341

Stack

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)

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 change only. The public NetBird CLI/API surface and the Rosenpass
feature behavior are unchanged: the dependency bump is transparent to users
(wire-compatible with v0.4.0), the nil-guard prevents a crash without
altering normal flow, the endpoint normalization restores the intended send
behavior on Linux, and the function move/refactor preserves inputs, outputs,
and call semantics.

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

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

N/A

Summary by CodeRabbit

  • New Features

    • Deterministic preshared-key generation added for peer handshakes.
  • Bug Fixes

    • Prevented panics by initializing internal handlers earlier and returning explicit errors when components are unready.
    • Normalized IPv4 endpoints to IPv6-mapped form for consistent connectivity.
  • Tests

    • Expanded test suite covering key derivation, manager/handler behaviors, endpoint selection, and edge cases.
  • Chores

    • Updated several dependencies (Rosenpass, WireGuard, eBPF, packet libraries).

Review Change Stack

**Original Pull Request:** https://github.com/netbirdio/netbird/pull/6136 **State:** closed **Merged:** Yes --- ## Describe your changes This PR bundles several related changes to the Rosenpass support in the client agent: 1. **Bump `cunicu.li/go-rosenpass` from v0.4.0 to v0.5.42.** The upstream library was pinned at a release from September 2023, ~40 releases behind the current upstream. The bump pulls in protocol fixes from upstream (resolves the recurring `failed to load biscuit (ICR1): detected replay` slog errors observed in production). Transitive bumps: - `cilium/ebpf` 0.15 → 0.19, - `gopacket/gopacket` 1.1.1 → 1.4.0, - `wireguard/wgctrl` updated. Wire-protocol interop between v0.4.0 and v0.5.42 verified end-to-end (cross-version handshake works), so no flag-day rollout is required. 2. **Fix nil-receiver crash on Android (#4341).** When `Engine.Run()` had not completed before `OnConnected` fired, `m.rpWgHandler` was nil and `m.rpWgHandler.AddPeer(...)` in `addPeer` panicked. `NewManager` now pre-initializes `rpWgHandler`, and `addPeer` has explicit nil guards for both `m.server` and `m.rpWgHandler` as defense in depth. `generateConfig` keeps replacing the handler on each `Run()` so peer state from previous engine sessions is not retained. 3. **Normalize peer endpoint to IPv4-mapped IPv6.** The Rosenpass UDP server binds on the IPv6 wildcard `[::]` and `net.ResolveUDPAddr` returns a 4-byte IPv4 for IPv4 hosts, which the kernel rejected with `EDESTADDRREQ` on Linux when the lib called `sendto` from the AF_INET6 socket. The initiator path in `addPeer` now converts the remote endpoint to IPv4-mapped IPv6 so its family matches the listening socket. 4. **Move `rosenpassDetermKey` into the `rosenpass` package** as the exported `DeterministicSeedKey`, closing the `// todo: move this logic into Rosenpass package` left at `conn.go:911`. While moving: - Replace `append(lk[:16], rk[:16]...)` with `append` onto an empty slice so the `//nolint:gocritic` suppression is no longer needed. - Validate input length (`>= 16` bytes) so the function returns an error instead of panicking on out-of-range slicing. - Wrap returned errors with package-scoped context. - Doc comment makes explicit that the seed is deterministic and **not** post-quantum safe; Rosenpass replaces it with a real PQ PSK on first rotation. 5. **Decouple `rp.Server` behind an `rpServer` interface** so the manager can be exercised without spinning up a real UDP server, and add unit tests covering the initiator/responder tie-break, peer lifecycle, PSK rotation `updateOnly` semantics, error propagation, and the new nil-guard branches. ## Issue ticket number and link GitHub: <https://github.com/netbirdio/netbird/issues/4341> ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [x] It is a refactor - [ ] Created tests that fail without the change (if possible) > 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 change only. The public NetBird CLI/API surface and the Rosenpass feature behavior are unchanged: the dependency bump is transparent to users (wire-compatible with v0.4.0), the nil-guard prevents a crash without altering normal flow, the endpoint normalization restores the intended send behavior on Linux, and the function move/refactor preserves inputs, outputs, and call semantics. ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Deterministic preshared-key generation added for peer handshakes. * **Bug Fixes** * Prevented panics by initializing internal handlers earlier and returning explicit errors when components are unready. * Normalized IPv4 endpoints to IPv6-mapped form for consistent connectivity. * **Tests** * Expanded test suite covering key derivation, manager/handler behaviors, endpoint selection, and edge cases. * **Chores** * Updated several dependencies (Rosenpass, WireGuard, eBPF, packet libraries). <!-- review_stack_entry_start --> [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/netbirdio/netbird/pull/6136) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
saavagebueno added the pull-request label 2026-08-05 07:08:57 -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#27605