[PR #6233] [MERGED] [client] filter A/AAAA answers pointing at disconnected peers #27820

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

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6233
Author: @mlsmaycon
Created: 5/21/2026
Status: Merged
Merged: 5/25/2026
Merged by: @mlsmaycon

Base: feat/private-service-expose-publicHead: feat/private-service-expose-client-dns


📝 Commits (1)

  • 0d45ad4 feat(dns/local): filter A/AAAA answers pointing at disconnected peers

📊 Changes

3 files changed (+253 additions, -0 deletions)

View changed files

📝 client/internal/dns/local/local.go (+100 -0)
📝 client/internal/dns/local/local_test.go (+126 -0)
📝 client/internal/dns/server.go (+27 -0)

📄 Description

Describe your changes

When the local resolver hands back records for a query, walk the A/AAAA answers and consult a connectivity checker keyed by IP. Records whose RDATA points at a known-but-disconnected peer are dropped from the answer. Records pointing at unknown IPs (anything outside the local peerstore) pass through untouched.

Motivation: synthesised private-service zones emit one A record per connected proxy peer in a cluster. The management side now refreshes the netmap whenever a proxy peer flips state, but the client may still hold a stale netmap for a short window. This is the client-side belt to that braces — even on the stale data, the resolver hides records pointing at peers that the local peerstore reports offline.

Escape hatch: if filtering would empty the answer entirely AND at least one record was dropped, the original list is restored. Better to hand the client a record that may not respond than NXDOMAIN it completely when every proxy in the cluster is offline (the upstream may still be reachable some other way, or the peerstore may be stale).

  • local.PeerConnectivity interface: IsConnectedByIP(ip) (known, connected).
  • Resolver.SetPeerConnectivity wires the source (nil = disabled, the legacy "return everything" default).
  • ServeDNS runs filterDisconnectedPeerAnswers between lookupRecords and the reply assembly; extractRecordIP pulls IP from A/AAAA only, other record types pass through.
  • server.go adapter localPeerConnectivity wraps *peer.Status and reports connected when ConnStatus == StatusConnected.
  • New tests cover the four cases: drop disconnected, pass unknown, fallback when all disconnected, and no-op when no checker is wired.

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)
  • 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)

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

    • DNS resolver now filters out local A/AAAA answers for peers that are not currently connected, preventing users from resolving IP addresses for unavailable peers.
  • Tests

    • Added comprehensive test coverage for DNS filtering behavior, including handling of mixed connectivity states and fallback scenarios.

Review Change Stack


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6233 **Author:** [@mlsmaycon](https://github.com/mlsmaycon) **Created:** 5/21/2026 **Status:** ✅ Merged **Merged:** 5/25/2026 **Merged by:** [@mlsmaycon](https://github.com/mlsmaycon) **Base:** `feat/private-service-expose-public` ← **Head:** `feat/private-service-expose-client-dns` --- ### 📝 Commits (1) - [`0d45ad4`](https://github.com/netbirdio/netbird/commit/0d45ad453a5bce1106d3e92aacaff31de28b378f) feat(dns/local): filter A/AAAA answers pointing at disconnected peers ### 📊 Changes **3 files changed** (+253 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `client/internal/dns/local/local.go` (+100 -0) 📝 `client/internal/dns/local/local_test.go` (+126 -0) 📝 `client/internal/dns/server.go` (+27 -0) </details> ### 📄 Description ## Describe your changes When the local resolver hands back records for a query, walk the A/AAAA answers and consult a connectivity checker keyed by IP. Records whose RDATA points at a known-but-disconnected peer are dropped from the answer. Records pointing at unknown IPs (anything outside the local peerstore) pass through untouched. Motivation: synthesised private-service zones emit one A record per connected proxy peer in a cluster. The management side now refreshes the netmap whenever a proxy peer flips state, but the client may still hold a stale netmap for a short window. This is the client-side belt to that braces — even on the stale data, the resolver hides records pointing at peers that the local peerstore reports offline. Escape hatch: if filtering would empty the answer entirely AND at least one record was dropped, the original list is restored. Better to hand the client a record that may not respond than NXDOMAIN it completely when every proxy in the cluster is offline (the upstream may still be reachable some other way, or the peerstore may be stale). - local.PeerConnectivity interface: IsConnectedByIP(ip) (known, connected). - Resolver.SetPeerConnectivity wires the source (nil = disabled, the legacy "return everything" default). - ServeDNS runs filterDisconnectedPeerAnswers between lookupRecords and the reply assembly; extractRecordIP pulls IP from A/AAAA only, other record types pass through. - server.go adapter localPeerConnectivity wraps *peer.Status and reports connected when ConnStatus == StatusConnected. - New tests cover the four cases: drop disconnected, pass unknown, fallback when all disconnected, and no-op when no checker is wired. ## Issue ticket number and link ## Stack <!-- branch-stack --> ### Checklist - [ ] Is it a bug fix - [ ] Is a typo/documentation fix - [x] 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 * **New Features** * DNS resolver now filters out local A/AAAA answers for peers that are not currently connected, preventing users from resolving IP addresses for unavailable peers. * **Tests** * Added comprehensive test coverage for DNS filtering behavior, including handling of mixed connectivity states and fallback scenarios. <!-- 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/6233?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 07:09:16 -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#27820