Skip to content

[client] Replace iOS DNS IsPrivate heuristic with route checker#5694

Merged
lixmal merged 1 commit intomainfrom
fix/ios-dns-replace-isprivate-heuristic
Mar 26, 2026
Merged

[client] Replace iOS DNS IsPrivate heuristic with route checker#5694
lixmal merged 1 commit intomainfrom
fix/ios-dns-replace-isprivate-heuristic

Conversation

@lixmal
Copy link
Copy Markdown
Collaborator

@lixmal lixmal commented Mar 25, 2026

Describe your changes

  • Replace IsPrivate() heuristic in iOS upstream DNS resolver with a route checker function that queries actual client routes from the route manager
  • Add SetRouteChecker to the DNS Server interface, wired up from the engine after route manager creation

Issue ticket number and link

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)

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
    • Implemented route-aware DNS resolution that enables intelligent routing decisions based on client-configured network routes. The system can now match upstream DNS resolvers against configured route networks, replacing purely network-type-based decisions with route-aware logic. This improves DNS query handling in split-DNS and complex multi-route network configurations.

@lixmal lixmal force-pushed the fix/ios-dns-replace-isprivate-heuristic branch 3 times, most recently from 5d13f1b to 3addb60 Compare March 26, 2026 08:58
@lixmal lixmal changed the base branch from client-ipv6-dns to main March 26, 2026 08:58
@lixmal lixmal force-pushed the fix/ios-dns-replace-isprivate-heuristic branch from 3addb60 to 3004050 Compare March 26, 2026 08:59
@netbirdio netbirdio deleted a comment from coderabbitai Bot Mar 26, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c53064c-fc29-4474-9f0e-448727d68bb7

📥 Commits

Reviewing files that changed from the base of the PR and between a8b9570 and 3004050.

📒 Files selected for processing (5)
  • client/internal/dns/mock_server.go
  • client/internal/dns/server.go
  • client/internal/dns/upstream.go
  • client/internal/dns/upstream_ios.go
  • client/internal/engine.go

📝 Walkthrough

Walkthrough

The changes introduce a route-checker callback mechanism to the DNS subsystem. The engine passes a route matcher function to the DNS server during startup, which is propagated to all upstream resolvers. DNS resolvers use this function to determine if upstream IPs match configured client routes during DNS resolution.

Changes

Cohort / File(s) Summary
DNS Server Interface and Implementation
client/internal/dns/server.go, client/internal/dns/mock_server.go
Extended Server interface with SetRouteChecker method. Implemented setter on DefaultServer to store the route matcher callback and propagate it to upstream resolvers in three creation paths: fallback resolver, domain-group handlers, and host root zone resolver.
Upstream Resolver Route Awareness
client/internal/dns/upstream.go, client/internal/dns/upstream_ios.go
Added routeMatch field to upstreamResolverBase. Modified DNS exchange logic in iOS resolver to determine private-client requirement based on local network containment OR custom route matcher satisfaction.
Engine Integration
client/internal/engine.go
Added SetRouteChecker call during Engine.Start with a closure that checks if candidate IPs exist in any client route's network prefix.

Sequence Diagram

sequenceDiagram
    participant Engine
    participant DNSServer as DNS Server
    participant RouteManager as Route Manager
    participant UpstreamResolver as Upstream Resolver
    participant PrivateClient as Private Client

    Engine->>DNSServer: SetRouteChecker(callback)
    DNSServer->>DNSServer: Store route matcher
    DNSServer->>UpstreamResolver: Propagate routeMatch
    
    UpstreamResolver->>UpstreamResolver: Receive DNS query
    UpstreamResolver->>UpstreamResolver: Determine needsPrivate flag
    alt needsPrivate = true
        UpstreamResolver->>RouteManager: Check if IP in routes (via callback)
        RouteManager-->>UpstreamResolver: Match result
        UpstreamResolver->>PrivateClient: GetClientPrivate()
        PrivateClient-->>UpstreamResolver: Private client instance
        UpstreamResolver->>PrivateClient: ExchangeWithFallback(query)
        PrivateClient-->>UpstreamResolver: DNS response
    else needsPrivate = false
        UpstreamResolver->>UpstreamResolver: Use standard exchange
    end
    UpstreamResolver-->>Engine: DNS response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • pappz
  • mlsmaycon

