Skip to content

fix: self-heal one-sided registrations across IP changes - #94

Merged
MegaManSec merged 1 commit into
mainfrom
fix/one-sided-introduce-self-heal
Aug 6, 2026
Merged

fix: self-heal one-sided registrations across IP changes#94
MegaManSec merged 1 commit into
mainfrom
fix/one-sided-introduce-self-heal

Conversation

@MegaManSec

Copy link
Copy Markdown
Owner

Closes the one-sided gap in #92's endpoint healing.

Problem

INTRODUCE healing rides the reachability poll, and the poll is driven by registered records. A Mac whose user never registered its peer (the half-configured state during setup, or after a one-sided remove) dials nothing — so when its IP changes, nothing carries the new address to the peer, and without Bonjour the peer keeps dialing the dead address until a manual re-add.

Fix

When nothing is registered, pollReachability now also introduces to discovered peers that have proved the current pairing key, on the same 30s cadence. The receiving side's source-IP ingest heals its registered record exactly as in the mutual case, and the reply refreshes this side's discovered entry so it survives the introduce TTL — the loop is self-sustaining while both Macs are up.

Guards:

  • Registered setups skip it entirely (networkDevices.isEmpty gate) — their poll already exchanges both ways, so no extra traffic in the normal case.
  • Self-addresses are skipped (Bonjour discovers this Mac's own service; without the filter it would dial itself every 30s).
  • Parked entries are skipped (no auth-fail spam at a peer whose key genuinely differs).
  • Key-proven only: same reasoning as the rename-migration gate — an impostor echoing our cleartext fp over Bonjour earns nothing but a failed handshake.

Remaining manual cases (both fundamental)

  • Both Macs changing IPs simultaneously with no Bonjour (no rendezvous point exists).
  • The half-configured Mac rebooting onto a new address — its discovered list is in-memory, so it has nothing to dial after relaunch.

Built clean with xcodebuild; swift-format clean.

Polling is driven by registered records, so a Mac whose user never
registered its peer dials nothing — and an IP change on that side never
reaches the peer's registered record; without Bonjour the peer keeps
dialing the old address until a manual re-add.

When nothing is registered, introduce to discovered peers that have
proved the current pairing key on the same 30s cadence. The receiver's
source-IP ingest heals its registered record, and the reply refreshes
this side's discovered entry so it survives the TTL. Self-addresses are
skipped (Bonjour discovers our own service), parked entries are skipped
(no auth-fail spam), and the fingerprint gate means an impostor echoing
our cleartext fp earns only a failed handshake.

Remaining manual cases, both fundamental: both Macs changing IPs at
once, and the half-configured Mac rebooting onto a new address (its
discovered list is in-memory).
@MegaManSec
MegaManSec merged commit 61b8e4c into main Aug 6, 2026
2 checks passed
@MegaManSec
MegaManSec deleted the fix/one-sided-introduce-self-heal branch August 6, 2026 13:03
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.25.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant