We clock the next Offer initiation to the OnDataPathRekeyed, so we have 2 minutes
ahead of us to do our attempts and stuff before to give up.
On failure, we will know because we will not receive a new answer.. but more importantly
the wg handshake will fail :D
Define OnDataPathRekeyed event to transition from control plane path to data plane path over the WG tunnel.
Keep confirm ALWAYS on NEW established WG tunnel (posthandshake with rekeying). We keep an active method
irrelevant of the WG handshake (we might decide that the indirect wg handshake is sufficient in the future).
Optimistic commit on responder(when sending answer), while on initiator we set it on getting the answer
- Have just one manager => one lock
- Session state is needed in driver to => we have it available now.
- Isomorphically align to rosenpass components and functionality
File Role rosenpass equivalent
kem.go primitive pure X25519MLKEM768 crypto.go/handshake
message.go Offer/Answer/Confirm + Encode/Decode messages.go
manager.go Manager stateful, single lock server logic
callbacks.go WGCallbackHandler (seam output) Handler
Transport (interfaccia) seam trasporto pluggable Conn
## Describe your changes
Removes redundant `Login` RPCs from the iOS SDK bindings.
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [x] 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](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)
### 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/__
<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6931"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1787779607&installation_model_id=427504&pr_number=6931&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6931&signature=ce1631be2a5ffdba58c44b4669b0d480dc9f956102cf10a0c7b5845a800cdc68"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>
<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added an interactive iOS login option that starts authentication
directly when needed.
* Improved login flow handling, including clearer error reporting and
successful-login notifications.
* Login configuration is now saved automatically after successful
authentication when applicable.
* **Bug Fixes**
* Prevented duplicate login requests during iOS startup.
* Improved startup behavior and error propagation when the management
service is unavailable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Removes redundant `Login` RPCs from the iOS SDK bindings. Both changed
files are behind
the `ios` build tag — Android, desktop and the shared core are not
affected.
### Problem
`auth.Auth.IsLoginRequired()` is not a cheap probe: it calls
`doMgmLogin()` and classifies
the resulting error, so every "is login required?" check costs a **full
`Login` RPC**. There
is no lighter way to ask. As a result the iOS client issued ~7 `Login`
requests before the
first `Sync`, where Android issues ~3, and the extra ones were
indistinguishable from real
logins in the management logs.
Three of those came from this package:
1. `Run()` called `LoginSync()` before starting the engine, which
performs `IsLoginRequired`
**and** `Login` — two RPCs. This duplicated the engine's own
`loginToManagement`
(`client/internal/connect.go`), which runs immediately before the first
`Sync` and is the
authoritative login. The `Login(ctx, "", "")` inside `LoginSync` could
not even establish
anything: with an empty setup key and empty JWT, a registration attempt
fails by
construction, so it was a pure check.
2. `Auth.login()` called `IsLoginRequired()` again before opening the
browser, even when the
caller had already determined that login is needed.
This is not only wasted traffic:
- **It pushes peers toward the server-side login ban.** In
`management/internals/shared/grpc/loginfilter.go`, every login with
unchanged metadata
increments `sessionCounter`, and exceeding `reconnLimitForBan` (30)
within
`reconnThreshold` (5 min) bans the peer for `baseBlockDuration` (10
min), doubling on
repeat. Redundant logins carry identical metadata, so they count against
exactly this
budget. At 7 logins per connect the budget is exhausted after ~4
reconnects instead of
~10 — reachable on flaky mobile networks.
- **Each redundant check is a potential 2-minute stall.**
`IsLoginRequired` retries with
backoff up to `MaxElapsedTime` (2 min) and returns `true` on failure, so
an unreachable
server was reported as "login required" rather than as a timeout, and
the `LoginSync`
pre-flight could abort engine startup on that basis.
### Changes
**`client/ios/NetBirdSDK/client.go`** — `Run()` no longer performs the
`LoginSync()`
pre-flight. The engine's `loginToManagement` remains the single
authoritative login.
**`client/ios/NetBirdSDK/login.go`** — new exported `LoginInteractive`,
which skips the
`IsLoginRequired()` pre-flight and goes straight to the browser /
device-code flow, for
callers that have already established login is required.
`LoginWithDeviceName` keeps the
check for callers where the auth state is unknown (tvOS). Both now
delegate to a shared
`startLogin()`.
### Why this is safe
An expired or revoked session still fails the connection, one step later
and through a
single path: `loginToManagement` returns `PermissionDenied` → the
deferred
`MarkManagementDisconnected` records it on the shared status recorder →
`ClientStop` fires
the listener's disconnect callback, where `IsLoginRequiredCached()`
reports login-required →
the client tears the tunnel down. The error is also returned out of
`Run()`.
Where the server is unreachable, the engine now retries with backoff and
recovers on its
own instead of aborting the start.
Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com>
## Describe your changes
`getInterfaceIndex` in the iOS upstream DNS resolver dereferenced the
result of `net.InterfaceByName` before checking the error, so a missing
interface (e.g. during teardown or renaming) caused a nil-pointer panic
instead of a DNS client error.
The helper now returns a wrapped error before touching the interface;
the only caller, `GetClientPrivate`, already propagates the error.
The helper moved to an un-build-tagged file so it can be unit-tested on
host platforms while remaining available to the iOS build. Added a test
covering the missing-interface path. Verified with the new host test, an
iOS arm64 CGO compile, and `git diff --check`.
## Issue ticket number and link
N/A
## Stack
<!-- branch-stack -->
Standalone PR based on `main`.
### 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 crash fix in the iOS DNS path; no user-facing behavior or
configuration changes.
### Docs PR URL (required if "docs added" is checked)
N/A
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved handling of network interface lookup failures with clearer
error messages that identify the affected interface.
* Added validation for network interface lookups, including reliable
error handling when an interface cannot be found.
* **Tests**
* Added coverage for both successful interface resolution and
missing-interface scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Describe your changes
[#7009](https://github.com/netbirdio/netbird/pull/7009) wrote down what
we expect
from a contribution: an agreed ticket first, a change the author has
run, one
purpose per PR, small enough to review, a title tag CI already enforces.
That
works for contributors who read CONTRIBUTING.md.
A growing share of what reaches the queue is drafted by a coding agent,
and those
tools never read it. The result is predictable and repetitive: a PR with
no ticket
behind it, an approach we would have talked the author out of in five
minutes, a
diff too large to review carefully against a daemon that runs as root, a
description longer than the code it describes, and an author who cannot
answer
questions about their own change. That is not a tooling problem. It is
what
happens when a capable tool is pointed at a repository whose
expectations nobody
told it.
AGENTS.md states those expectations in the format agents pick up
automatically.
The first entry in its stop-and-ask list is asking the contributor for
the
discussion or issue before drafting anything, which is where most of
these PRs
go wrong. It also carries the repository map, the Go conventions we
apply in
review, the local verification commands, the PR template and title-tag
rules,
and instructions to read the review bots rather than resolve their
threads.
CONTRIBUTING.md gains a short section saying plainly that we have no
policy for
or against agents, that this guide exists because of what we keep seeing
rather
than as a restriction on tools, and that whatever produced a diff its
author owns
it. It also records that we weigh whether a contribution is worth
maintaining,
and that what gets merged has to match our security and design
expectations.
CLAUDE.md is a one-line pointer rather than a symlink, deliberately. A
symlink is
tidier, but a Windows checkout without symlink support materialises it
as a plain
file containing the target path, and an agent then reads one word as its
entire
instruction set with no error to show for it. Given how much Windows
work this
repository sees, a pointer file that survives every checkout is worth
the extra
file.
Nothing here is enforced by CI, and no workflow changes. It is guidance,
aimed at
PRs arriving in a reviewable state more often.
## Describe your changes
We are updating the contributing guide to require an issue to be opened
before PRs; this will allow discussing changes before code is shipped.
Update the rest of the file because of outdated information and align
the pull request template
## Issue ticket number and link
## Describe your changes
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [ ] Is it a bug fix
- [x] 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](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)
### 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
* **Documentation**
* Expanded the security vulnerability reporting policy with private
reporting options and guidance for hosted infrastructure issues.
* Added recommendations for report contents, acknowledgements, severity
assessment, remediation, advisories, and reporter credit.
* Clarified supported versions, advisory distribution, bug bounty
status, and where to report non-security issues.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Describe your changes
`NB_LAZY_CONN_INACTIVITY_THRESHOLD` was parsed with `strconv.Atoi`, i.e.
as a bare
integer number of minutes. The documentation, however, states it takes a
Go duration
(e.g. `30m`, `1h`). As a result any documented value such as `30m` or
`5m` failed to
parse and **silently fell back to the 15m default**, so the setting
appeared to have
no effect.
`inactivityThresholdEnv()` now parses the value with
`time.ParseDuration`, matching
the docs. A bare integer is still accepted as a number of minutes for
backwards
compatibility, and an unparseable value logs a warning and falls back to
the default.
Added `TestInactivityThresholdEnv` covering Go-duration values
(`30m`/`1h`/`90s`), the
bare-integer minutes fallback, and zero/negative/garbage inputs.
## Issue ticket number and link
N/A
On iOS the tunnel reconfiguration (setTunnelNetworkSettings) was driven
from three independent Go paths without serialization: route prefix
updates via the route notifier's own delivery loop, interface IP/IPv6
set synchronously from the engine start goroutine, and DNS config
applied from the DNS apply chain through a separate Swift object. The
three sources mutated the shared Swift settings-manager state
concurrently and triggered overlapping updateTunnel() calls, losing or
half-applying route and DNS settings.
Introduce client/internal/tunnelnotifier: a single notifier that
implements both listener.NetworkChangeListener and dns.IosDnsManager,
queues all four callbacks (OnNetworkChanged, SetInterfaceIP,
SetInterfaceIPv6, ApplyDns) in one FIFO and delivers them one-by-one
from a single goroutine, so calls into Swift never overlap and arrive in
order. RunOniOS wraps the two Swift objects into the notifier and closes
it after the run loop exits.
The route notifier keeps its prefix dedup but delegates delivery to the
shared notifier instead of maintaining its own queue and loop; the dedup
check and the enqueue stay under one mutex so queue order matches
state-update order. Setting the interface IP becomes asynchronous, which
is safe: on iOS wgInterface.Create() only uses the TunFd, and the FIFO
preserves the IP -> routes/DNS relative order.
The package is build-tag free so the unit tests run on any platform
under -race. Android is unaffected: it receives all settings atomically
in one configureInterface call and serializes TUN rebuilds on a single
handler thread.
## Describe your changes
## Issue ticket number and link
## 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)
- [ ] 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)
### 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/__
<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6870"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1787404610&installation_model_id=427504&pr_number=6870&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6870&signature=7db66c4ec4262cc21137b3d3e1fd5e905950eab82ef46236a13ac3d512ff2a16"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>
<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Improved iOS tunnel networking by coordinating network, interface,
route, and DNS updates through a unified notifier.
* Updated iOS behavior so route/prefix changes are applied immediately
instead of via queued/background delivery.
* **Bug Fixes**
* Improved reliability by ensuring network and DNS-related callbacks are
invoked in order without overlap.
* Ensured pending updates are drained and handled correctly during
shutdown.
* **Tests**
* Added coverage for FIFO ordering, non-overlapping callback execution,
interleaved DNS/route updates, and graceful shutdown behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->