Poem

🐰 Routes now guide the DNS way,
Callbacks dance through night and day,
Upstream checkers verify the path,
No rogue addresses block our craft!
One function spreads through resolver lines—
Route-aware DNS by design! 🌐

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 accurately summarizes the main change: replacing the iOS DNS IsPrivate heuristic with a route checker mechanism across multiple files.
Description check ✅ Passed The description covers the key changes and follows the template structure, though the issue ticket and docs PR URL sections are incomplete or use placeholder links.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ios-dns-replace-isprivate-heuristic

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.

@lixmal
Copy link
Copy Markdown
Collaborator Author

lixmal commented Mar 26, 2026

@coderabbitai review

@sonarqubecloud
Copy link
Copy Markdown

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":404,"request":{"method":"PATCH","url":"https://api.github.com/repos/netbirdio/netbird/issues/comments/4126419363","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\nNo actionable comments were generated in the recent review. 🎉\n\n<details>\n<summary>ℹ️ Recent review info</summary>\n\n<details>\n<summary>⚙️ Run configuration</summary>\n\n**Configuration used**: defaults\n\n**Review profile**: CHILL\n\n**Plan**: Pro\n\n**Run ID**: `cf68e63b-64ef-45fc-be82-738a261382f6`\n\n</details>\n\n<details>\n<summary>📥 Commits</summary>\n\nReviewing files that changed from the base of the PR and between a8b95707009e16f808d442d2b741b580dc8e4593 and 3004050005c23ea2ce0abbf647276ae2fca11f6e.\n\n</details>\n\n<details>\n<summary>📒 Files selected for processing (5)</summary>\n\n* `client/internal/dns/mock_server.go`\n* `client/internal/dns/server.go`\n* `client/internal/dns/upstream.go`\n* `client/internal/dns/upstream_ios.go`\n* `client/internal/engine.go`\n\n</details>\n\n</details>\n\n---\n\n\n<!-- walkthrough_start -->\n\n<details>\n<summary>📝 Walkthrough</summary>\n\n## Walkthrough\n\nThis PR extends the DNS resolver with route-aware IP matching capabilities. A new `SetRouteChecker` method is added to the Server interface and DefaultServer, accepting a function that determines if an IP address matches a client route. The checker is propagated through upstream resolvers and used during iOS DNS queries to decide whether to use a private DNS client based on route membership.\n\n## Changes\n\n|Cohort / File(s)|Summary|\n|---|---|\n|**Server Interface & Mock** <br> `client/internal/dns/server.go`, `client/internal/dns/mock_server.go`|Added `SetRouteChecker(func(netip.Addr) bool)` method to Server interface and implemented on DefaultServer, storing the function in a routeMatch field guarded by mutex. Mock version is a no-op.|\n|**Upstream Resolver Base** <br> `client/internal/dns/upstream.go`|Added unexported `routeMatch func(netip.Addr) bool` field to upstreamResolverBase to carry route-matching predicate for IP address selection logic.|\n|**Server Handler Registration** <br> `client/internal/dns/server.go` (handler setup)|Modified registerFallback, createHandlersForDomainGroup, and addHostRootZone to copy s.routeMatch onto each created handler's routeMatch field after construction.|\n|**iOS DNS Query Logic** <br> `client/internal/dns/upstream_ios.go`|Updated private DNS client decision logic to use combined condition: private client is selected when upstream IP is in local network prefix OR when routeMatch predicate returns true. Updated debug logs to include queried DNS name.|\n|**Engine Integration** <br> `client/internal/engine.go`|Configured e.dnsServer with a route-aware checker in Engine.Start that iterates over e.routeManager.GetClientRoutes() and returns true if provided netip.Addr is contained within any route's Network prefix.|\n\n## Sequence Diagram(s)\n\n```mermaid\nsequenceDiagram\n    participant Engine\n    participant DNSServer as DNS Server\n    participant RouteManager\n    participant UpstreamResolver\n    participant iOS as iOS Network Layer\n\n    Engine->>RouteManager: GetClientRoutes()\n    RouteManager-->>Engine: Client routes list\n    Engine->>DNSServer: SetRouteChecker(checker function)\n    Note over DNSServer: Store checker in routeMatch<br/>(guarded by mutex)\n    \n    DNSServer->>UpstreamResolver: registerFallback/createHandlers\n    Note over DNSServer: Copy routeMatch to<br/>each handler\n    UpstreamResolver->>UpstreamResolver: Store routeMatch on handler\n\n    rect rgba(100, 150, 200, 0.5)\n        Note over UpstreamResolver,iOS: During DNS Query\n        UpstreamResolver->>UpstreamResolver: Check if IP in local network\n        UpstreamResolver->>UpstreamResolver: OR routeMatch(upstream IP) == true\n        UpstreamResolver->>iOS: Create private DNS client<br/>(if condition met)\n        UpstreamResolver->>iOS: Send DNS query\n        iOS-->>UpstreamResolver: Query result\n    end\n```\n\n## Estimated code review effort\n\n🎯 3 (Moderate) | ⏱️ ~20 minutes\n\n## Suggested reviewers\n\n- pappz\n\n## Poem\n\n> 🐰 Routes now guide our DNS way,\n> With checkers hopping through the day,\n> Each query knows which path to take,\n> IPs matched for network's sake,\n> Upstream resolvers celebrate! 🎉\n\n</details>\n\n<!-- walkthrough_end -->\n\n\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 2 | ❌ 1</summary>\n\n### ❌ Failed checks (1 warning)\n\n|     Check name     | Status     | Explanation                                                                          | Resolution                                                                         |\n| :----------------: | :--------- | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |\n| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |\n\n<details>\n<summary>✅ Passed checks (2 passed)</summary>\n\n|     Check name    | Status   | Explanation                                                                                                                                                              |\n| :---------------: | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|    Title check    | ✅ Passed | The title clearly and concisely summarizes the main change: replacing the iOS DNS IsPrivate heuristic with a route checker function.                                     |\n| Description check | ✅ Passed | The description includes change details and checklist completion, but lacks an issue ticket number and the issue link section is left empty as required by the template. |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>📝 Generate docstrings</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> Create stacked PR\n- [ ] <!-- {\"checkboxId\": \"3e1879ae-f29b-4d0d-8e06-d12b7ba33d98\"} --> Commit on current branch\n\n</details>\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"6ba7b810-9dad-11d1-80b4-00c04fd430c8\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Commit unit tests in branch `fix/ios-dns-replace-isprivate-heuristic`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=netbirdio/netbird&utm_content=5694)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n\n<!-- internal state start -->\n\n\n<!-- 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 -->\n\n<!-- internal state end -->"},"request":{"retryCount":1}},"response":{"url":"https://api.github.com/repos/netbirdio/netbird/issues/comments/4126419363","status":404,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","content-encoding":"gzip","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Thu, 26 Mar 2026 09:03:28 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","transfer-encoding":"chunked","vary":"Accept-Encoding, Accept, X-Requested-With","x-accepted-github-permissions":"issues=write; pull_requests=write","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-api-version-selected":"2022-11-28","x-github-media-type":"github.v3; format=json","x-github-request-id":"A42F:11E0:218FFE7:8D707D9:69C4F660","x-ratelimit-limit":"5000","x-ratelimit-remaining":"4827","x-ratelimit-reset":"1774518545","x-ratelimit-resource":"core","x-ratelimit-used":"173","x-xss-protection":"0"},"data":{"message":"Not Found","documentation_url":"https://docs.github.com/rest/issues/comments#update-an-issue-comment","status":"404"}}}

Comment thread client/internal/dns/server.go
Comment thread client/internal/dns/server.go
Comment thread client/internal/dns/server.go
Copy link
Copy Markdown
Collaborator

@mlsmaycon mlsmaycon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

@lixmal lixmal merged commit 145d82f into main Mar 26, 2026
43 of 44 checks passed
@lixmal lixmal deleted the fix/ios-dns-replace-isprivate-heuristic branch March 26, 2026 10:11
@lixmal lixmal mentioned this pull request Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants