[client] Forward non-address DNS record types through route forwarders#6455
Conversation
…f NXDOMAIN fallthrough
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughAdds MX, TXT, NS, SRV, CNAME, and PTR DNS record handling in the client forwarding path. The forwarder now dispatches by query type, resutil builds records and rcodes, tests cover PTR parsing and response behavior, and intercepted domains are forwarded for all query types. ChangesDNS Record Forwarding
Sequence Diagram(s)sequenceDiagram
participant Client as DNS Client
participant Interceptor as dnsinterceptor
participant Forwarder as DNSForwarder
participant ResUtil as resutil.LookupRecords
participant Resolver as net.Resolver
Client->>Interceptor: DNS query
Interceptor->>Forwarder: Forward all query types
alt A / AAAA
Forwarder->>Resolver: LookupIPAddr
Resolver-->>Forwarder: IPs
Forwarder-->>Client: address answer
else MX / TXT / NS / SRV / CNAME / PTR
Forwarder->>ResUtil: LookupRecords(...)
ResUtil->>Resolver: LookupMX / LookupTXT / LookupNS / LookupSRV / LookupCNAME / LookupAddr
Resolver-->>ResUtil: records or error
ResUtil-->>Forwarder: RRs + rcode
Forwarder-->>Client: record answer
else unsupported
Forwarder-->>Client: NODATA + EDE
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Release artifactsBuilt for PR head
GHCR images (amd64)No GHCR images were pushed. This comment is updated by the Release workflow. Artifact links expire according to the workflow retention policy. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
client/internal/dns/resutil/resolve.go (1)
209-309: ⚡ Quick winExtract the per-type branches to satisfy the static-analysis gate.
LookupRecordsis now doing resolution, error mapping, and RR construction for every qtype in one switch, which matches the Sonar failure on Line 209 and the long-case warnings in both switches. Pulling each branch into small helpers likelookupMXRecords,lookupTXTRecords, andparseIPv4PTR/parseIPv6PTRshould clear the gate without changing behavior.Also applies to: 314-352
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@client/internal/dns/resutil/resolve.go` around lines 209 - 309, The LookupRecords function is too large with all DNS record type handling (MX, TXT, NS, SRV, CNAME, PTR) in a single switch statement, causing static analysis failures. Extract each case branch into separate helper functions such as lookupMXRecords, lookupTXTRecords, lookupNSRecords, lookupSRVRecords, lookupCNAMERecords, and helper functions for PTR record parsing. Then replace each case in the switch statement with a call to the corresponding helper function, ensuring the same behavior and error handling are preserved while reducing the main function's complexity.Source: Linters/SAST tools
client/internal/dnsfwd/forwarder_test.go (1)
659-772: ⚡ Quick winAdd NS and SRV cases to the new record-query suite.
TestDNSForwarder_RecordQueriesvalidates MX/TXT/CNAME/PTR, but NS/SRV forwarding (added in the same switch path) is not asserted here. Adding one success and one not-found/NODATA case for each would close the regression surface.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@client/internal/dnsfwd/forwarder_test.go` around lines 659 - 772, The TestDNSForwarder_RecordQueries function is missing test cases for NS and SRV record types, even though they are handled in the same code path as the existing tested record types (MX, TXT, CNAME, PTR). Add four new test cases within TestDNSForwarder_RecordQueries: one success case and one not-found/NODATA case each for NS and SRV records. Follow the same pattern as the existing test cases by using t.Run subtests, mocking the appropriate resolver methods (LookupNS and LookupSRV), calling runRecordQuery, and validating the response codes and record values using require and assert statements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@client/internal/dns/resutil/resolve.go`:
- Around line 365-368: The current logic in the nameHasAddress check at line 365
only proves a name exists by checking for A/AAAA records. If no address records
are found, it returns NXDOMAIN at line 368, which is incorrect for names that
exist as owners of other record types like SRV, TXT, NS, or MX records. To fix
this, broaden the existence check beyond just nameHasAddress to also verify if
the name exists as a valid owner of supported non-address record types before
returning NXDOMAIN. Alternatively, change the default response for missing
address records to NODATA instead of NXDOMAIN. Apply the same fix to the similar
code block referenced at lines 374-389 to ensure consistent behavior across all
existence checks.
In `@client/internal/dnsfwd/forwarder_test.go`:
- Around line 135-163: The MockResolver methods directly type-assert the return
values from args.Get() without nil checks, which causes panics when mocked
values are nil. For each method (LookupMX, LookupTXT, LookupNS, LookupSRV, and
LookupAddr), guard the type assertions by checking if args.Get() returns nil
before performing the type cast, and return appropriate zero values (nil for
pointer types, nil or empty slices for slice types) when nil is encountered
instead of allowing the panic to occur.
---
Nitpick comments:
In `@client/internal/dns/resutil/resolve.go`:
- Around line 209-309: The LookupRecords function is too large with all DNS
record type handling (MX, TXT, NS, SRV, CNAME, PTR) in a single switch
statement, causing static analysis failures. Extract each case branch into
separate helper functions such as lookupMXRecords, lookupTXTRecords,
lookupNSRecords, lookupSRVRecords, lookupCNAMERecords, and helper functions for
PTR record parsing. Then replace each case in the switch statement with a call
to the corresponding helper function, ensuring the same behavior and error
handling are preserved while reducing the main function's complexity.
In `@client/internal/dnsfwd/forwarder_test.go`:
- Around line 659-772: The TestDNSForwarder_RecordQueries function is missing
test cases for NS and SRV record types, even though they are handled in the same
code path as the existing tested record types (MX, TXT, CNAME, PTR). Add four
new test cases within TestDNSForwarder_RecordQueries: one success case and one
not-found/NODATA case each for NS and SRV records. Follow the same pattern as
the existing test cases by using t.Run subtests, mocking the appropriate
resolver methods (LookupNS and LookupSRV), calling runRecordQuery, and
validating the response codes and record values using require and assert
statements.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 796f2565-acac-435c-b89b-93221b2dee8e
📒 Files selected for processing (5)
client/internal/dns/resutil/resolve.goclient/internal/dns/resutil/resolve_test.goclient/internal/dnsfwd/forwarder.goclient/internal/dnsfwd/forwarder_test.goclient/internal/routemanager/dnsinterceptor/handler.go
# Conflicts: # client/internal/dns/resutil/resolve_test.go # client/internal/dnsfwd/forwarder.go # client/internal/dnsfwd/forwarder_test.go
riccardomanfrin
left a comment
There was a problem hiding this comment.
Looks ok to me, it's improving the DNS support. Routing peer not updated would just reply with NotImplemented
|



Describe your changes
DNS queries for a domain handled by a NetBird DNS route are now fully owned by that route's forwarder. Previously only A/AAAA were served; any other record type fell through to the client's system resolver, which is not authoritative for the routed (often internal, split-horizon) zone and answers NXDOMAIN. Because NXDOMAIN is name-scoped, that poisoned the whole name and broke the A/AAAA records the route does serve.
Issue ticket number and link
Stack
Checklist
Documentation
Select exactly one:
Behavioral fix to existing DNS route forwarding; no user-facing configuration or API changes.
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
Bug Fixes
Tests