Skip to content

[client] Ability to disable default route with Exit Node#5309

Open
Arsolitt wants to merge 6 commits intonetbirdio:mainfrom
Arsolitt:feature/disable-default-route
Open

[client] Ability to disable default route with Exit Node#5309
Arsolitt wants to merge 6 commits intonetbirdio:mainfrom
Arsolitt:feature/disable-default-route

Conversation

@Arsolitt
Copy link

@Arsolitt Arsolitt commented Feb 13, 2026

Describe your changes

This PR introduces the ability to prevent the installation of the default route (0.0.0.0/0) into the system routing table while preserving the WireGuard AllowedIPs configuration by passing
--disable-default-route CLI arg.

This allows enabling an Exit Node on the peer without automatically routing all host traffic through the tunnel, enabling custom routing management outside netbird.

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:

netbirdio/docs#602

Summary by CodeRabbit

  • New Features

    • Added a system configuration option and CLI flag to disable adding the system default route; the setting is persisted, exposed via the daemon API, and causes the route manager to ignore system default routes when enabled.
  • Tests

    • Added and updated tests validating the disable-default-route behavior across configuration, startup, and route-management flows.

@CLAassistant
Copy link

CLAassistant commented Feb 13, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

Adds a new disable-default-route flag and boolean that flow CLI → proto/server → profile config → engine → route manager; when enabled, default IPv4/IPv6 system routes are skipped during add/remove operations. (50 words)

Changes

Cohort / File(s) Summary
CLI
client/cmd/system.go, client/cmd/up.go
Add disable-default-route persistent flag and propagate DisableDefaultRoute into request/setup builders.
Proto / Server
client/proto/daemon.proto, client/server/server.go
Add disable_default_route fields to LoginRequest, SetConfigRequest, GetConfigResponse; server maps request field into internal config and includes it in GetConfig responses.
Profile & Config Propagation
client/internal/profilemanager/config.go, client/internal/connect.go
Expose DisableDefaultRoute in profile input/config; apply() handles updates and logging; propagate flag into EngineConfig.
Engine / Route Manager
client/internal/engine.go, client/internal/routemanager/manager.go, client/internal/routemanager/manager_test.go
Add DisableDefaultRoute to EngineConfig/ManagerConfig; route manager stores flag and skips adding/removing default IPv4/IPv6 system routes when set; tests updated and new tests added.
Tests
client/server/setconfig_test.go, client/internal/routemanager/manager_test.go
Wire new field into test requests/assertions; update coverage and add cases verifying default-route skipping behavior.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI
    participant Server as Server (daemon)
    participant Profile as ProfileManager
    participant Engine as Engine
    participant RouteMgr as RouteManager

    CLI->>Server: Send SetConfigRequest (disable_default_route)
    Server->>Profile: apply SetConfig (config.DisableDefaultRoute = msg.DisableDefaultRoute)
    Profile->>Engine: create EngineConfig (propagate DisableDefaultRoute)
    Engine->>RouteMgr: NewManager / ManagerConfig (DisableDefaultRoute)
    RouteMgr->>RouteMgr: setupRefCounters: if DisableDefaultRoute -> skip default routes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • pappz
  • bcmmbaga

Poem

🐇
A tiny flag hopped through every stack,
From CLI to daemon, never looking back,
When 0.0.0.0 wants to quietly hide,
The rabbit skips the route with nimble pride,
Tunnels hum softly as hops decide.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% 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 concisely summarizes the main feature: adding the ability to disable the default route when using Exit Node.
Description check ✅ Passed The description covers what changed, marks it as a feature enhancement, indicates tests were created, and references a documentation PR. All required sections are completed.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@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: 1

🤖 Fix all issues with AI agents
In `@client/proto/daemon.proto`:
- Around line 673-674: The proto adds the new field disable_default_route but it
was not added to the LoginRequest and GetConfigResponse messages nor propagated
in setupLoginRequest, so the value won't persist or be queryable; add an
optional bool disable_default_route field to both LoginRequest and
GetConfigResponse (choosing a unique tag number consistent with nearby fields),
update setupLoginRequest in client/cmd/up.go to copy the local
disable_default_route setting into the LoginRequest like the other disable_*
flags, regenerate protobuf stubs, and ensure server-side code that builds
GetConfigResponse populates disable_default_route from the server config/state.
🧹 Nitpick comments (1)
client/internal/routemanager/manager_test.go (1)

209-228: Test validates watcher creation but not route-skipping behavior.

