[PR #6087] [CLOSED] dns: prefer loopback over WireGuard IP when binding DNS listener #29023

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

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6087
Author: @logan71f100
Created: 5/6/2026
Status: Closed

Base: mainHead: fix/dns-listener-prefer-loopback


📝 Commits (3)

  • 47e369f dns: prefer loopback over WireGuard IP when binding DNS listener
  • 6109242 dns: update stale comment to reflect loopback-first bind order
  • 6c91607 dns: fix comment and add regression test for loopback-first binding

📊 Changes

2 files changed (+22 additions, -6 deletions)

View changed files

📝 client/internal/dns/service_listener.go (+5 -6)
📝 client/internal/dns/service_listener_test.go (+17 -0)

📄 Description

Describe your changes

`testFreePort` in `client/internal/dns/service_listener.go` tries the WireGuard interface IP first when scanning for a free port. If the DNS server binds to that IP (e.g. `100.71.x.x:53`), queries routed to it are silently dropped by the WireGuard kernel module — the host's own WireGuard IP is not in any peer's `AllowedIPs`, so packets never reach the listener. DNS resolution breaks entirely.

This fix reorders the candidate IP list so loopback (`127.0.0.1`) is tried first, then `127.0.0.153`, with the WireGuard IP as a last resort. The DNS proxy then binds to a loopback address where packets are always delivered locally.

```go
// Before
ips = []netip.Addr{s.wgInterface.Address().IP, defaultIP, customIP}

// After
ips = []netip.Addr{defaultIP, customIP, s.wgInterface.Address().IP}
```

Verified on Ubuntu 25.10 with systemd-resolved: after the fix `netbird` binds to `127.0.0.1:53` and DNS resolves correctly. Before the fix it bound to the WireGuard IP and all DNS queries timed out.

Fixes #4110 (timeout towards netbird domain DNS forwarder on arch linux)
Related to #3258 (client does not set DNS server in systemd-resolved on Linux)

Both issues stem from the DNS listener binding to the WireGuard interface IP, which the WireGuard kernel module drops packets for since the local IP is not in any peer's AllowedIPs.

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:

  • Documentation is not needed for this change (internal bind address selection, no user-facing behavior change)

Summary by CodeRabbit

  • Refactor
    • Adjusted DNS port probing order on non-Darwin systems to prefer loopback addresses when determining a free port.
  • Tests
    • Added a test ensuring loopback addresses are preferred over other interfaces when selecting a free DNS port.

🔄 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/6087 **Author:** [@logan71f100](https://github.com/logan71f100) **Created:** 5/6/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/dns-listener-prefer-loopback` --- ### 📝 Commits (3) - [`47e369f`](https://github.com/netbirdio/netbird/commit/47e369fedf59009c297d4c862e04daaf934b6b63) dns: prefer loopback over WireGuard IP when binding DNS listener - [`6109242`](https://github.com/netbirdio/netbird/commit/6109242e344b57bac138a0dd527e6dd64f34b4d1) dns: update stale comment to reflect loopback-first bind order - [`6c91607`](https://github.com/netbirdio/netbird/commit/6c91607151a2ee4ce5f4c1461a35de5938f9ee61) dns: fix comment and add regression test for loopback-first binding ### 📊 Changes **2 files changed** (+22 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `client/internal/dns/service_listener.go` (+5 -6) 📝 `client/internal/dns/service_listener_test.go` (+17 -0) </details> ### 📄 Description ## Describe your changes \`testFreePort\` in \`client/internal/dns/service_listener.go\` tries the WireGuard interface IP first when scanning for a free port. If the DNS server binds to that IP (e.g. \`100.71.x.x:53\`), queries routed to it are silently dropped by the WireGuard kernel module — the host's own WireGuard IP is not in any peer's \`AllowedIPs\`, so packets never reach the listener. DNS resolution breaks entirely. This fix reorders the candidate IP list so loopback (\`127.0.0.1\`) is tried first, then \`127.0.0.153\`, with the WireGuard IP as a last resort. The DNS proxy then binds to a loopback address where packets are always delivered locally. \`\`\`go // Before ips = []netip.Addr{s.wgInterface.Address().IP, defaultIP, customIP} // After ips = []netip.Addr{defaultIP, customIP, s.wgInterface.Address().IP} \`\`\` Verified on Ubuntu 25.10 with systemd-resolved: after the fix \`netbird\` binds to \`127.0.0.1:53\` and DNS resolves correctly. Before the fix it bound to the WireGuard IP and all DNS queries timed out. ## Issue ticket number and link Fixes #4110 (timeout towards netbird domain DNS forwarder on arch linux) Related to #3258 (client does not set DNS server in systemd-resolved on Linux) Both issues stem from the DNS listener binding to the WireGuard interface IP, which the WireGuard kernel module drops packets for since the local IP is not in any peer's AllowedIPs. ## Stack <!-- branch-stack --> ### Checklist - [x] 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](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [x] Documentation is **not needed** for this change (internal bind address selection, no user-facing behavior change) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Adjusted DNS port probing order on non-Darwin systems to prefer loopback addresses when determining a free port. * **Tests** * Added a test ensuring loopback addresses are preferred over other interfaces when selecting a free DNS port. <!-- 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 08:07:20 -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#29023