[PR #5409] fix: auto-recover stale wintun driver on Windows #27894

Open
opened 2026-08-05 07:09:22 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/5409
Author: @Vivek-Yarra
Created: 2/21/2026
Status: 🔄 Open

Base: mainHead: fix/wintun-driver-recovery


📝 Commits (2)

  • fecbddc fix: auto-recover stale wintun driver on Windows
  • 77e6e9d address CodeRabbit review feedback

📊 Changes

2 files changed (+244 additions, -1 deletions)

View changed files

📝 client/iface/device/device_windows.go (+105 -1)
client/iface/device/device_windows_test.go (+139 -0)

📄 Description

Summary

After Windows updates (especially on Windows 11 Insider/Dev builds), the wintun kernel driver registration can become stale. The driver entry exists in the Windows service registry but fails to load, causing tun.CreateTUNWithRequestedGUID() to fail with:

Error creating interface: The system cannot find the file specified.

NetBird retries indefinitely via exponential backoff in connect.go, but never fixes the underlying driver issue — requiring manual intervention (sc.exe delete wintun + service restart).

This PR adds automatic recovery logic to TunDevice.Create() on Windows:

  • isWintunDriverError() — detects the specific "system cannot find the file specified" error pattern (case-insensitive)
  • tryRecoverWintunDriver() — queries the wintun service state via sc.exe, and if the service exists but is stopped/failed, removes the stale entry so the wintun library can re-register on retry
  • getSystem32Command() — resolves sc.exe path, mirroring the existing GetSystem32Command pattern in iface_destroy_windows.go

Recovery is conservative:

  • Only triggered on the specific wintun driver error message
  • Only acts if the wintun service exists but is not running
  • If the service doesn't exist, returns nil (nothing to recover)
  • If the service is running, returns an error (recovery not applicable)
  • Single retry after recovery — no infinite recovery loops

This runs under the NetBird Windows service (LocalSystem account) which has the required administrator privileges for sc.exe operations.

Test Results

All tests pass on Windows 11 (build 26200):

$ go test -v ./client/iface/device/ -run "TestIsWintunDriverError|TestGetSystem32Command|TestTryRecoverWintunDriver"
=== RUN   TestIsWintunDriverError
=== RUN   TestIsWintunDriverError/nil_error
=== RUN   TestIsWintunDriverError/wintun_driver_error_-_exact_message
=== RUN   TestIsWintunDriverError/wintun_driver_error_-_wrapped
=== RUN   TestIsWintunDriverError/wintun_driver_error_-_different_case
=== RUN   TestIsWintunDriverError/unrelated_error_-_access_denied
=== RUN   TestIsWintunDriverError/unrelated_error_-_timeout
=== RUN   TestIsWintunDriverError/unrelated_error_-_generic
--- PASS: TestIsWintunDriverError (0.00s)
=== RUN   TestGetSystem32Command
=== RUN   TestGetSystem32Command/sc.exe_should_be_found
=== RUN   TestGetSystem32Command/nonexistent_command_returns_full_path
--- PASS: TestGetSystem32Command (0.00s)
=== RUN   TestTryRecoverWintunDriver
--- PASS: TestTryRecoverWintunDriver (0.00s)
PASS
ok      github.com/netbirdio/netbird/client/iface/device    1.665s

Additional verification:

  • go build ./client/iface/device/ Pass
  • go vet ./client/iface/device/ No issues

Test Plan

  • Unit tests for isWintunDriverError — 7 test cases covering nil, exact match, wrapped error, case-insensitive match, and unrelated errors
  • Unit tests for getSystem32Command — verifies PATH resolution and fallback path construction
  • Integration test for tryRecoverWintunDriver — exercises actual sc.exe calls, verifies no panics regardless of system state
  • go build and go vet clean
  • Manually verified fix on Windows 11 build 26200 where wintun driver was in failed state

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows TUN creation with automatic detection and recovery for wintun driver-related failures, reducing service disruptions from transient driver issues.
  • Tests

    • Added comprehensive Windows-specific tests covering error detection, command resolution, and recovery behavior (including an integration-style guarded test).

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/5409 **Author:** [@Vivek-Yarra](https://github.com/Vivek-Yarra) **Created:** 2/21/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/wintun-driver-recovery` --- ### 📝 Commits (2) - [`fecbddc`](https://github.com/netbirdio/netbird/commit/fecbddc48e265822857ba8550ef2fba4772f2143) fix: auto-recover stale wintun driver on Windows - [`77e6e9d`](https://github.com/netbirdio/netbird/commit/77e6e9db7e77d81dedaef07f90e2b5b31f2a70df) address CodeRabbit review feedback ### 📊 Changes **2 files changed** (+244 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `client/iface/device/device_windows.go` (+105 -1) ➕ `client/iface/device/device_windows_test.go` (+139 -0) </details> ### 📄 Description ## Summary After Windows updates (especially on Windows 11 Insider/Dev builds), the wintun kernel driver registration can become stale. The driver entry exists in the Windows service registry but fails to load, causing `tun.CreateTUNWithRequestedGUID()` to fail with: ``` Error creating interface: The system cannot find the file specified. ``` NetBird retries indefinitely via exponential backoff in `connect.go`, but never fixes the underlying driver issue — requiring manual intervention (`sc.exe delete wintun` + service restart). This PR adds automatic recovery logic to `TunDevice.Create()` on Windows: - **`isWintunDriverError()`** — detects the specific "system cannot find the file specified" error pattern (case-insensitive) - **`tryRecoverWintunDriver()`** — queries the wintun service state via `sc.exe`, and if the service exists but is stopped/failed, removes the stale entry so the wintun library can re-register on retry - **`getSystem32Command()`** — resolves `sc.exe` path, mirroring the existing `GetSystem32Command` pattern in `iface_destroy_windows.go` Recovery is conservative: - Only triggered on the specific wintun driver error message - Only acts if the wintun service exists but is **not** running - If the service doesn't exist, returns nil (nothing to recover) - If the service is running, returns an error (recovery not applicable) - Single retry after recovery — no infinite recovery loops This runs under the NetBird Windows service (LocalSystem account) which has the required administrator privileges for `sc.exe` operations. ## Related Issues - Fixes #5408 - Related: #4670, #2967 ## Test Results All tests pass on Windows 11 (build 26200): ``` $ go test -v ./client/iface/device/ -run "TestIsWintunDriverError|TestGetSystem32Command|TestTryRecoverWintunDriver" === RUN TestIsWintunDriverError === RUN TestIsWintunDriverError/nil_error === RUN TestIsWintunDriverError/wintun_driver_error_-_exact_message === RUN TestIsWintunDriverError/wintun_driver_error_-_wrapped === RUN TestIsWintunDriverError/wintun_driver_error_-_different_case === RUN TestIsWintunDriverError/unrelated_error_-_access_denied === RUN TestIsWintunDriverError/unrelated_error_-_timeout === RUN TestIsWintunDriverError/unrelated_error_-_generic --- PASS: TestIsWintunDriverError (0.00s) === RUN TestGetSystem32Command === RUN TestGetSystem32Command/sc.exe_should_be_found === RUN TestGetSystem32Command/nonexistent_command_returns_full_path --- PASS: TestGetSystem32Command (0.00s) === RUN TestTryRecoverWintunDriver --- PASS: TestTryRecoverWintunDriver (0.00s) PASS ok github.com/netbirdio/netbird/client/iface/device 1.665s ``` Additional verification: - `go build ./client/iface/device/` — ✅ Pass - `go vet ./client/iface/device/` — ✅ No issues ## Test Plan - [x] Unit tests for `isWintunDriverError` — 7 test cases covering nil, exact match, wrapped error, case-insensitive match, and unrelated errors - [x] Unit tests for `getSystem32Command` — verifies PATH resolution and fallback path construction - [x] Integration test for `tryRecoverWintunDriver` — exercises actual `sc.exe` calls, verifies no panics regardless of system state - [x] `go build` and `go vet` clean - [x] Manually verified fix on Windows 11 build 26200 where wintun driver was in failed state <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Windows TUN creation with automatic detection and recovery for wintun driver-related failures, reducing service disruptions from transient driver issues. * **Tests** * Added comprehensive Windows-specific tests covering error detection, command resolution, and recovery behavior (including an integration-style guarded test). <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 07:09:22 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#27894