The test only asserts require.Len(t, routeManager.clientNetworks, expectedWatchers), confirming a watcher is created. It does not verify the core feature: when disableDefaultRoute is true, the default route is excluded from the system routing table via the route ref counter's ErrIgnore path (see manager.go lines 190-193).

Add assertions that verify the default route is skipped from system route addition, or document that this behavior is covered by integration tests.

Add optional bool disable_default_route field (tag 35) to the
SetConfigRequest protobuf message and wire it through the daemon
server handler to ConfigInput.
Add DisableDefaultRoute field to ConfigInput, Config, EngineConfig
structs and wire it through the config update/create logic and
engine config mapping.
Register the --disable-default-route flag and implement filtering in
the route ref counter to skip adding default route (0.0.0.0/0) to
the system routing table while preserving WireGuard allowed IPs.
Update setconfig_test.go to cover the new DisableDefaultRoute field
in SetConfigRequest (AllFieldsSaved, verifyAllFieldsCovered, and
CLIFlags mapping). Add a test case to TestManagerUpdateRoutes verifying
that the default route watcher is still created when the flag is set.
The field was missing from LoginRequest (used during setup key login)
and GetConfigResponse (used by UI and status queries), causing the
flag to not persist in daemon mode.
Add TestDisableDefaultRouteSkipsSystemRoute that directly asserts the
route ref counter behavior: default route (0.0.0.0/0) is not tracked
in the ref counter (ErrIgnore path) while non-default routes are
tracked normally. Also update the table-driven test case to include
a non-default route alongside the default one to verify selective
filtering.
@Arsolitt Arsolitt force-pushed the feature/disable-default-route branch from f247332 to 48fc631 Compare February 24, 2026 09:29
@sonarqubecloud
Copy link

Copy link
Contributor

@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: 1

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

Inline comments:
In `@client/cmd/system.go`:
- Around line 32-34: Update the flag help text for
upCmd.PersistentFlags().BoolVar that uses disableDefaultRoute and
disableDefaultRouteFlag to explicitly mention both IPv4 and IPv6 default routes
(e.g. "Disable adding the IPv4 and IPv6 default routes (0.0.0.0/0 and ::/0) to
the system routing table while keeping them in WireGuard allowed IPs.") so users
understand the flag affects both families.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60a55a1 and 48fc631.

⛔ Files ignored due to path filters (1)
  • client/proto/daemon.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (10)
  • client/cmd/system.go
  • client/cmd/up.go
  • client/internal/connect.go
  • client/internal/engine.go
  • client/internal/profilemanager/config.go
  • client/internal/routemanager/manager.go
  • client/internal/routemanager/manager_test.go
  • client/proto/daemon.proto
  • client/server/server.go
  • client/server/setconfig_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • client/cmd/up.go
  • client/proto/daemon.proto
  • client/internal/engine.go

Comment on lines +32 to +34
upCmd.PersistentFlags().BoolVar(&disableDefaultRoute, disableDefaultRouteFlag, false,
"Disable adding default route (0.0.0.0/0) to the system routing table while keeping it in WireGuard allowed IPs.")

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Help text should mention IPv6 default route too.
The behavior skips both IPv4 and IPv6 defaults, but the flag description only cites 0.0.0.0/0. Consider clarifying to avoid user confusion.

Suggested text update
- upCmd.PersistentFlags().BoolVar(&disableDefaultRoute, disableDefaultRouteFlag, false,
-     "Disable adding default route (0.0.0.0/0) to the system routing table while keeping it in WireGuard allowed IPs.")
+ upCmd.PersistentFlags().BoolVar(&disableDefaultRoute, disableDefaultRouteFlag, false,
+     "Disable adding default routes (0.0.0.0/0, ::/0) to the system routing table while keeping them in WireGuard allowed IPs.")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
upCmd.PersistentFlags().BoolVar(&disableDefaultRoute, disableDefaultRouteFlag, false,
"Disable adding default route (0.0.0.0/0) to the system routing table while keeping it in WireGuard allowed IPs.")
upCmd.PersistentFlags().BoolVar(&disableDefaultRoute, disableDefaultRouteFlag, false,
"Disable adding default routes (0.0.0.0/0, ::/0) to the system routing table while keeping them in WireGuard allowed IPs.")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/cmd/system.go` around lines 32 - 34, Update the flag help text for
upCmd.PersistentFlags().BoolVar that uses disableDefaultRoute and
disableDefaultRouteFlag to explicitly mention both IPv4 and IPv6 default routes
(e.g. "Disable adding the IPv4 and IPv6 default routes (0.0.0.0/0 and ::/0) to
the system routing table while keeping them in WireGuard allowed IPs.") so users
understand the flag affects both families.

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