Skip to content

Fix DNS resolution failure when toggling exit nodes #82

Merged
mlsmaycon merged 5 commits intomainfrom
update-core-with-dns
Apr 8, 2026
Merged

Fix DNS resolution failure when toggling exit nodes #82
mlsmaycon merged 5 commits intomainfrom
update-core-with-dns

Conversation

@mlsmaycon
Copy link
Copy Markdown
Contributor

@mlsmaycon mlsmaycon commented Apr 6, 2026

Summary

  • Route all DNS through the tunnel on iOS by always setting matchDomains=[""], eliminating the drift between Go's DNS server (which has a root zone fallback handler) and iOS
    tunnel settings that only matched specific domains
  • Handle empty route notifications from Go — when the exit node was the only route and was deselected, the notifier sent an empty string that Swift silently dropped, leaving
    stale 0.0.0.0/0 in the tunnel and black-holing all traffic
  • Fix route card status indicator showing green after deselecting a route by checking route.selected before evaluating peer connection status

Test plan

  • Connect on WiFi with exit node enabled, disable it — DNS should continue working
  • Connect on cellular with exit node enabled, disable it — DNS should continue working
  • Re-enable exit node — DNS should work through the exit node
  • Disable exit node — UI status color should change to gray immediately
  • Connect without any exit node — DNS should work for NB domains and external domains

Summary by CodeRabbit

  • Chores
    • Release/TestFlight flow updated: uploads can be triggered by tags or PR description and optionally skipped.
  • Bug Fixes
    • Route cards only show “Connected” when a route is actively selected.
  • Improvements
    • Network handling now applies parsed route updates even when no routes are present.
    • DNS and tunnel domain/search handling simplified for more consistent behavior; upload can be disabled for build-only runs.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 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: af11d7af-72f7-42cd-a240-61d846f6d80c

📥 Commits

Reviewing files that changed from the base of the PR and between 8b3dadc and 8be54d8.

📒 Files selected for processing (1)
  • NetbirdKit/NetworkChangeListener.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • NetbirdKit/NetworkChangeListener.swift

📝 Walkthrough

Walkthrough

Workflows: testflight triggers and gate logic revised to remove comment-based triggers and derive upload/version from tag refs or a /testflight line in PR descriptions. build-upload adds an upload input to control App Store Connect upload. App code: route selection, network-change parsing, and tunnel DNS settings behavior adjusted.

Changes

Cohort / File(s) Summary
GitHub Actions — testflight workflow
​.github/workflows/testflight.yml
Triggers changed to push on main and tag pushes v*; removed issue_comment trigger and reaction step. gate now outputs upload and extracts version from tag refs or from a /testflight line in the PR description; build receives upload; notify restricted to pull_request and always reads PR number from payload.
GitHub Actions — build/upload inputs
​.github/workflows/build-upload.yml
Added boolean workflow-call input upload (default true) and made App Store Connect export/upload step conditional on inputs.upload.
UI component — Route status
NetBird/Source/App/Views/Components/RouteCard.swift
statusIndicatorColor now requires route.selected == true to display the “Connected” (green) state; other fallback color logic unchanged.
Network change parsing
NetbirdKit/NetworkChangeListener.swift
onNetworkChanged(_:) no longer early-returns on nil/empty route string — it normalizes to "", parses routes, and always calls tunnelManager.setRoutes(...) with the parsed results (which may be empty).
Tunnel / DNS settings
NetbirdNetworkExtension/PacketTunnelProviderSettingsManager.swift
DNS construction simplified: always initializes DNS servers to [config.serverIP] (removed 1.1.1.1 fallback); dnsSettings.matchDomains/searchDomains handling consolidated (matchDomains set to [""] unconditionally; searchDomains built from enabled non-matchOnly domains and applied only if non-empty).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • doromaraujo

Poem

🐰 I hopped through diffs with a curious twitch,
Tags whisper versions, PR lines flip the switch,
Builds mind the flag, uploads only when told,
Routes glow green only when they've been enrolled,
🥕✨

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix DNS resolution failure when toggling exit nodes' accurately summarizes the main objective—addressing DNS resolution issues when exit nodes are toggled—which is clearly supported by the substantial changes to DNS and route handling across multiple files.

✏️ 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 update-core-with-dns

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.

@mlsmaycon
Copy link
Copy Markdown
Contributor Author

/testflight netbird-ref=add-default-resolver version=0.67.5

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build failed for d27148c

View workflow run

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build failed for d27148c

