Lerch Web Wiki

Random, erratic, no responsibility is taken for the correctness of this information

User Tools

Site Tools


powershell:ad:test-dnsregistration

Test-DNSRegistration

Hi, it’s me back again with a little PowerShell script function that may help you verify if your DCs have registered all necessary DNS records correctly.

One of the main reasons for problems in Active Directory is always DNS. As Active Directory is relying heavily on DNS for name resolution and service advertisement it is essential your DNS is working correctly and all your DCs have registered their appropriate DNS records.

A DC needs to register a couple of records in DNS. First of all there is the A-Record that registers the name and the IP-Address for your DC and another A-Record that registers the name of your domain and the IP-Address of the DC. Secondly there is a CName (or Aliase) called the Glue-Record. This ‘glues’ the GUID of your DC to its FQDN. And last but not least there are loads of service records which advertise the services of your DC stating which service is offered what priority it has and what weight and which port the service is listening on. Which service records need to be registered depends on your infrastructure setup, your sites, if your DC is a Global Catalogue Server or the PDC Emulator. Each of these records is registered with a TTL of (default) 600 seconds.

So how do you know which records need to be registered so you can check if everything is fine? Well you’re lucky, you don’t need to know because your DC knows and stores the information for you in a file. This file is called netlogon.dns and it resides in the Windows\System32\config directory on your DC.

Here is a sample of one

  • _ldap._tcp.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • _ldap._tcp.pdc._msdcs.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • _ldap._tcp.69e4df56-8b16-4092-9652-4e5ff42161f10.domains._msdcs.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • 9348c15a-dd27-4ff7-6761-68452bfce2cb._msdcs.contoso.com. 600 IN CNAME MYDC1.contoso.com.
  • _ldap._tcp.dc._msdcs.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • _ldap._tcp.gc._msdcs.contoso.com. 600 IN SRV 0 100 3268 MYDC1.contoso.com.
  • _kerberos._tcp.dc._msdcs.contoso.com. 600 IN SRV 0 100 88 MYDC1.contoso.com.
  • _kerberos._tcp.contoso.com. 600 IN SRV 0 100 88 MYDC1.contoso.com.
  • _gc._tcp.contoso.com. 600 IN SRV 0 100 3268 MYDC1.contoso.com.
  • _kerberos._udp.contoso.com. 600 IN SRV 0 100 88 MYDC1.contoso.com.
  • _kpasswd._tcp.contoso.com. 600 IN SRV 0 100 464 MYDC1.contoso.com.
  • _kpasswd._udp.contoso.com. 600 IN SRV 0 100 464 MYDC1.contoso.com.
  • _ldap._tcp.DomainDnsZones.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • _ldap._tcp.ForestDnsZones.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.
  • _ldap._tcp.DefaultFirstSiteName._sites.contoso.com. 600 IN SRV 0 100 389 MYDC1.contoso.com.

… and so on

As you see there are a lot of records that a DC needs to register on your DNS Servers. Checking them all is quite a challenge if you have a lot of DCs so I came up with the following little function to help you automate this task.

