mirror of
https://github.com/netbirdio/docs.git
synced 2026-08-24 16:51:26 +02:00
docs: explain macOS DNS resolver behavior for match-only vs primary nameservers (#912)
* docs: explain macOS two-resolver-stack DNS behavior and the match-only vs primary nameserver split Lab-validated against client 0.76.3 (macOS 26, NetBird Cloud): - DNS troubleshooting: new Issue 5 'dig and host fail, but browsers and curl work (macOS)' with the scoped-resolver vs resolv.conf explanation, the language-runtime split table (pure-Go/dnspython/c-ares vs getaddrinfo), and the Windows nslookup-vs-NRPT analog; renumbered Issues 5-8 to 6-9; checklist step 6 now says why it prescribes dscacheutil/Resolve-DnsName - Internal DNS Servers: primary-vs-match now explains that match-only leaves resolv.conf untouched on macOS; new warning that emptying a match group's domains silently drops the search suffix (masked on domain-joined Windows); split-horizon example gains the route-everything-internal variant (the OpenVPN migration shape) - DNS overview: macOS line now distinguishes scoped resolvers from the primary case, where configd regenerates resolv.conf with NetBird's resolver * docs: add dashboard screenshot for the route-all-internal nameserver example * docs: polish wording in the macOS DNS additions * docs: promote the route-all-internal example to its own section * docs: drop the Example prefix from the nameserver scenario headings * docs: state the public-resolution prerequisite for an internal primary nameserver * docs: make the direct-resolver check precise * docs: anchor the scoped-resolver term to scutil output and split the dense solution paragraph
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -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).
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
</Note>
|
||||
|
||||
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
|
||||
<Note>
|
||||
**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.
|
||||
</Note>
|
||||
|
||||
### 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**:
|
||||
|
||||
<Note>
|
||||
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.
|
||||
</Note>
|
||||
|
||||
**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.
|
||||
|
||||
<img src="/docs-static/img/manage/dns/nameservers-route-all-internal.png" alt="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" className="imagewrapper-big"/>
|
||||
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user