View workflow run

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build uploaded for d27148c

The build has been submitted to App Store Connect and will be available in TestFlight shortly.

View workflow run

@mlsmaycon
Copy link
Copy Markdown
Contributor Author

/testflight netbird-ref=add-default-resolver

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build failed for 3b4aec8

View workflow run

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@NetbirdKit/NetworkChangeListener.swift`:
- Around line 24-28: The code currently logs the full routesString in
NetworkChangeListener (onNetworkChanged), which can expose private CIDRs;
instead parse routesString to produce only aggregate metadata (e.g., number of
routes and whether a default route like 0.0.0.0/0 or ::/0 is present) and
replace the direct routesString log with a sanitized message such as
"onNetworkChanged: routesCount=\(count), hasDefault=\(true/false)"; update the
AppLogger.shared.log call(s) in the onNetworkChanged handling to emit only these
aggregates and never the raw routesString.
- Around line 30-32: Guard against applying empty routes before interface IP is
initialized: after calling parseRoutesToNESettings and logging, only call
self.tunnelManager.setRoutes(v4Routes:v4Routes, v6Routes:v6Routes,
containsDefault:containsDefault) when at least one of v4Routes or v6Routes is
non-empty or when the tunnel manager reports the interface IP is already set; if
both route lists are empty and the interface IP isn't set, skip setRoutes and
log a warning so PacketTunnelProviderSettingsManager won't apply empty included
routes prematurely. Use the existing symbols parseRoutesToNESettings,
AppLogger.shared.log, and self.tunnelManager.setRoutes and, if available, check
a tunnelManager property or method indicating interface IP state (e.g.,
interfaceIP / hasInterfaceIP()) to decide whether to defer applying routes.

In `@NetbirdNetworkExtension/PacketTunnelProviderSettingsManager.swift`:
- Line 55: The current log in PacketTunnelProviderSettingsManager
(AppLogger.shared.log call in the setDNS logic) prints raw DNS server and search
domain values; change it to avoid logging sensitive values by replacing
config.serverIP and searchDomains with redacted or summarized information (e.g.,
"server=<redacted>" or "serverCount=\(servers.count)") and log counts/flags
instead (searchDomains.count, config.routeAll, config.domains.count). Update the
message in the AppLogger.shared.log invocation inside the setDNS path to use
masked placeholders or a small helper that returns counts/flags rather than full
values.
- Around line 34-56: The setDNS function currently forces full DNS tunneling by
unconditionally setting dnsSettings.matchDomains = [""], ignoring
HostDNSConfig.routeAll; update setDNS to honor config.routeAll: if routeAll is
true keep matchDomains = [""], otherwise build matchDomains from config.domains
(include domains that are not disabled and include match-only domains
appropriately, e.g., add domain.domain entries for matchOnly and non-matchOnly
where split-DNS is desired) and only set dnsSettings.matchDomains when
non-empty; also update the AppLogger.shared.log call to reflect the actual
matchDomains used and ensure dnsSettings.searchDomains logic remains unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4f0cbaba-031b-43a1-a201-0dff7872ba16

📥 Commits

Reviewing files that changed from the base of the PR and between d27148c and 3b4aec8.

📒 Files selected for processing (5)
  • .github/workflows/build-upload.yml
  • .github/workflows/testflight.yml
  • NetBird/Source/App/Views/Components/RouteCard.swift
  • NetbirdKit/NetworkChangeListener.swift
  • NetbirdNetworkExtension/PacketTunnelProviderSettingsManager.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/testflight.yml

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build uploaded for 3b4aec8

The build has been submitted to App Store Connect and will be available in TestFlight shortly.

View workflow run

@mlsmaycon mlsmaycon changed the title remove unused React to comment step in testflight workflow Fix DNS resolution failure when toggling exit nodes Apr 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build uploaded for 8b3dadc

The build has been submitted to App Store Connect and will be available in TestFlight shortly.

View workflow run

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build failed for 8be54d8

View workflow run

@mlsmaycon
Copy link
Copy Markdown
Contributor Author

/testflight netbird-ref=add-default-resolver

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

TestFlight build uploaded for 8be54d8

The build has been submitted to App Store Connect and will be available in TestFlight shortly.

View workflow run

@mlsmaycon mlsmaycon merged commit dd44b16 into main Apr 8, 2026
6 of 7 checks passed
@mlsmaycon mlsmaycon deleted the update-core-with-dns branch April 8, 2026 06:44
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