Test-DNSRegistration.ps1
function Test-DNSRegistration {
    [CmdletBinding(DefaultParametersetName="LocalCheck")] 
	param(
        [Parameter(ParametersetName="ProvidedList", Mandatory=$true)]
        [Parameter(ParametersetName="RemoteCheck", Mandatory=$true, ValueFromPipeline=$true)]
        [System.String[]]
        $Server,
		[Parameter(ParametersetName="LocalCheck")]
		[Parameter(ParametersetName="RemoteCheck")]
		[Parameter(ParametersetName="ProvidedList")]
        [System.String]
        $DNSServerAdress,
		[Parameter(ParametersetName="ProvidedList", Mandatory=$true)]
		[ValidateNotNullOrEmpty()]
		[System.String[]]
		$DNSRecordList
)
Begin {    
    switch ($PSCmdlet.ParameterSetName){
        "LocalCheck" { 
            if (Test-Path $env:SystemRoot\System32\config\netlogon.dns -PathType Leaf){
                $DNSRecordList = Get-Content $env:SystemRoot\System32\config\netlogon.dns
                $Server = $env:COMPUTERNAME
            }
            else{
                Write-Output ("Could not read {0}`nPlease verify the existence of the netlogon.dns File.`nIs the local machine really a domain controller?" -f "$env:SystemRoot\System32\config\netlogon.dns" )
            }
        }
        "RemoteCheck" {
            #$DNSRecordList = @()
            foreach ($SingleServer in $Server){
                $NetLogonDNSPath = '\\{0}\admin$\\System32\config\netlogon.dns' -f $SingleServer
                if (Test-Path $NetLogonDNSPath -PathType Leaf){
                    $DNSRecordList += Get-Content $NetLogonDNSPath
                }
                else{
                    Write-Output ("Could not read {0}`nPlease verify the existence of the netlogon.dns File.`nIs the target machine really a domain controller?" -f $NetLogonDNSPath)
                }
            }
        }
    }
    if($DNSServerAdress -eq ""){
        $DNSServerAdress = ((Get-DnsClientServerAddress -AddressFamily IPv4) | Where-Object {$_.ServerAddresses})[0].ServerAddresses[0]
    }
    $ServiceRecordList = @()
}
Process {
	foreach ($DNSEntry in $DNSRecordList){
		$Entry = $DNSEntry -split " "
		$DNSName = $Entry[0]
        $DNSTTL = $Entry[1]
		$DNSType = $Entry[3]
        if ($DNSType -eq "SRV"){
            $SRVPriority = $Entry[4]
            $SRVWeight = $Entry[5]
            $SRVPort = $Entry[6]
        }
        $ServerInQuestion = ($Entry[-1]).TrimEnd(".")
        $ServiceRecord = New-Object System.Object | Select-Object SourceServer,DNSRecord,DNSRecordType,IsRegistered,IsCorrect,DNSServer
        $ServiceRecord.SourceServer = $ServerInQuestion
        $ServiceRecord.DNSRecord = $DNSName
        $ServiceRecord.DNSRecordType = $DNSType
        $ServiceRecord.IsRegistered = $false
        $ServiceRecord.IsCorrect = $false
        $ServiceRecord.DNSServer = $DNSServerAdress
        $nslResults = Resolve-DnsName -Name $DNSName -Type $DNSType -DnsOnly -Server $DNSServerAdress -ErrorAction SilentlyContinue
		switch ($DNSType) {
 
            "SRV" {
                foreach ($nslResult in $nslResults){
                    if ($nslResult.NameTarget -eq $ServerInQuestion){
                        $ServiceRecord.IsRegistered = $true
                        if ($nslResult.TTL -eq $DNSTTL -and 
                            $nslResult.Priority -eq $SRVPriority -and 
                            $nslResult.Weight -eq $SRVWeight -and 
                            $nslResult.Port -eq $SRVPort){
                            $ServiceRecord.IsCorrect = $true
                        }
                        break
                    }
              }
 
			}
 
			"A" {
				foreach ($nslResult in $nslResults){
                    if ($nslResult.IP4Address -eq $ServerInQuestion){
                        $ServiceRecord.IsRegistered = $true
                        if ($nslResult.TTL -eq $DNSTTL){
                            $ServiceRecord.IsCorrect = $true
                        }
                        break
                    }
              }
			}
 
			"CNAME" {
				foreach ($nslResult in $nslResults){
                    if ($nslResult.NameHost -eq $ServerInQuestion){
                        $ServiceRecord.IsRegistered = $true
                        if ($nslResult.TTL -eq $DNSTTL){
                            $ServiceRecord.IsCorrect = $true
                        }
                        break
                    }
              }
			}
 
			Default {
				break
			}
		}
        $ServiceRecordList += $ServiceRecord
	}
}
End {
    $ServiceRecordList | Sort-Object DNSRecordType, DNSRecord
}
}

The function reads the netlogon.dns file from the local or remote host and checks each record against a DNS server. If you provide no DNS server to check against, the function uses the first DNS server of the local machine.

The function can also take a list of records to check as string array using the -ProvidedList parameter.

What you need is PowerShell 4.0 with the DNSClient module as I use the Resolve-DnsName and Get-DnsClientServerAddress commandlets.

Till next time…

powershell/ad/test-dnsregistration.txt · Last modified: 2017/02/27 09:18 by marcus