Skip to content

Active Directory DC Locator and DNS Troubleshooting

When a Windows client cannot find or use a domain controller (DC), trace the path in order: the client asks its local Netlogon service for a DC, DNS returns service records, the client probes candidates, and Netlogon caches a suitable response. This guide gives senior administrators a repeatable way to separate locator, DNS registration, site mapping, and network-path failures.

01

Understand the DC Locator Sequence

Architecture

Applications normally reach the locator through Windows APIs such as DsGetDcName. The request is handled by the local Netlogon service. For DNS-based discovery, Netlogon asks DNS for SRV records that advertise the requested DC capability, resolves candidate host names to addresses, and sends UDP LDAP pings (CLDAP locator requests) to candidates. A responding DC reports whether it is operating and returns site information; the client can retry using site-specific records. Netlogon returns and caches a suitable DC so later requests tend to use the same server.

NetBIOS-style discovery is a separate legacy path. It can use WINS and mailslot datagrams. Do not interpret “mailslot/LDAP ping” as two stages in the normal DNS path: DNS-based discovery uses LDAP/CLDAP over UDP, while mailslot belongs to legacy NetBIOS discovery. Newer Windows Server releases deprecate or restrict legacy NetBIOS location behavior.

Application / Windows component
|
v
DsGetDcName request -> local Netlogon service
|
+-- DNS SRV lookup -> candidate DC hostnames
| |
| v
| A/AAAA address lookup
| |
| v
| UDP LDAP ping (CLDAP, 389)
| |
| suitable DC replies with site data
| |
+<-- selected DC; locator result is cached
Legacy NetBIOS lookup -> WINS/broadcast -> mailslot ping
❯ Illustrative Output (Results Vary)
Expected DNS path: query -> SRV answer -> target address -> UDP LDAP ping -> DC response
If SRV is absent, troubleshoot DNS publication/resolution first.
If SRV and target address are correct but no DC is returned, inspect UDP 389 and return routing.

02

Map the Locator Records and Site Selection

DNS Records

Domain controllers publish service location (SRV) records through Netlogon and host (A/AAAA) records through DNS registration. The forest-wide _msdcs zone also holds GUID-based CNAME records used to identify replication partners. These names are examples of the important records; the full set varies with DC roles, site configuration, and forest design.

  • _ldap._tcp.dc._msdcs.<DomainFQDN> — domain controller LDAP locator records, normally port 389.
  • _ldap._tcp.<DomainFQDN> — LDAP service records for the domain.
  • _kerberos._tcp.dc._msdcs.<DomainFQDN> and _kerberos._udp.<DomainFQDN> — Kerberos KDC service records, normally port 88.
  • _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainFQDN> — site-specific DC LDAP records.
  • _ldap._tcp.gc._msdcs.<ForestRootFQDN> — Global Catalog LDAP records, normally port 3268; site-specific GC records are also published where applicable.
  • _ldap._tcp.pdc._msdcs.<DomainFQDN> — the PDC emulator locator record.
  • <DSA-GUID>._msdcs.<ForestRootFQDN> — a CNAME pointing to the DC’s DNS host name; that host name must resolve to the correct address.

AD Sites and Services maps client IP subnets to sites. The locator uses this site information to prefer an appropriate local-site DC, querying site-specific records when it knows the client site and falling back to broader records when needed. SRV priority selects lower-numbered priorities first; weight distributes selection among records at the same priority. “Closest” therefore depends on correct subnet-to-site mapping and advertised records, not simply geographic distance.

