From c142761de92c841b60a74878a0872b1e865a5383 Mon Sep 17 00:00:00 2001 From: riccardom Date: Wed, 26 Aug 2026 12:25:10 +0200 Subject: [PATCH 1/3] docs: document that a primary nameserver is exclusive on Windows A peer with a primary nameserver now gets a Name Resolution Policy Table rule covering every namespace, so all resolution goes through NetBird and nowhere else. Without it Windows queries every adapter's resolvers in parallel and keeps whichever answer arrives first, which leaks queries to the local network and lets another resolver answer for a name NetBird is authoritative for. Two consequences worth knowing before it surprises someone: - Zones only the local network resolves stop working while connected, unless they are declared as match domains. A more specific rule takes precedence, so declaring the zone is the fix. `.local` is exempt, so multicast DNS is unaffected. - Short names depend on which adapter's suffix Windows tries first, and it stops at the first "no such name" rather than continuing down the list. On domain-joined machines the machine's own domain wins that first attempt, so a short name can fail while its fully qualified form resolves. Placed next to the existing macOS note in the same section, since both are about what a primary nameserver does beyond catching unmatched queries, and next to the existing warning about emptying match domains, which the suffix caveat explains the other half of. Also documents NB_USE_LEGACY_DNS_RESOLUTION, which restores the old behaviour on a peer. --- src/pages/client/environment-variables.mdx | 1 + src/pages/manage/dns/internal-dns-servers.mdx | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/pages/client/environment-variables.mdx b/src/pages/client/environment-variables.mdx index 202811169..53a0afef3 100644 --- a/src/pages/client/environment-variables.mdx +++ b/src/pages/client/environment-variables.mdx @@ -82,6 +82,7 @@ To clear all saved service parameters (including env vars), run `sudo netbird se | `NB_DNS_FORWARDER_PORT` | All | Override the port the internal DNS forwarder binds to for handling DNS routes received from clients (default: `22054`). The forwarder is separate from the local resolver. | | `NB_SKIP_DNS_PROBE` | All | Skip the startup check that sends a test query to the local resolver to verify it is reachable. Set this if the probe causes delays (e.g. in air-gapped networks). | | `NB_DNS_LAZY_WARMUP_TIMEOUT` | All | Per-query budget for waking an idle peer when the local resolver returns one of its A or AAAA records (Go duration, default: `2s`). The value must be positive; invalid, zero, or negative values use the default. | +| `NB_USE_LEGACY_DNS_RESOLUTION` | Windows | Go back to only setting the NetBird address as the tunnel adapter's nameserver, leaving Windows free to query the other adapters' resolvers in parallel. By default, a peer with a primary nameserver also gets a Name Resolution Policy Table rule that sends every query to the NetBird resolver and nowhere else. Set this if a zone that only the local network resolves has to stay reachable while connected and cannot be declared as a match domain — it also brings back the query leak and the non-deterministic resolution the rule prevents. | | `NB_UNCLEAN_SHUTDOWN_RESOLV_FILE` | Linux, FreeBSD | Custom file path to store a backup of `/etc/resolv.conf` before the client modifies it. Used to restore the original on next startup if the client crashed without cleaning up (default: `/resolv.conf`, i.e. `/var/lib/netbird/resolv.conf` on Linux, `/var/db/netbird/resolv.conf` on FreeBSD). | ## Connection retry diff --git a/src/pages/manage/dns/internal-dns-servers.mdx b/src/pages/manage/dns/internal-dns-servers.mdx index e5259b838..e9a4e5d55 100644 --- a/src/pages/manage/dns/internal-dns-servers.mdx +++ b/src/pages/manage/dns/internal-dns-servers.mdx @@ -100,6 +100,14 @@ Each peer should have exactly **one** primary nameserver. If you don't configure A primary nameserver does more than catch unmatched queries. On macOS, a match-domain-only configuration registers a *scoped* resolver through system APIs and leaves the nameservers in `/etc/resolv.conf` untouched. Applications that use the system resolver follow the scoped entry, but tools that read `resolv.conf` directly (`dig`, `host`, and some language runtimes) keep querying your LAN or public nameservers and get `NXDOMAIN` for internal names. Adding a primary group puts NetBird's resolver into `resolv.conf`, so both kinds of tools query the same server. If your users report that browsers resolve internal names but `dig` does not, see [dig and host fail, but browsers and curl work](/manage/dns/troubleshooting#issue-5-dig-and-host-fail-but-browsers-and-curl-work-mac-os). + +On Windows, a primary nameserver makes NetBird the **exclusive** resolver while the peer is connected. Windows otherwise queries the resolvers of every network adapter in parallel and keeps the first answer that arrives, which both leaks queries to the local network and lets another resolver answer for a name NetBird is authoritative for. The client prevents that with a Name Resolution Policy Table rule covering every namespace. + +The cost is that names only the local network's resolver knows — a home router's own zone, or an internal domain not reachable through NetBird — stop resolving while connected. Declare those zones as match domain nameservers: a more specific rule takes precedence over the catch-all, so a declared zone keeps resolving. `.local` is exempt, so multicast DNS names keep working. + +Setting `NB_USE_LEGACY_DNS_RESOLUTION=true` on a peer restores the previous behaviour — see [Client Environment Variables](/client/environment-variables). + + ### Search Domains Toggle **Mark match domains as search domains** to enable domain suffix searching. When enabled, typing `server` expands to `server.company.internal`. Only applies to match domain nameservers. @@ -108,6 +116,10 @@ Toggle **Mark match domains as search domains** to enable domain suffix searchin **Don't convert a match-domain group to primary by emptying its domains.** Removing the match domains also removes the search domains, so short names like `server` stop expanding. Domain-joined Windows machines hide the regression because Active Directory supplies its own suffix, so it surfaces as "short names broke for some users." To add a primary, create a **second** nameserver group with the same servers and leave the existing match-domain group in place. + +On Windows, whether a short name resolves depends on the order in which the DNS client tries each adapter's suffixes: it stops at the first suffix that answers "no such name" rather than trying the rest. When the machine's own domain is tried before NetBird's — usual on domain-joined machines — a short name fails even though its fully qualified form resolves. Use the fully qualified name, or move the zone behind a match domain nameserver. + + ### Split-Horizon DNS A common setup with two nameservers: From a42998f4fb9c4047a52a7e057c72e493814d2bbc Mon Sep 17 00:00:00 2001 From: riccardom Date: Thu, 27 Aug 2026 15:25:49 +0200 Subject: [PATCH 2/3] docs: correct how Windows expands short names, and say from which version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes to the notes added in the previous commit. The short-name mechanism was described wrongly. Windows does not stop at the first suffix that misses: it walks the whole suffix list of the preferred interface, and what it will not do is fall through to another interface's suffixes. Measured on a Windows 11 machine — with NetBird's adapter preferred, a list of {fritz.box, netbird.cloud} resolves a name that only exists under the second entry; with the metric raised so the physical adapter wins, the same name fails because only that adapter's single suffix is ever tried. The practical advice changes with it: declaring the local zone with search domains enabled puts both suffixes in one list, which is what makes short names work either way. Both notes now say the exclusive behaviour arrives in client v0.78.0 and what earlier clients did instead, so the page reads correctly for someone still on 0.77, and the environment variable is marked with the version that introduces it. --- src/pages/client/environment-variables.mdx | 2 +- src/pages/manage/dns/internal-dns-servers.mdx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/client/environment-variables.mdx b/src/pages/client/environment-variables.mdx index 53a0afef3..834d74e95 100644 --- a/src/pages/client/environment-variables.mdx +++ b/src/pages/client/environment-variables.mdx @@ -82,7 +82,7 @@ To clear all saved service parameters (including env vars), run `sudo netbird se | `NB_DNS_FORWARDER_PORT` | All | Override the port the internal DNS forwarder binds to for handling DNS routes received from clients (default: `22054`). The forwarder is separate from the local resolver. | | `NB_SKIP_DNS_PROBE` | All | Skip the startup check that sends a test query to the local resolver to verify it is reachable. Set this if the probe causes delays (e.g. in air-gapped networks). | | `NB_DNS_LAZY_WARMUP_TIMEOUT` | All | Per-query budget for waking an idle peer when the local resolver returns one of its A or AAAA records (Go duration, default: `2s`). The value must be positive; invalid, zero, or negative values use the default. | -| `NB_USE_LEGACY_DNS_RESOLUTION` | Windows | Go back to only setting the NetBird address as the tunnel adapter's nameserver, leaving Windows free to query the other adapters' resolvers in parallel. By default, a peer with a primary nameserver also gets a Name Resolution Policy Table rule that sends every query to the NetBird resolver and nowhere else. Set this if a zone that only the local network resolves has to stay reachable while connected and cannot be declared as a match domain — it also brings back the query leak and the non-deterministic resolution the rule prevents. | +| `NB_USE_LEGACY_DNS_RESOLUTION` | Windows | Available from client v0.78.0. Go back to only setting the NetBird address as the tunnel adapter's nameserver, leaving Windows free to query the other adapters' resolvers in parallel. By default, a peer with a primary nameserver also gets a Name Resolution Policy Table rule that sends every query to the NetBird resolver and nowhere else. Set this if a zone that only the local network resolves has to stay reachable while connected and cannot be declared as a match domain — it also brings back the query leak and the non-deterministic resolution the rule prevents. | | `NB_UNCLEAN_SHUTDOWN_RESOLV_FILE` | Linux, FreeBSD | Custom file path to store a backup of `/etc/resolv.conf` before the client modifies it. Used to restore the original on next startup if the client crashed without cleaning up (default: `/resolv.conf`, i.e. `/var/lib/netbird/resolv.conf` on Linux, `/var/db/netbird/resolv.conf` on FreeBSD). | ## Connection retry diff --git a/src/pages/manage/dns/internal-dns-servers.mdx b/src/pages/manage/dns/internal-dns-servers.mdx index e9a4e5d55..3928ffef4 100644 --- a/src/pages/manage/dns/internal-dns-servers.mdx +++ b/src/pages/manage/dns/internal-dns-servers.mdx @@ -101,11 +101,11 @@ Each peer should have exactly **one** primary nameserver. If you don't configure A primary nameserver does more than catch unmatched queries. On macOS, a match-domain-only configuration registers a *scoped* resolver through system APIs and leaves the nameservers in `/etc/resolv.conf` untouched. Applications that use the system resolver follow the scoped entry, but tools that read `resolv.conf` directly (`dig`, `host`, and some language runtimes) keep querying your LAN or public nameservers and get `NXDOMAIN` for internal names. Adding a primary group puts NetBird's resolver into `resolv.conf`, so both kinds of tools query the same server. If your users report that browsers resolve internal names but `dig` does not, see [dig and host fail, but browsers and curl work](/manage/dns/troubleshooting#issue-5-dig-and-host-fail-but-browsers-and-curl-work-mac-os). -On Windows, a primary nameserver makes NetBird the **exclusive** resolver while the peer is connected. Windows otherwise queries the resolvers of every network adapter in parallel and keeps the first answer that arrives, which both leaks queries to the local network and lets another resolver answer for a name NetBird is authoritative for. The client prevents that with a Name Resolution Policy Table rule covering every namespace. +From client **v0.78.0**, on Windows a primary nameserver makes NetBird the **exclusive** resolver while the peer is connected. Earlier clients only set the resolver on the tunnel adapter, leaving Windows free to query the other adapters' resolvers alongside it. Windows otherwise queries the resolvers of every network adapter in parallel and keeps the first answer that arrives, which both leaks queries to the local network and lets another resolver answer for a name NetBird is authoritative for. The client prevents that with a Name Resolution Policy Table rule covering every namespace. The cost is that names only the local network's resolver knows — a home router's own zone, or an internal domain not reachable through NetBird — stop resolving while connected. Declare those zones as match domain nameservers: a more specific rule takes precedence over the catch-all, so a declared zone keeps resolving. `.local` is exempt, so multicast DNS names keep working. -Setting `NB_USE_LEGACY_DNS_RESOLUTION=true` on a peer restores the previous behaviour — see [Client Environment Variables](/client/environment-variables). +Setting `NB_USE_LEGACY_DNS_RESOLUTION=true` on a peer restores the pre-v0.78.0 behaviour — see [Client Environment Variables](/client/environment-variables). ### Search Domains @@ -117,7 +117,9 @@ Toggle **Mark match domains as search domains** to enable domain suffix searchin -On Windows, whether a short name resolves depends on the order in which the DNS client tries each adapter's suffixes: it stops at the first suffix that answers "no such name" rather than trying the rest. When the machine's own domain is tried before NetBird's — usual on domain-joined machines — a short name fails even though its fully qualified form resolves. Use the fully qualified name, or move the zone behind a match domain nameserver. +On Windows a short name is expanded by the DNS client using the suffix list of the **preferred** network interface — the one with the lowest interface metric. Windows walks that list in full, but it does not fall through to another interface's suffixes when the name is not found there. So when an adapter other than NetBird's is preferred, a short name fails while its fully qualified form resolves. + +NetBird's interface usually wins, but a tie on the metric is enough to lose it. When that happens, declaring the local network's zone as a match domain with search domains enabled puts both suffixes in the same list, and short names resolve again for either zone. Otherwise, use the fully qualified name. ### Split-Horizon DNS From a6a8d8c1f39cdc2b9ea434ae714a78538a3bdb60 Mon Sep 17 00:00:00 2001 From: riccardom Date: Thu, 27 Aug 2026 15:36:41 +0200 Subject: [PATCH 3/3] docs: say that exclusive resolution is what breaks short names on Windows The suffix-search behaviour is not Windows' own: without the catch-all NRPT rule Windows keeps searching the other adapters' suffix lists, and the short name resolves. Gate the note to v0.78.0 and point at it from the exclusivity note, so both texts agree on what the change costs. --- src/pages/manage/dns/internal-dns-servers.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/manage/dns/internal-dns-servers.mdx b/src/pages/manage/dns/internal-dns-servers.mdx index 3928ffef4..c4e8129c3 100644 --- a/src/pages/manage/dns/internal-dns-servers.mdx +++ b/src/pages/manage/dns/internal-dns-servers.mdx @@ -103,7 +103,7 @@ A primary nameserver does more than catch unmatched queries. On macOS, a match-d From client **v0.78.0**, on Windows a primary nameserver makes NetBird the **exclusive** resolver while the peer is connected. Earlier clients only set the resolver on the tunnel adapter, leaving Windows free to query the other adapters' resolvers alongside it. Windows otherwise queries the resolvers of every network adapter in parallel and keeps the first answer that arrives, which both leaks queries to the local network and lets another resolver answer for a name NetBird is authoritative for. The client prevents that with a Name Resolution Policy Table rule covering every namespace. -The cost is that names only the local network's resolver knows — a home router's own zone, or an internal domain not reachable through NetBird — stop resolving while connected. Declare those zones as match domain nameservers: a more specific rule takes precedence over the catch-all, so a declared zone keeps resolving. `.local` is exempt, so multicast DNS names keep working. +The cost is that names only the local network's resolver knows — a home router's own zone, or an internal domain not reachable through NetBird — stop resolving while connected. Declare those zones as match domain nameservers: a more specific rule takes precedence over the catch-all, so a declared zone keeps resolving. `.local` is exempt, so multicast DNS names keep working. Short names can also stop expanding when another adapter is preferred — see the note under [Search Domains](#search-domains). Setting `NB_USE_LEGACY_DNS_RESOLUTION=true` on a peer restores the pre-v0.78.0 behaviour — see [Client Environment Variables](/client/environment-variables). @@ -117,9 +117,9 @@ Toggle **Mark match domains as search domains** to enable domain suffix searchin -On Windows a short name is expanded by the DNS client using the suffix list of the **preferred** network interface — the one with the lowest interface metric. Windows walks that list in full, but it does not fall through to another interface's suffixes when the name is not found there. So when an adapter other than NetBird's is preferred, a short name fails while its fully qualified form resolves. +**On Windows, from client v0.78.0**, making NetBird the exclusive resolver also ends the suffix search early. A short name is expanded by the DNS client using the suffix list of the **preferred** network interface — the one with the lowest interface metric — and Windows no longer falls through to another interface's suffixes when the name is not found there. So when an adapter other than NetBird's is preferred, a short name fails while its fully qualified form still resolves. Earlier clients kept searching the other adapters' suffixes, so the same short name resolved. -NetBird's interface usually wins, but a tie on the metric is enough to lose it. When that happens, declaring the local network's zone as a match domain with search domains enabled puts both suffixes in the same list, and short names resolve again for either zone. Otherwise, use the fully qualified name. +NetBird's interface is usually the preferred one, but a tie on the metric is enough to lose it. When that happens, declaring the local network's zone as a match domain with search domains enabled puts both suffixes in the same list, and short names resolve again for either zone. Otherwise use the fully qualified name, or set `NB_USE_LEGACY_DNS_RESOLUTION=true` to go back to shared resolution. ### Split-Horizon DNS