Isolate a DC - Part 8: Metadata cleanup all other DCs

This is Part 8 of a series on Active Directory Forest recovery; make your DC lonely.

Metadata Cleanup all other DCs

Its not recovered until all the DCs are alive, but first, you have to kill them off with Metadata cleanup. Unfortunately the powershell commands won’t just delete a Domain Controller for you. So its up to NTDSUTIL automation to do the work again. You will need to run these in the Console host, not the PowerShell ISE.

In this step we also purge DNS records created by those DCs and try to eliminate as many lingering bits of fluff as possible.

function MetadataCleanupAllOtherDCsInCurrentDomain{
 [CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'High')]param()
    $domainObj = get-addomain
    $domain = $domainObj.dnsroot  
    $domaindn = $domainObj.distinguishedName 
    Write-Warning "Metadata will be removed for all domain controllers except $(&hostname) in $domain, performing this activity in a production environment will be catastrophic."
    if ($pscmdlet.ShouldProcess($domain.name)){ 
        get-addomaincontroller -filter * | ?{$_.hostname -notmatch $(&hostname)} |  %{  
            $domains = ntdsutil "metadata cleanup" "con" "con to dom $domain" q "sel op ta" "list do"  q q q
            $DomainNum = "FailedToFindDomain"; switch -regex ($domains){ "^(\d+) - $domaindn"{$DomainNum = $matches[1];break; }  }             
            $sites =  ntdsutil "metadata cleanup" "con" "con to dom $domain" q "sel op ta" "list do" "select do $DomainNum" "list sites" q q q  
            $sername = $_.name  
            $sitename = $_.site  
            $sitenum = "FailedTofindSite"; switch -regex ($sites){    "^(\d+) - .+$sitename"{$sitenum = $matches[1];break; }  }  
            $servers = ntdsutil "metadata cleanup" "con" "con to dom $domain" q "sel op ta" "list do" "select do $DomainNum" "list sites" "sel site $sitenum" "list ser for dom in site" q q q  
            $servnum = "FailedToFindServer"; switch -regex ($servers){"^(\d+).+$sername"{ $servnum = $matches[1];break; }  }   
            write-verbose "Executing cleanup metadata $sername from $sitename : ntdsutil `"metadata cleanup`" `"con`" `"con to dom $domain`" q `"sel op ta`" `"list do`" `"select do $DomainNum`" `"list sites`" `"sel site $sitenum`" `"list ser for dom in site`" `"sel ser $servnum`" q `"rem sel server`" q q"  
            $result = ntdsutil "metadata cleanup" "con" "con to dom $domain" q "sel op ta" "list do" "select do $DomainNum" "list sites" "sel site $sitenum" "list ser for dom in site" "sel ser $servnum" q "rem sel server" q q
            if ($result -match "removed from server") {  
                Write-verbose ($_.name + " Metadata cleanup complete")
            }  
        }  
        Write-Verbose "Removing all SRV records, Domain A,AAAA and NS records"      
        $DNSDOmain = $domain
        Get-DnsServerResourceRecord -ZoneName $DNSDOmain -Node '@' -RRType A | Remove-DnsServerResourceRecord -ZoneName $DNSDOmain -force
        Get-DnsServerResourceRecord -ZoneName $DNSDOmain -node '@' -RRType AAAA | Remove-DnsServerResourceRecord -ZoneName $DNSDOmain -force
        Get-DnsServerResourceRecord -ZoneName $DNSDOmain -node '@' -RRType NS | Remove-DnsServerResourceRecord -ZoneName $DNSDOmain -force
        Get-DnsServerResourceRecord -ZoneName $DNSDOmain -node '_kpasswd._udp' -RRType SRV | Remove-DnsServerResourceRecord -ZoneName $DNSDOmain -force
        Get-DnsServerResourceRecord -ZoneName $DNSDOmain -node '_kpasswd._tcp' -RRType SRV | Remove-DnsServerResourceRecord -ZoneName $DNSDOmain -force
        try {$MSDCSRecords = Get-DnsServerResourceRecord -ZoneName _msdcs.$DNSDOmain -RRType SRV; $DNSDomain = "_msdcs.$DNSDOmain" } 
        catch {$MSDCSRecords = Get-DnsServerResourceRecord -ZoneName $DNSDOmain -RRType SRV | ?{$_.hostname -match '_msdcs'}}
        $MSDCSRecords | ?{$_.hostname -match '^_(kerberos|ldap)'} | remove-dnsserverresourcerecord -zonename $DnsDOmain -force
        #Restart DNS and netlogon to recreate the records for this Domain Controller
        Write-Verbose "Restarting DNS and Netlogon to recreate domain records from this server"   
        restart-service dns
        restart-service netlogon
    }
}

MetadataCleanupAllOtherDCsInCurrentDomain

All the other parts of this series are available here