Terminal window
$domain = 'contoso.com'
$site = 'Branch-01'
$forestRoot = 'contoso.com'
Resolve-DnsName -Type SRV "_ldap._tcp.dc._msdcs.$domain"
Resolve-DnsName -Type SRV "_ldap._tcp.$site._sites.dc._msdcs.$domain"
Resolve-DnsName -Type SRV "_kerberos._tcp.dc._msdcs.$domain"
Resolve-DnsName -Type SRV "_ldap._tcp.gc._msdcs.$forestRoot"
Resolve-DnsName -Type CNAME `
'11111111-2222-3333-4444-555555555555._msdcs.contoso.com'
# On a DC, inspect the records Netlogon is configured to register:
Get-Content "$env:SystemRoot\System32\Config\netlogon.dns" |
Select-String -Pattern '_ldap|_kerberos|_msdcs'
❯ Illustrative Output (Results Vary)
NameTarget Priority Weight Port
---------- -------- ------ ----
dc01.contoso.com 0 100 389
dc02.contoso.com 0 100 389
Resolve each SRV target separately. A valid SRV answer pointing to a stale
or wrong host address is still a broken locator path.

03

Run the Client-Side Locator and DNS Checks

Diagnostic Toolkit

Start on the failing client. Confirm that its active interface uses DNS servers authoritative for, or correctly forwarding, the AD zones. Then check the client’s site, force a new locator lookup, query the SRV records against the intended DNS server, and resolve the returned host names. Compare the results with a healthy client on the same subnet. For dcdiag, target the DC being investigated from an elevated session with the AD DS tools available. /DnsRecordRegistration checks essential host, GUID CNAME, LDAP, GC, and PDC records. /DnsDynamicUpdate checks dynamic update by creating and deleting a test record in the relevant DNS zone; this is not a read-only test.

Terminal window
ipconfig /all
Get-DnsClientServerAddress |
Where-Object ServerAddresses |
Format-Table InterfaceAlias, AddressFamily, ServerAddresses -AutoSize
nltest /dsgetsite
nltest /dsgetdc:contoso.com /force
$dnsServer = '10.0.0.10' # AD DNS server used by this client/site
Resolve-DnsName -Server $dnsServer -Type SRV `
_ldap._tcp.dc._msdcs.contoso.com
Resolve-DnsName -Server $dnsServer -Type SRV `
_ldap._tcp.Branch-01._sites.dc._msdcs.contoso.com
Resolve-DnsName -Server $dnsServer DC01.contoso.com
# Run these from an elevated administrative session with AD DS tools:
dcdiag /test:DNS /DnsRecordRegistration /s:DC01 /v
# Optional: requires approval to create/delete a temporary DNS test record.
dcdiag /test:DNS /DnsDynamicUpdate /s:DC01 /v
❯ Illustrative Output (Results Vary)
DC: \\DC01.contoso.com
Address: \\10.0.0.10
Dom Guid: 11111111-2222-3333-4444-555555555555
Dom Name: contoso.com
Forest Name: contoso.com
Dc Site Name: Branch-01
Our Site Name: Branch-01
The command completed successfully
Starting test: DNS
DC01 passed test DNS
In verbose output, check the individual record-registration results too.

04

Failure 1: Remove Stale or Missing SRV Targets

Failure Playbook

Typical signs: the SRV query returns a retired DC, a target has no A/AAAA record, a DC was renamed or demoted, or the site-specific answer is missing while the generic answer works. Query each DNS server that the client may use; AD-integrated zone replication can make answers differ temporarily or persistently.

On the affected DC, compare DNS with netlogon.dns and check Netlogon, DNS Server, and Directory Service events. Confirm that the DC points only to functioning AD DNS servers and that the zone is replicated. Correct the underlying stale record through the DNS owner and change process; do not delete every SRV record for a DC as a first step.

Terminal window
$dnsServers = '10.0.0.10', '10.0.0.11'
foreach ($server in $dnsServers) {
"--- DNS server $server ---"
Resolve-DnsName -Server $server -Type SRV `
_ldap._tcp.dc._msdcs.contoso.com -ErrorAction Continue
}
# On the DC, after DNS/zone health is corrected and the refresh is approved:
nltest /dsregdns
❯ Illustrative Output (Results Vary)
Compare DNS servers for missing or inconsistent targets.
Resolve every SRV target to its current address.
Use nltest /dsregdns on the affected DC to request Netlogon locator registration.

05

Failure 2: Repair Dynamic Update and Record Permissions

Failure Playbook

