If the title of this blog hasn’t already put you off, you’re probably interested in the interaction between Microsoft DNS and DHCP services. Specifically, you should understand how Microsoft DHCP servers can be configured to dynamically register A and PTR records in DNS on behalf of their clients.

The default behavior of a Microsoft DHCP server is to only perform dynamic DNS registration on behalf of a client, if the client requests. The default behavior of a relatively modern Microsoft client (XP or higher) is to perform the dynamic registration of their A-record themselves, and to allow the DHCP server to perform the dynamic registration of their PTR-record.

Things become slightly more complex when you use secure-only dynamic DNS, and I hope you do you use secure-only dynamic DNS. Unfortunately, secure-only is not the default configuration for a DNS zone, so you should verify. If DCs run DHCP and perform dynamic DNS registration on behalf of their clients, the potential problem is that DCs are over-privileged with respect to secure dynamic DNS. DCs could, theoretically, hijack any DNS record on-behalf of their clients. Thus, you should use alternate credentials for dynamic DNS registration on the DHCP server.

If you’re really into this stuff, fellow PFE Karam Masri has written a nice, deep in the weeds blog about how DHCP and secure dynamic DNS registrations work (or don’t always work) on Domain Controllers.

At the end of the day, there is some very simple guidance for running DHCP on Domain Controllers – configure DHCP with alternate credentials for dynamic DNS registration. How? Simply use the DHCP management tool, open the DHCP server properties (or IPv4 properties in Windows 2008 R2), then follow three simple steps.

image

Or if you’re a command-line admin, you can use netsh:

Netsh.exe dhcp server \\servername set dnscredentials username domainname password

Where servername is the name of the DHCP server, username is the name of the user account, domainame is the domain where the user account resides and password is the password associated with the account.

If you just want to see the credentials already configured for a dhcp server:

Netsh.exe dhcp server \\servername show dnscredentials

 

Some Basic Best Practices

  • If you’re running dynamic DNS, be sure your zones are allowing “Secure Only” dynamic updates. If you are allowing non-secure and secure updates, alternate credentials are irrelevant and you’ve got bigger security concerns.
  • When you provision a domain account for alternate credentials, DO NOT grant the account any special privileges. You’ve already got too many service accounts that are over-privileged (and don’t think I don’t know it). Don’t add to the problem.
  • Even if you’re running DHCP on member servers (not Domain Controllers), you may want to consider alternate credentials for dynamic DNS registration. This makes for a nice transition when you’ve got to replace your existing DHCP server with a new one. If you use the same account on the old and new DHCP servers, ownership of the DNS records will not have to change.

Didn’t You Mention Something About PowerShell?

The real point of this blog was to help you check the alternate credentials for Dynamic DNS, across all of your domain controllers. Manually checking credentials on more than 2 DCs can be a real pain. In fact, I often run into customers who have dozens, if not hundreds of Domain Controllers running DHCP.

 

Enter the PowerShell Script

If you’ve seen some of my other scripts, some of the code in this new script may look familiar. I basically do the following:

1. Discover DCs (the old fashion way - without using the AD cmdlets, because they require a 2008 R2 DC):

##################################
Function EnumerateDCs
{
     $arrServers =@()
     $rootdse=new-object directoryservices.directoryentry("LDAP://rootdse")
     $Configpath=$rootdse.configurationNamingContext
     $adsientry=new-object directoryservices.directoryentry(LDAP://cn=Sites,$Configpath)
     $adsisearcher=new-object directoryservices.directorysearcher($adsientry)
     $adsisearcher.pagesize=1000
     $adsisearcher.searchscope="subtree"
     $strfilter="(ObjectClass=Server)"
     $adsisearcher.filter=$strfilter
     $colAttributeList = "cn","dNSHostName","ServerReference","distinguishedname"
     Foreach ($c in $colAttributeList)
     {
          [void]$adsiSearcher.PropertiesToLoad.Add($c)
     }
     $objServers=$adsisearcher.findall()
     ForEach ($objServer in $objServers)
     {
          $serverDN = $objServer.properties.item("distinguishedname")
          $ntdsDN = "CN=NTDS Settings,$serverDN"
          if ([adsi]::Exists(LDAP://$ntdsDN))
          {
               $serverdNSHostname = $objServer.properties.item("dNSHostname")
               $arrServers += "$serverDNSHostname"
          }
          $serverdNSHostname=""
     }
     $arrServers
}
##################################

2. Walk through the DCs and use WMI to discover whether or not they are running DHCP:

##################################
Function isRunningDHCP
{
     Param($computer)
     $DHCP = "FALSE"
     $Query = "SELECT Name, Status FROM Win32_Service WHERE (Name = 'DHCPServer') AND  (State = 'Running')"
     Try
     {
          $DHCPRunning = Get-WmiObject -Query $Query -ComputerName $Computer -EA Stop
          If ($DHCPRunning){$DHCP = "TRUE"}
     }
     Catch {$DHCP = "FALSE"}
     Finally {$DHCP}
}|
###################################

3. Use Netsh and some string manipulation to determine if DHCP is using alternate credentials for DDNS:

###################################
Function GetAltCreds
{
     Param($computer)
     $AltCreds = $Null
     $Query = Netsh dhcp server "\\$computer" show dnscredentials
     $username = $Query[2].substring(14)
     $domain = $Query[3].substring(14)
     If ($username.length -eq 0){$AltCreds = "NULL"}
     Else {$AltCreds = "$domain\$username"}
     $AltCreds
}
##################################

4. Put it all together and report back the findings. Both on-screen and logged into a CSV file.

image

image

 

Now You Try

Simply download and run the attached script (DHCPDNSCreds.ps1). It requires administrative privileges against your DCs. It will discover all DCs in your forest, and report which are running DHCP and what alternate credentials (if any) are being used. Simply analyze the output (either on-screen, or in the DHCPDynamicDNS.csv file. Look for DCs where Running DHCP=TRUE and AltCreds is blank.

I hope you enjoy the script, and come back for more PowerShell goodness in the future.

Doug Symalla

Update: 16August2012.  Some users reported issues with the script when NetSH DHCP commands are not available.  In that case, the script will execute, but bleed red everywhere as it errors.  I added some error control for the case when NetSH DHCP commands are not available.  In this case, you should install the DHCP remote server admin tools (Windows Server 2008 R2) before running the script.  The updated script is attached.

Update (3.April.2013):  To centralize the storage of all AskPFEPlat scripts, we are now storing them on the TechNet Script Center Repository.  This specific script can be found at the following location:

http://gallery.technet.microsoft.com/scriptcenter/DHCP-Server-View-or-Set-688295bc