netbird icon indicating copy to clipboard operation
netbird copied to clipboard

[client] Fall through dns chain for custom dns zones

Open lixmal opened this issue 1 month ago • 2 comments

Describe your changes

Custom zones act as "overlays". You define specific records while unmatched queries in that zone fall through to lower-priority handlers (DNS routes, upstream). Without this, the local resolver claims authority over the entire zone and returns NXDOMAIN for any record it doesn't have, blocking CNAMEs from resolving via other handlers.

Issue ticket number and link

Stack

Checklist

  • [ ] Is it a bug fix
  • [ ] Is a typo/documentation fix
  • [x] Is a feature enhancement
  • [ ] It is a refactor
  • [x] 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
  • [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/__

lixmal avatar Jan 09 '26 16:01 lixmal

📝 Walkthrough

Walkthrough

The changes refactor DNS zone handling by replacing the SkipPTRProcess flag with NonAuthoritative, updating the local resolver's zone storage from a slice to a map, refactoring the Update API to accept CustomZone objects instead of separate records and zones parameters, and introducing fallthrough behavior for non-authoritative zones while clearing DNS Zero bits to prevent external signaling interference.

Changes

Cohort / File(s) Summary
DNS Zone Definition & Protocol
dns/dns.go, shared/management/proto/management.proto, management/internals/shared/grpc/conversion.go
Replaced SkipPTRProcess bool field with NonAuthoritative bool field in CustomZone struct across proto definition and conversion logic. Updated proto message and grpc conversion to map the new field.
DNS PTR Collection Logic
client/internal/dns.go
Changed zone filter condition in collectPTRRecords from checking SkipPTRProcess to checking NonAuthoritative when deciding which zones to evaluate for PTR record creation.
DNS Local Resolver Core
client/internal/dns/local/local.go
Transformed zones storage from slice ([]domain.Domain) to map (map[domain.Domain]bool) with bool indicating non-authoritative status. Refactored Update API from Update([]nbdns.SimpleRecord, []domain.Domain) to Update([]nbdns.CustomZone). Added zone lookup helpers (findZone, shouldFallthrough, continueToNext) and introduced fallthrough behavior in ServeDNS for non-authoritative zones via NXDOMAIN responses with Zero bit signaling.
DNS Local Resolver Tests
client/internal/dns/local/local_test.go
Updated all Update API calls to use new CustomZone-based signature. Added test coverage for fallthrough behavior with case-insensitive domain matching and benchmark tests for zone lookup performance.
DNS Server Configuration
client/internal/dns/server.go
Updated buildLocalHandlerUpdate signature from returning ([]handlerWrapper, []nbdns.SimpleRecord, []domain.Domain, error) to ([]handlerWrapper, []nbdns.CustomZone, error). Simplified local resolver update call to use unified CustomZone objects, removing separate localRecords/zones handling.
DNS Server Tests
client/internal/dns/server_test.go
Refactored test inputs from SimpleRecord-based to CustomZone-based structures and updated all resolver Update calls to match new API signature.
Upstream DNS Response Handling
client/internal/dns/upstream.go, client/internal/routemanager/dnsinterceptor/handler.go
Added clearing of Zero bit in DNS message header after response processing to prevent external upstream servers from interfering with internal fallthrough signaling.
Engine Configuration
client/internal/engine.go
Added backward compatibility logic for single custom zone scenarios: computes NonAuthoritative as zone.GetNonAuthoritative() && !singleZoneCompat, treating single zones as authoritative regardless of flag.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant LocalResolver as Local DNS Resolver
    participant UpstreamResolver as Upstream Resolver
    
    Client->>LocalResolver: Query for non-authoritative zone
    LocalResolver->>LocalResolver: findZone(qname)
    alt Zone found and non-authoritative
        LocalResolver->>LocalResolver: Check NXDOMAIN condition
        LocalResolver->>Client: Return NXDOMAIN + set Zero bit (fallthrough signal)
        Client->>UpstreamResolver: Forward to next handler (Zero bit triggers fallthrough)
        UpstreamResolver->>UpstreamResolver: Clear Zero bit to prevent cascading signals
        UpstreamResolver->>Client: Return upstream response
    else Zone found and authoritative
        LocalResolver->>LocalResolver: Serve from local records
        LocalResolver->>Client: Return response
    else Zone not found
        LocalResolver->>UpstreamResolver: Forward to next handler
        UpstreamResolver->>Client: Return response
    end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • netbirdio/netbird#4826: Introduces and modifies the SkipPTRProcess/NonAuthoritative flag behavior in CustomZone and adjusts PTR collection filtering logic—directly related to the zone classification refactoring.
  • netbirdio/netbird#4774: Updates DNS CustomZone handling in grpc conversion by mapping the NonAuthoritative field—code-level overlap with proto and conversion changes.

Suggested reviewers

  • mlsmaycon

Poem

🐰 A rabbit's DNS hop so spry,
From skipping zones to truth we spy,
NonAuthoritative marks the way,
Fallthrough signals won't delay,
Zero bits cleared, responses fly! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature: implementing fall-through behavior for custom DNS zones in the client DNS resolver.
Description check ✅ Passed The description provides a clear rationale for the change (custom zones as overlays), confirms feature enhancement and test additions, and explains why documentation is not needed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • [ ] 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Jan 09 '26 16:01 coderabbitai[bot]