Typical signs: a DC’s registration test fails, Netlogon reports registration errors, or one DC cannot update records that another DC can. Check whether the zone is AD-integrated, whether secure dynamic updates are enabled, whether the DC can reach a DNS server hosting the zone, and whether an old record’s ACL/owner prevents the DC computer account from updating it. Check a separately delegated _msdcs zone as well as the parent domain zone.

Repair the specific zone setting, delegation, replication issue, or record ACL. Preserve secure updates. Do not enable nonsecure updates or grant broad write permissions as a shortcut. Once the rights and zone path are corrected, request a targeted Netlogon DNS registration refresh and rerun both DCDiag tests.

Terminal window
# From an authorized diagnostic host, target the affected DC.
# DnsDynamicUpdate creates/deletes a temporary record; obtain write approval:
dcdiag /test:DNS /DnsDynamicUpdate /s:DC01 /v
dcdiag /test:DNS /DnsRecordRegistration /s:DC01 /v
# On DC01, after the DNS owner/ACL issue is fixed and change-approved:
nltest /dsregdns
❯ Illustrative Output (Results Vary)
The affected DC can perform the secure update.
Its locator records appear on each DNS server hosting the zone.
DCDiag registration and dynamic-update checks pass.

06

Failure 3: Trace Firewall Blocks and Asymmetric Routing

Failure Playbook

Typical signs: SRV and host lookups succeed, but the client cannot discover a DC or authenticate; only one direction or one site fails; or a TCP test passes while locator discovery still times out. Verify UDP 389 for the LDAP ping and TCP/UDP 88 for Kerberos in both directions required by the session. Validate the forward and return routes, stateful inspection, VPN policy, host firewall, and network ACLs.

Test the exact client/DC pair and time window. Run the trace from an elevated PowerShell prompt and capture at the client and DC, or inspect firewall logs. A request leaving the client but not arriving at the DC points to the forward path; a request arriving with no response points to the DC/firewall/service; a response leaving but not reaching the client points to the return path. AD logon may also require DNS 53, SMB 445, RPC endpoint mapper 135 and dynamic RPC ports, time 123, or other ports depending on the operation, so validate the full Microsoft port matrix for the scenario.

