Stop pointing clients at the domain controller for DNS
Nathan Chadwick · · 7 min read
TLDRRead the short version
- Pointing every Windows client at a domain controller for DNS is still the default in a lot of estates. It is also one of the most common ways to create a false compromise story, a silent single point of failure, and a firewall that cannot see who asked for what.
- When a DC recurses for a client, the firewall only sees the DC’s IP. East-west DNS never hits the edge, so outbound resolution looks like the domain controller is browsing the internet on its own.
- If that DC goes offline, users do not say “DNS failed”. They say the internet is down. A secondary DNS entry on the NIC is not real HA: Windows sticks to the preferred server and only fails over on timeout.
- Better pattern: DHCP hands clients the firewall (or another controlled recursive resolver) as DNS. External names go to an authoritative public resolver such as Cloudflare or Google. Internal AD zones forward to the domain controllers so Kerberos, LDAP, and domain join keep working.
- You keep AD-integrated DNS where it belongs, regain north-south visibility and filtering at the edge, and stop coupling “can I open a webpage” to “is a domain controller up”.
The pattern I keep walking into#
Open DHCP. Look at the DNS option. More often than not it is the IP of a domain controller.
That setting feels safe. Active Directory needs DNS. Domain controllers usually run DNS. Microsoft’s own client guidance has historically pointed member servers at DNS servers that host the AD zone. So the mental leap is easy: put the DC in the DNS field and walk away.
That leap is where a lot of estates go wrong—not because AD-integrated DNS is a bad idea, but because making the DC every client’s recursive resolver mixes three jobs that should stay separated:
- Authoritative answers for your AD zones (
_msdcs, SRV records, domain hosts). - Recursive resolution for everything else on the internet.
- Policy and visibility for who asked for which name.
When all three sit on the same box, and every laptop talks to that box directly, you get security theatre, resilience theatre, and a helpdesk that blames “the internet” when a domain controller reboots.
What the firewall actually sees#
Picture a client on the LAN resolving evil.example.
Bad pattern: client → domain controller → public DNS (or recursion through the DC’s forwarders).
The packet that leaves toward the internet is sourced from the domain controller. Your firewall, SIEM, and threat intel see:
- source:
dc01.corp.local - destination:
1.1.1.1/8.8.8.8/ whatever you forward to - query: whatever the user typed
You lost the originating client. The request is east-west on the inside until the DC decides to recurse. Many perimeter designs never inspect that hop. Even when they do, attribution is wrong: it looks like the DC is talking to the world.
That is how you get false positives that waste a day. An MDR analyst flags “domain controller making unusual DNS lookups”. Someone opens a ticket for a compromised DC. You chase lateral movement that never happened—because a helpdesk machine resolved a phishing domain and the DC kindly asked on its behalf.
Good pattern: client → firewall DNS → (external) Cloudflare/Google or (internal) domain controller.
Now the firewall sees the real client IP, can apply DNS policy, can log the query against the device that asked, and only forwards AD-namespace queries to the DCs. The domain controllers still answer for Kerberos and domain join. They stop looking like they are “browsing” the internet for every user on the floor.
If your firewall is blind to origin DNS today, that is not a tooling gap. It is a design choice: you put recursion behind a host the edge never sees as the client.
Single point of failure dressed up as “AD best practice”#
Couple every workstation’s ability to resolve google.com to the health of a domain controller and you have built a single point of failure with excellent branding.
When that DC is patched, blue-screens, loses a NIC, or has a hung DNS service:
- Outlook looks broken.
- Teams looks broken.
- “The internet is down” tickets flood in.
- AD authentication may also be degraded—so you are fighting identity and name resolution at the same time.
A second DC listed as alternate DNS on the client does not fix this the way people think. Windows does not round-robin between primary and secondary for load or neat failover. The DNS Client keeps a priority per configured server. In practice it sticks to the preferred server while that server answers. It only moves on when queries time out. After a failover it can keep preferring the alternate for a while (ServerPriorityTimeLimit defaults to fifteen minutes) before priorities reset.
So:
- Most of the time almost all clients hammer DNS1.
- DNS2 sits idle until timeouts happen.
- A DC that is “up” but answering slowly or incorrectly can keep traffic stuck on the broken path.
- Your secondary entry is a timeout safety net, not an active-active DNS design.
That is why “we have two DCs in DHCP so we’re fine” is one of the most common false comforts in Windows estates.
Why sysadmins get this wrong#
A few honest reasons it keeps shipping this way:
- AD and DNS were taught as one thing. For locator records they are tightly coupled. For recursion they should not be.
- It works in the lab. One subnet, one DC, no MDR, no east-west logging. The pain only shows under load, incident response, or the first unplanned DC outage.
- Microsoft docs talk about pointing at AD DNS. They are solving “can the machine find a domain controller?”, not “should the domain controller be the recursive resolver for Netflix and phishing domains?”. Those are different questions.
- Firewalls got DNS late in many shops. Older designs treated DNS as an OS concern. Modern appliances can terminate DNS, filter categories, and forward by zone. The design did not always catch up.
- Secondary DNS feels like HA. The checkbox is there. The behaviour is not what the checkbox implies.
None of that makes the default evil. It makes it under-specified.
The design that separates the jobs#
Give clients one recursive address they care about: your firewall (or a pair of firewalls / dedicated recursive resolvers you control). Then split forwarding by namespace.
| Query type | Where it should go | Why |
| --- | --- | --- |
| corp.local, _msdcs.corp.local, AD SRV/host records | Domain controllers (AD-integrated DNS) | Kerberos, LDAP, secure channel, domain join, GPO location |
| Everything else | Public recursive DNS you trust (e.g. Cloudflare 1.1.1.1, Google 8.8.8.8, or a protective DNS service) | Internet resolution without putting recursion on a DC |
| Policy / logging | On the firewall path | Client identity, block lists, NXDOMAIN anomalies, audit trail |
On Sophos Firewall and similar products this is usually DNS request route / conditional forwarder style config: match internal domains to the DC IPs, default everything else to upstream resolvers. DHCP option 006 (and IPv6 DNS options) should hand out the firewall LAN IP, not dc01.
Domain controllers still run DNS. They still hold the AD zones. Member servers and clients still reach those zones—just via the firewall’s forwarder for internal names, not by treating the DC as the only brain on the network.
What you gain#
- Correct attribution. DNS logs show the laptop, not a mysterious DC.
- Fewer false compromise stories. Outbound recursion no longer looks like the domain controller went rogue.
- Resilience. A DC reboot no longer equals “WAN is dead” for every browser tab—so long as the firewall and upstream resolvers stay up, and internal names still have a healthy forwarder path (ideally to more than one DC).
- A place to put controls. Protective DNS, category filtering, sinkholing, and query logging belong on infrastructure you expect to inspect, not buried inside AD.
What you must not break#
- Do not point clients only at public DNS and hope AD still works. Domain join and Kerberos need your internal zones.
- Do not stop hosting AD DNS on the DCs unless you have a deliberate alternative that still serves locator records correctly.
- Do not forward the AD zone to the internet. Conditional forwarders are one way: internal names to DCs, external names outbound.
- Do test domain join, GPO, LDAP, certificate enrolment, and a cold boot of a DC while users are online.
A practical cutover#
- Inventory DHCP scopes and static DNS on servers. Find every place that lists a DC as preferred DNS for clients.
- On the firewall, enable DNS for the LAN (or point to your chosen recursive pair). Add request routes for your AD DNS suffixes to both (or all) DC DNS IPs.
- Set upstream resolvers to Cloudflare, Google, or your protective DNS provider. Prefer providers you can explain in an audit.
- Change a pilot scope first: one VLAN or one office. Confirm resolution for internal hosts and external sites. Confirm
nltest/ secure channel / domain join on a test machine. - Watch logs. You should suddenly see client IPs in DNS telemetry. That is the point.
- Roll the rest of DHCP, then chase static outliers (jump boxes, printers, poorly imaged servers).
- Leave DC DNS running for AD. Optionally tighten so only the firewall (and other DCs) may query the DCs for recursion-related paths if your control model allows it—without breaking replication and inter-DC DNS.
Summary#
Pointing every client at a domain controller for DNS is a habit, not a design. It blinds the firewall to who is asking, makes healthy DCs look compromised when they recurse for users, and turns a directory service outage into an “internet down” event. Windows will not save you with a secondary DNS checkbox; clients stick to the primary until timeouts say otherwise.
Use the firewall as the DNS server clients talk to. Send external resolution to a proper public or protective resolver. Forward internal names to the domain controllers so Kerberos and domain services keep working. Same AD. Same zones. Far less mystery—and far fewer days spent proving the DC was only being a good neighbour.
References#
Sources and further reading for the claims above.