24 October, 2012

Cleanup DNS SRV records - Active Directory

As I mentioned in the previous post, when you perform DC metadata cleanup at 2 AM (after working all day with a hangover from the previous night) in a large IT environment, you don't want to walk through all SRV records and "folders" on the dnsmgmt.msc console and hit delete and then think about it 3 times, sweat a bit before clicking on Yes for the "Are you sure?" question.

What you need is a semi-automated way which creates the dnscmd commands for you to review on the fly and run - I wouldn't just run the dnscmd command blindly even if I'm about to fall asleep and my eyes are like arrowslits. The reason for this paranoia is that each SRV record has a so called RRData (Resource Record Data) which contains the DC name, weight, priority. If you specify only the SRV record for dnscmd and you don't specify the RRData, it wipes out the whole SRV record for ALL DCs not just for the one you wanted to clean up. Believe me, I've been there... or test it in a QA environment, you'll see.

Red circle shows the RRData, without it, dnsmcd will wipe out the record for ALL DCs!

Although restoring SRV records is fairly easy in a small environment: just restart the NETLOGON service on all DCs and they re-register all of them. However, if you have a global environment, with 100+ DCs in different parts of the world, it's a bit more difficult and can take several hours... and your weekend has gone and it's Monday again...

When you Think Big - think about large IT infrastructure with multiple 1000s of servers spread across 100+ locations - just take into account:
  • There's no such thing that "out of business hours" - when it's at night in EU for you, it's business hours in America. If it's Sunday for you, doesn't matter, people may work still in different part of the world 24x7.
  • You have to go through all 100+ DCs probably with a quick script but not just to restart the NETLOGON service, you will have to perform checkouts on all of the DCs to make sure all dependent services are running and are functional.
  • If you want to recover in a multi-site environment, it can take several hours to just replicate the SRV records you registered to all DCs/DNS servers.
  • Restarting the netlogon service may break some applications during business hours
  • etc.


Essentially, you want to make sure you delete what needs to be deleted and only that. Here is the main part of the script (without proper error handling, parameter handling, logging...etc.) which composes the dnscmd commands for deleting SRV records of a given domain controller:

$dcname = "c3poDC1"
$domain = "tatooine.com"
$dnsServer = "MyDNSServer"
$dnscommands = @()

# list all srv records containing the given DC name
$listSRVs = gwmi -Namespace root/microsoftdns -q "select * from MicrosoftDNS_SRvtype" -ComputerName $dnsServer | ?{($_.domainname -imatch $dcname) -or ($_.srvdomainname -imatch $dcname)}

#generate dnscmd syntax for each
$listSRVs | %{
   $tmpstr = $srvrecordname = $null

  
# if the textrepresentation contains our DC name,
   # then we can proceed
   if($_.textrepresentation -imatch $dcname){

     
# the srvrecord name is in the ownername property,
      # we need to delete the domain FQDN from it
      $srvrecordname = $_.ownername -replace $domain, ""
      # delete the domain FQDN from the SRV record name
      # and delete the text 'IN '
      $srvrecordNameandData = $_.textrepresentation -replace "((?<!.$domain.*).$domain)|IN ",""

      # store the command in a variable and in an array
      $tmpstr = "dnscmd $dnsServer /recorddelete $domain $srvrecordNameandData "
      $dnscommands += $tmpstr
   }
   else{
      write-host -ForegroundColor 'red' "Could not enumerate RRData from $srvrecordname"
   }
}
$dnscommands

Explanation:
  • The script enumerates all SRV records of a given DC
  • Picks up the 'textrepresentation' of each record
  • Creates the syntax of the dnscmd command for deleting that particular record

Clipboard friendly code:


 $dcname = "c3poDC1"  
 $domain = "tatooine.com"  
 $dnsServer = "MyDNSServer"  
 $dnscommands = @()  
   
 # list all srv records containing the given DC name  
 $listSRVs = gwmi -Namespace root/microsoftdns -q "select * from MicrosoftDNS_SRvtype" -ComputerName $dnsServer | ?{($_.domainname -imatch $dcname) -or ($_.srvdomainname -imatch $dcname)}   
 
 #generate dnscmd syntax for each  
 $listSRVs | %{  
      $tmpstr = $srvrecordname = $null  

      # if the textrepresentation contains our DC name, then we can proceed  
      if($_.textrepresentation -imatch $dcname){  

           # the srvrecord name is in the ownername property, we need to delete the domain FQDN from it  
           $srvrecordname = $_.ownername -replace $domain, ""  
  
           # delete the domain FQDN from the SRV record name and delete the text IN  
           $srvrecordNameandData = $_.textrepresentation -replace "((?<!.$domain.*).$domain)|IN ",""  

           # store the command in a variable and in an array  
           $tmpstr = "dnscmd $dnsServer /recorddelete $domain $srvrecordNameandData "  
           $dnscommands += $tmpstr  
      }  
      else{  
           write-host -ForegroundColor 'red' "Could not enumerate RRData from $srvrecordname"  
      }  
 }  
 $dnscommands  

May The Force...

3 comments:

  1. thanks for posting this script it is life saver
    how ever i get this error whn i try to delet the srv record

    dnscmd co1ylpads002 /recorddelete YLOPPE.MSOAAE.targ.NET _kerberos._tcp.CO1._sites.dc._msdcs SRV 0 100 88 co1ylpadds004.yloppe.msoaae.targ.net.

    Command failed: DNS_ERROR_NAME_DOES_NOT_EXIST 9714 0x25F2

    ReplyDelete
    Replies
    1. This error mean the record you are trying to delete is not present in the zone. Check it with either nslookup or with dnsmgmt.msc to see if it's there.

      Delete
  2. this is because script incorrectly forms commands for records under _msdcs.FQDN zone adding _msdcs to record. i.e. in this case records is in _msdcs.YLOPPE.MSOAAE.targ.NET zone and correct command is:
    dnscmd co1ylpads002 /recorddelete _msdcs.YLOPPE.MSOAAE.targ.NET _kerberos._tcp.CO1._sites.dc SRV 0 100 88 co1ylpadds004.yloppe.msoaae.targ.net

    if deleting hundreds of records nice to add /f too else you are asked Yes/No for each record.

    Anyway good script, saved me tons of time. Thanks.

    ReplyDelete