Terminal window
$dc = 'DC01.contoso.com'
Test-NetConnection -ComputerName $dc -Port 389 -InformationLevel Detailed
Test-NetConnection -ComputerName $dc -Port 88 -InformationLevel Detailed
# On a Windows client, capture a bounded trace while reproducing the issue:
netsh trace start scenario=NetConnection capture=yes `
tracefile=C:\Windows\Temp\dc-locator.etl maxsize=256
# Reproduce one failed locator/authentication attempt, then stop:
netsh trace stop
❯ Illustrative Output (Results Vary)
TcpTestSucceeded : True
This confirms only a TCP handshake to the tested port.
Use the trace/firewall telemetry to verify UDP 389 and the return path.

07

Failure 4: Correct Multi-Homed DC Registration

Failure Playbook

Typical signs: a DC hostname resolves to a VPN, backup, isolated, or public-facing interface; clients receive multiple addresses and select an unreachable one; or a DC registers a NIC that should not serve domain clients. List every adapter, address, DNS server, suffix, and registration setting. Check whether DNS has A/AAAA records for each interface and whether those addresses are routable from the affected client site.

Decide which interfaces are intended for AD client traffic. Correct adapter DNS settings and the DNS registration checkbox/advanced settings for interfaces that should not publish records; remove only confirmed obsolete records after ownership and replication are understood. Keep DCs on the intended internal DNS service and verify each advertised address is reachable from its intended sites. Do not disable IPv6 broadly as a substitute for identifying the unwanted registration.

Terminal window
Get-NetIPConfiguration -All
Get-DnsClient | Format-Table InterfaceAlias, ConnectionSpecificSuffix, RegisterThisConnectionsAddress
Get-DnsClientServerAddress | Where-Object ServerAddresses
Resolve-DnsName DC01.contoso.com -Type A
Resolve-DnsName DC01.contoso.com -Type AAAA -ErrorAction SilentlyContinue
❯ Illustrative Output (Results Vary)
Each published address belongs to an intended, reachable DC interface.
Unintended interface addresses are no longer being registered.
Clients in each site resolve and reach an appropriate address.

08

Automate the Read-Only Client Checks

PowerShell Function

This function gathers the client site, a forced DC locator result, generic and site-specific locator SRV answers, and TCP probes to the explicitly supplied DC, or the located DC when none is supplied. It returns objects that can be saved or compared. By default it makes no DNS, firewall, registry, or service configuration changes. A forced lookup refreshes the local locator result. -RunDcDiag runs record-registration checks; the separate -TestDynamicUpdate switch opts into a temporary DNS write. Provide -DnsServer to query a specific AD DNS server; add -RunDcDiag and -DomainController only when you have the required administrative tools and permissions.

Terminal window
function Test-ADDcLocator {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string] $Domain,
[string] $DnsServer,
[string] $DomainController,
[switch] $RunDcDiag,
[switch] $TestDynamicUpdate
)
if ($TestDynamicUpdate -and -not $RunDcDiag) {
throw '-TestDynamicUpdate requires -RunDcDiag and approval for a temporary DNS write.'
}
$null = Get-Command nltest.exe, Resolve-DnsName, Test-NetConnection -ErrorAction Stop
if ($RunDcDiag) { $null = Get-Command dcdiag.exe -ErrorAction Stop }
$siteOutput = (& nltest.exe /dsgetsite 2>&1 | Out-String).Trim()
$siteExitCode = $LASTEXITCODE
$site = $null
if ($siteExitCode -eq 0) {
$site = ($siteOutput -split '\r?\n' |
Where-Object { $_.Trim() } | Select-Object -First 1)
}
if ($site) { $site = $site.Trim() }
$locatorOutput = (& nltest.exe "/dsgetdc:$Domain" /force 2>&1 | Out-String).Trim()
$locatorExitCode = $LASTEXITCODE
$selectedDC = $null
$dcMatch = [regex]::Match($locatorOutput, '(?im)^\s*DC:\s+\\\\(?<name>\S+)')
if ($locatorExitCode -eq 0 -and $dcMatch.Success) {
$selectedDC = $dcMatch.Groups['name'].Value.TrimEnd('.')
}
if (-not $DomainController) { $DomainController = $selectedDC }
$srvNames = @(
"_ldap._tcp.dc._msdcs.$Domain",
"_ldap._tcp.$Domain",
"_kerberos._tcp.dc._msdcs.$Domain",
"_ldap._tcp.pdc._msdcs.$Domain"
)
if ($site) {
$srvNames += "_ldap._tcp.$site._sites.dc._msdcs.$Domain"
}
$srvResults = foreach ($name in $srvNames) {
$query = @{ Name = $name; Type = 'SRV'; ErrorAction = 'Stop' }
if ($DnsServer) { $query.Server = $DnsServer }
try {
$answers = @(Resolve-DnsName @query | Where-Object Type -eq 'SRV')
if ($answers.Count -eq 0) { throw "No SRV answers returned for $name." }
$answers | Select-Object @{n='Query';e={$name}}, NameTarget, Port, Priority, Weight,
@{n='Error';e={$null}}
}
catch {
[pscustomobject]@{
Query = $name
NameTarget = $null
Port = $null
Priority = $null
Weight = $null
Error = $_.Exception.Message
}
}
}
$hostResults = @()
if ($DomainController) {
$hostQuery = @{ Name = $DomainController; ErrorAction = 'Stop' }
if ($DnsServer) { $hostQuery.Server = $DnsServer }
try {
$hostResults = @(Resolve-DnsName @hostQuery |
Where-Object Type -In 'A', 'AAAA' |
Select-Object Name, Type, IPAddress)
}
catch {
$hostResults = @([pscustomobject]@{
Name = $DomainController; Type = $null; IPAddress = $null
Error = $_.Exception.Message
})
}
}
$tcpResults = @()
if ($DomainController) {
$tcpResults = foreach ($port in 389, 88) {
$test = Test-NetConnection -ComputerName $DomainController -Port $port `
-InformationLevel Quiet -WarningAction SilentlyContinue
[pscustomobject]@{
ComputerName = $DomainController
Port = $port
TcpSucceeded = [bool]$test
}
}
}
$dcDiagResults = @()
if ($RunDcDiag) {
if (-not $DomainController) {
throw 'Specify -DomainController or successfully locate a DC before using -RunDcDiag.'
}
$testNames = @('DnsRecordRegistration')
if ($TestDynamicUpdate) { $testNames += 'DnsDynamicUpdate' }
foreach ($testName in $testNames) {
$diagnosticOutput = (& dcdiag.exe /test:DNS "/$testName" "/s:$DomainController" /v 2>&1 | Out-String).Trim()
$diagnosticExitCode = $LASTEXITCODE
$dcDiagResults += [pscustomobject]@{
Test = $testName
ExitCode = $diagnosticExitCode
Output = $diagnosticOutput
}
}
}
[pscustomobject]@{
ComputerName = $env:COMPUTERNAME
Domain = $Domain
DnsServer = $DnsServer
Site = $site
SiteCommand = $siteOutput
SiteExitCode = $siteExitCode
SelectedDC = $selectedDC
ProbeDC = $DomainController
LocatorCommand = $locatorOutput
LocatorExitCode = $locatorExitCode
SrvResults = @($srvResults)
HostResults = @($hostResults)
TcpResults = @($tcpResults)
DcDiagResults = @($dcDiagResults)
Interpretation = 'TCP probes do not validate UDP 389 LDAP pings or UDP 88 Kerberos. Review DNS errors, locator output, routes, and firewall telemetry together.'
}
}
# Run on the affected domain-joined client:
$report = Test-ADDcLocator -Domain 'contoso.com' -DnsServer '10.0.0.10'
$report | Format-List ComputerName, Domain, DnsServer, Site, SelectedDC
$report.SrvResults | Format-Table -AutoSize
$report.HostResults, $report.TcpResults | Format-Table -AutoSize
# Optional, with the AD DS tools and suitable permissions:
$report = Test-ADDcLocator -Domain 'contoso.com' `
-DnsServer '10.0.0.10' -DomainController 'DC01' -RunDcDiag
$report.DcDiagResults | Format-List
# Only after approval for temporary DNS record creation/deletion:
# Test-ADDcLocator -Domain contoso.com -DomainController DC01 -RunDcDiag -TestDynamicUpdate
❯ Illustrative Output (Results Vary)
ComputerName : CLIENT07
Domain : contoso.com
DnsServer : 10.0.0.10
Site : Branch-01
SelectedDC : DC01.contoso.com
Review SrvResults for missing/stale targets and HostResults for wrong addresses.
TcpResults is only a TCP connectivity hint; it is not a UDP locator test.

09

Validate Recovery and Preserve the Evidence

Closeout

After the approved repair, query the same SRV names against the same DNS servers, resolve each advertised host, run nltest /dsgetsite and nltest /dsgetdc:<Domain> /force from the affected client, and rerun targeted DCDiag tests on the DC where registration failed. Confirm the original sign-in or application operation works. Record which DNS server answered, the returned DC and site, the firewall path tested, and the change made.

If the fault remains, retain a bounded network trace and compare the query, SRV response, CLDAP request, and response at both endpoints. Avoid broad cache flushing or record deletion until you know which layer is returning the wrong data.

Terminal window
Resolve-DnsName -Server 10.0.0.10 -Type SRV `
_ldap._tcp.dc._msdcs.contoso.com
nltest /dsgetsite
nltest /dsgetdc:contoso.com /force
dcdiag /test:DNS /DnsRecordRegistration /s:DC01 /v
❯ Illustrative Output (Results Vary)
Locator SRV targets are current and resolve to intended addresses.
The client site and selected DC match the expected topology.
The original workload succeeds, and the change record includes evidence.

Comments