diff --git a/public/docs-static/img/manage/dns/nameservers-route-all-internal.png b/public/docs-static/img/manage/dns/nameservers-route-all-internal.png new file mode 100644 index 00000000..6a68c8d3 Binary files /dev/null and b/public/docs-static/img/manage/dns/nameservers-route-all-internal.png differ diff --git a/src/pages/help/troubleshooting-client/windows.mdx b/src/pages/help/troubleshooting-client/windows.mdx index 8ee74836..8c1a6548 100644 --- a/src/pages/help/troubleshooting-client/windows.mdx +++ b/src/pages/help/troubleshooting-client/windows.mdx @@ -98,7 +98,7 @@ Windows Firewall or endpoint security software can block NetBird traffic before DNS on Windows has a few platform-specific failure modes worth checking separately: -- **Match-domain names don't resolve, even though the NRPT (Name Resolution Policy Table) rule was written.** A lingering Group Policy `DnsPolicyConfig` container can stop NetBird's rule from taking effect on an off-domain machine. See [DNS Troubleshooting: Issue 8 (lingering GPO)](/manage/dns/troubleshooting#issue-8-windows-nrpt-rule-is-written-but-never-takes-effect-lingering-gpo). +- **Match-domain names don't resolve, even though the NRPT (Name Resolution Policy Table) rule was written.** A lingering Group Policy `DnsPolicyConfig` container can stop NetBird's rule from taking effect on an off-domain machine. See [DNS Troubleshooting: Issue 9 (lingering GPO)](/manage/dns/troubleshooting#issue-9-windows-nrpt-rule-is-written-but-never-takes-effect-lingering-gpo). - **Active Directory login, mapped drives, or DFS fail** while a file share by IP works. This is usually a DC-locator (`SRV` record) problem. See [Domain Controllers as routing peers](/manage/dns/internal-dns-servers#domain-controllers-as-routing-peers). - **NetBird won't start on a Domain Controller** and the peer shows disconnected. The Windows DNS Server service can claim WireGuard's UDP port 51820 before NetBird does, so the tunnel never comes up. See [WireGuard port conflict on Domain Controllers](/manage/dns/internal-dns-servers#wire-guard-port-conflict-on-domain-controllers). diff --git a/src/pages/manage/dns/index.mdx b/src/pages/manage/dns/index.mdx index f8c75d4a..16bf79f9 100644 --- a/src/pages/manage/dns/index.mdx +++ b/src/pages/manage/dns/index.mdx @@ -100,7 +100,7 @@ You don't need to configure custom nameservers to use NetBird. On Linux, peer do NetBird configures the operating system to use its DNS resolver: - **Linux**: Always sets up DNS via `/etc/resolv.conf` or `resolvconf`. Original nameservers preserved as upstream. -- **macOS**: Uses system APIs (does **not** modify `/etc/resolv.conf` directly) +- **macOS**: Uses system APIs. Match-domain nameservers become scoped resolvers (visible in `scutil --dns`, not in `/etc/resolv.conf`); a primary nameserver makes macOS regenerate `/etc/resolv.conf` with NetBird's resolver in it - **Windows**: Sets the network adapter's DNS server to the local NetBird resolver - **Android/iOS**: Uses VPN DNS configuration diff --git a/src/pages/manage/dns/internal-dns-servers.mdx b/src/pages/manage/dns/internal-dns-servers.mdx index 25d903c0..e5259b83 100644 --- a/src/pages/manage/dns/internal-dns-servers.mdx +++ b/src/pages/manage/dns/internal-dns-servers.mdx @@ -98,11 +98,17 @@ For details, see [Manage Network Access](/manage/access-control/manage-network-a Each peer should have exactly **one** primary nameserver. If you don't configure a primary, peers use their original DNS settings for non-matched queries. +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). + ### 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. -### Example: Split-Horizon DNS + +**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. + + +### Split-Horizon DNS A common setup with two nameservers: @@ -115,6 +121,27 @@ Result: - `app.company.internal` → Internal DNS (10.0.0.1) - `server` → Expanded to `server.company.internal` → Internal DNS +### Route All Queries to Internal DNS + +If you are migrating from a VPN that pushed your internal DNS servers for everything (a common OpenVPN setup), the equivalent is the same two groups as in the split-horizon example, but both pointing at your **internal servers**: + + +This setup requires internal DNS servers that resolve public domains too, by recursing or forwarding upstream. Active Directory DNS servers do this by default. If your servers are authoritative-only for the internal zone, making them primary cuts off public resolution; use the split-horizon setup above instead. + + +**Primary (internal)**: Custom DNS with your internal DNS server IPs (e.g., 10.0.0.1, 10.0.0.2). Assign to your target group. Leave match domains empty. + +**Match domain (internal)**: Same servers. Add match domain `company.internal`. Enable search domains. + +Two nameserver groups pointing at the same internal DNS servers: one primary with no match domains, one with match domain company.internal and search domains enabled + +Result: +- All queries, public and internal, go to your internal DNS +- `server` still expands to `server.company.internal` +- Tools that read `/etc/resolv.conf` directly and tools that use the system resolver query the same server + +Two groups look redundant when they hold the same servers, but they do different jobs: the primary receives every query, while the match-domain group provides the search-domain expansion. A VPN "pushing DNS servers" maps to the **primary** group, not to a match-domain group. + ### DNS Failover and Overlapping Domains Configure multiple nameserver IPs within a single nameserver entry for automatic failover. The client tries servers in order. diff --git a/src/pages/manage/dns/troubleshooting.mdx b/src/pages/manage/dns/troubleshooting.mdx index 16c0e5c4..58a63657 100644 --- a/src/pages/manage/dns/troubleshooting.mdx +++ b/src/pages/manage/dns/troubleshooting.mdx @@ -42,12 +42,14 @@ dig @10.0.0.53 app.internal.company.com # Replace 10.0.0.53 with your actual nameserver IP # 6. Can you resolve match domains through the system resolver? +# Use the tools below, not dig/host/nslookup: those test a DIFFERENT path +# (see Issue 5) and can report NXDOMAIN while the system resolver works. # Linux: resolvectl query app.internal.company.com # macOS: dscacheutil -q host -a name app.internal.company.com -# Windows/Cross-platform: -nslookup app.internal.company.com +# Windows: +Resolve-DnsName app.internal.company.com # 7. Confirm public domains still resolve (verifies split DNS is working) nslookup google.com @@ -372,7 +374,63 @@ cat /etc/resolv.conf **Fix**: Limit to 3-4 most important search domains. -### Issue 5: DNS Works on NetBird Network, Fails Outside +### Issue 5: dig and host Fail, but Browsers and curl Work (macOS) + +**Symptoms**: +- Browsers, `curl`, and most applications resolve internal names fine +- `dig` and `host` return `NXDOMAIN` for the same names, short and fully qualified +- Typically on macOS with a match-domain nameserver and no primary; hits CLI tooling and IDEs hardest + +**Diagnosis**: + +macOS resolves names through two separate paths, and they can disagree: + +- **The system resolver** (`getaddrinfo`, via mDNSResponder): used by browsers, `curl`, and most applications. It follows *scoped* resolvers, the per-domain entries that `scutil --dns` lists (flagged `Supplemental` in its output). +- **`/etc/resolv.conf` readers**: `dig`, `host`, and some language runtimes read this file directly and query the nameservers in it themselves. + +A match-domain nameserver registers a scoped resolver, and the `resolv.conf` format cannot express "use this server, but only for this domain". So `resolv.conf` keeps your LAN or public nameservers, and `dig` asks those, receives an authoritative `NXDOMAIN` for the internal zone, and reports it confidently. Resolution did not fail; it succeeded against the wrong server. + +Search domains sharpen the trap: they *do* merge into `resolv.conf`, so `host myserver` expands the short name to `myserver.company.internal` and then still asks the wrong nameserver. + +Confirm the split: + +```bash +# System resolver path — works: +dscacheutil -q host -a name app.company.internal + +# resolv.conf path — NXDOMAIN: +dig app.company.internal + +# The scoped resolver dig cannot see: +scutil --dns | grep -B1 -A4 company.internal + +# Query NetBird's resolver directly — works, showing the query succeeds +# through NetBird's resolver (replace 100.x.255.254 with the nameserver +# from the scutil --dns resolver block whose domain is your internal zone): +dig @100.x.255.254 app.company.internal +``` + +If `dscacheutil` and `dig @100.x.255.254` resolve while plain `dig` does not, the client is working as configured: `dig` is just reading `resolv.conf`. + +Language runtimes split the same way (verified on macOS), which is how this reaches developers: + +| Reads `resolv.conf` (misses scoped resolvers) | Uses the system resolver (works) | +|---|---| +| Go's pure-Go resolver (`GODEBUG=netdns=go`, the default in `CGO_ENABLED=0` builds) | Go's cgo resolver | +| Python `dnspython` | Python `socket.getaddrinfo` | +| Node.js `dns.resolve4()` and friends (c-ares) | Node.js `dns.lookup()` | + +Windows has the same two-path split under different names: NetBird steers match domains with an NRPT rule, which `Resolve-DnsName` honors but `nslookup` bypasses (it queries the adapter's nameservers directly). This is why the diagnostics on this page prescribe `dscacheutil` on macOS and `Resolve-DnsName` on Windows. + +**Solution**: + +Add a **primary** nameserver group (leave Match Domains empty) pointing at the same internal DNS servers, alongside the existing match-domain group. The primary puts NetBird's resolver into `/etc/resolv.conf`, so both paths query the same server. The internal servers must resolve public domains too (by recursing or forwarding upstream, which Active Directory DNS servers do by default); if they are authoritative-only for the internal zone, point the primary group at a resolver that handles public domains instead. + +Keep the match-domain group with search domains enabled; do not convert it by emptying its domains, which silently drops the search suffix (see [Search Domains](/manage/dns/internal-dns-servers#search-domains)). + +**Verify**: `dig app.company.internal` and `host myserver` both resolve, and `cat /etc/resolv.conf` shows `nameserver 100.x.255.254` plus your search domain. + +### Issue 6: DNS Works on NetBird Network, Fails Outside **Symptoms**: - DNS works when connected to NetBird @@ -426,7 +484,7 @@ sudo systemctl disable netbird curl -sSL https://pkgs.netbird.io/install.sh | sh ``` -### Issue 6: DNS Rebinding Protection +### Issue 7: DNS Rebinding Protection **Symptoms**: - Router blocks internal DNS queries @@ -457,7 +515,7 @@ config domain --- -### Issue 7: Active Directory Login or DFS Fails (but a file share by IP works) +### Issue 8: Active Directory Login or DFS Fails (but a file share by IP works) **Symptoms**: - Domain login, mapped drives, or DFS paths fail for remote users — yet the file server is reachable by IP @@ -479,7 +537,7 @@ Running the NetBird client directly **on** a Domain Controller is a separate cas --- -### Issue 8: Windows NRPT rule is written but never takes effect (lingering GPO) +### Issue 9: Windows NRPT rule is written but never takes effect (lingering GPO) **Symptoms**: - Match-domain names don't resolve on a Windows client, even though `netbird status -d` shows the nameserver as Available and the client log records the NRPT (Name Resolution Policy Table) rule as written.