Manage reverse DNS zones with Powershell
Manage reverse DNS zones with Powershell
Manage reverse DNS zones with Powershell

The script is a complete tool that will perform the following tasks:

  • list the A records in the domain name defined in the variable $dnsDomainName
  • for each record, check if the reverse zone exist. If not, ask to create the reverse zone (choice between domain and forest-wide replication scope)
  • if the A record does not have a valid reverse record:
    • check if the A record is reachable (ping ok/nok)
    • if the A record is available (ping ok), create the PTR record in the correct zone
    • if the A record is not available (ping nok), the PTR record creation is skipped

The script has been tested successfully in a Windows 2012R2 infrastructure (Active Directory + DNS).

$dnsServer = "mydc01.root.local"
$dnsDomainName = "root.local"
  
$record_A_list = Get-DnsServerResourceRecord -ComputerName $dnsServer -ZoneName $dnsDomainName -RRType A | ? {$_.Hostname -notmatch "@|DomainDnsZones|ForestDnsZones"}
$reverse_zone_list = (Get-DnsServerZone -ComputerName $dnsServer | ? { $_.IsReverseLookupZone -eq $true -and $_.IsAutoCreated -eq $false}).ZoneName
if (-not ($reverse_zone_list)) {
    $record_R_list = ""
    Write-host "No Reverse DNS zone has been found. Analyzing host (A) records to create them..." -ForegroundColor Yellow

    $ReverseZonesToCreate = ($record_A_list.RecordData.IPv4Address.IPAddressToString | % { $_.split(".")[0..2] -join "."}) | select -Unique

    $ReverseZonesToCreate | % {
        "The reverse DNS zone for the NetworkID $_/24 need to be created. Choose the replication scope for this new zone :"
        $netid = "$_/24"    
        $coll = @()

        $b = New-Object System.Management.Automation.Host.ChoiceDescription "&Domain"
        $b.HelpMessage = "Domain-wide replication scope"
        $b | Add-Member -MemberType ScriptMethod -Name Invoke -Value {Add-DnsServerPrimaryZone -NetworkId $netid -ReplicationScope Domain} -force
        $coll+=$b
 
        $c = New-Object System.Management.Automation.Host.ChoiceDescription "&Forest"
        $c.HelpMessage = "Forest-wide replication scope"
        $c | Add-Member -MemberType ScriptMethod -Name Invoke -Value {Add-DnsServerPrimaryZone -NetworkId $netid -ReplicationScope Forest} -force
        $coll+=$c
 
        $q = New-Object System.Management.Automation.Host.ChoiceDescription "&Quit"
        $q.HelpMessage = "Skip the Reverse DNS zone creation"
        $q | Add-Member -MemberType ScriptMethod -Name Invoke -Value {Write-Host "The reverse DNS zone creation for the NetworkID $netid has been skipped" -ForegroundColor DarkGray } -force
        $coll+=$q
        $result = $host.ui.PromptForChoice($title, $message, $coll, 2) 
        $coll[$result].invoke() 
    }
}

$record_R_list = @()
$reverse_zone_list = (Get-DnsServerZone -ComputerName $dnsServer | ? { $_.IsReverseLookupZone -eq $true -and $_.IsAutoCreated -eq $false}).ZoneName
$reverse_zone_list | % {
    try {
        $record_R_list += Get-DnsServerResourceRecord -ComputerName $dnsServer -ZoneName $_ -RRType PTR | ? {$_.Hostname -notmatch "@|DomainDnsZones|ForestDnsZones"}    
    }
    catch {
        "No Reverse DNS zone found. Skipping..."
    }
}

$record_A_list | % {
    $hostname = $_.HostName
    $ipaddress = $_.RecordData.IPv4Address.IPAddressToString
                if ($record_R_list.recordData.PtrDomainName -notcontains "$hostname.$dnsDomainName.") {
                                Write-Host -NoNewline "The following host does not have a valid reverse record in DNS : $hostname.$dnsDomainName."
        
                                $PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$hostname'" | Select-Object StatusCode
                                If ($PingStatus.StatusCode -eq 0){
                                                Write-Host " (online)" -Fore "Green"
                                                $arr = $ipaddress.split(".")
                                                [array]::Reverse($arr)
                                                $reverse_ip = ($arr -join '.') + ".in-addr.arpa"
 
                                                #detect the correct dns reverse lookup zone
                                                $arr_rvr = $reverse_ip.Split(".")
                                                $arr_rvr1 = $arr_rvr[1] + "." + $arr_rvr[2] + "." + $arr_rvr[3] + ".in-addr.arpa"
                                                $arr_rvr2 = $arr_rvr[2] + "." + $arr_rvr[3] + ".in-addr.arpa"
                                                $arr_rvr3 = $arr_rvr[3] + ".in-addr.arpa"

            switch ($reverse_zone_list) {
                {$_ -contains $arr_rvr1} {
                                                                    Write-Host $arr_rvr1 "zone exists in DNS reverse lookup zones"
                                                                    Write-Host "Creating PTR record : $reverse_ip ($hostname.$dnsDomainName.)" -foreground green
                    Add-DnsServerResourceRecordPtr -ComputerName $dnsServer -Name ($arr[0] -join ".")  -ZoneName $arr_rvr1 -PtrDomainName "$hostname.$dnsDomainName"
                                                }
                {$_ -contains $arr_rvr2} {
                                                                    Write-Host $arr_rvr2 "zone exists in DNS reverse lookup zones"
                                                                    Write-Host "Creating PTR record : $reverse_ip ($hostname.$dnsDomainName.)" -foreground green
                    Add-DnsServerResourceRecordPtr -ComputerName $dnsServer -Name ($arr[0..1] -join ".")  -ZoneName $arr_rvr2 -PtrDomainName "$hostname.$dnsDomainName"
                                                }
                {$_ -contains $arr_rvr3} {
                                                                    Write-Host $arr_rvr3 "zone exists in DNS reverse lookup zones"
                                                                    Write-Host "Creating PTR record : $reverse_ip ($hostname.$dnsDomainName.)" -foreground green
                    Add-DnsServerResourceRecordPtr -ComputerName $dnsServer -Name ($arr[0..2] -join ".")  -ZoneName $arr_rvr3 -PtrDomainName "$hostname.$dnsDomainName"
                                                }
            }
                                }
                                Else {
                                                Write-Host " (offline: PTR record creation skipped)"  -Fore "Red"
                                }
                }
    else {
        write-host -foreground DarkGray "$hostname : PTR record already exists"
    }
}

My Powershell script categories

Manage reverse DNS zones with Powershell

One thought on “Manage reverse DNS zones with Powershell

  • May 10, 2021 at 1:25 pm
    Permalink

    Hi Niko,

    Thanks for sharing this great script, this is exactly I was looking for.

    My only problem is that after the script goes through the PTR records and finds the one that already exists, it’s like starting over and then adds another domain name to it.
    So which was originally “something.xxx.lan” – “PTR record already exists”, next time it says “Creating PTR record” and it changes to “something.xxx.lan.xxx.lan”

    Can you please help me on this?

    Thank you in advance.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *