14.3 Server Classes

Nearly 50 different settings can be configured on a Microsoft DNS Server. They range from scavenging and logging settings to settings that customize the name server's behavior, such as how zone transfers are sent to secondaries and whether to round-robin responses that include multiple A records. A name server is represented by an instance of the MicrosoftDNS_Server class. Table 14-1[2] contains all the property methods defined in the MicrosoftDNS_Server class.

[2] For the latest list of supported properties and methods for any of the DNS Provider classes, check out the MSDN documentation: http://msdn.microsoft.com/library/en-us/dns/dns/microsoftdns_server.asp. If that link becomes out of date, you should be able to find the documentation by going to http://msdn.microsoft.com/ and searching on MicrosoftDNS_Server.

Table 14-1. MicrosoftDNS_Server class properties

Property name

Property description

AddressAnswerLimit

Maximum number of records to return for address requests (i.e., A records). This value can be a number between 5 and 28. The default value is 0, which does not limit the number of records that can be returned.

AllowUpdate

Determines whether dynamic updates are allowed. The value of this property can be any sum of the following values:


0

No restrictions.


1

Dynamic updates to SOA records are not allowed.


2

Dynamic updates to NS records at the apex of the zone are not allowed.


4

Dynamic updates to NS records of delegated zones are not allowed.

The default value is 0.

AutoCacheUpdate

Boolean that indicates whether the name server dynamically attempts to update its root hints (also known as cache) file. The default value is TRUE, which means the server auto-updates its root hints.

AutoConfigFileZones

Indicates whether the name server attempts to automatically update any zone it knows about that has an A, NS, or SOA record when the name of the server changes. The value for this property can be one of the following:


0

None


1

Only zones that have name servers that allow dynamic updates


2

Only zones that have name servers that do not allow dynamic updates


4

All zones

The default value is 1.

BindSecondaries

Boolean that if TRUE causes the name server to send zone transfers in a less efficient (but more interoperable) format to non-Microsoft DNS Servers. The default value is TRUE.

BootMethod

Determines where the server reads its zone information. The value for this property can be one of the following:


1

Boot from the zone file.


2

Boot from the Registry.


3

Boot from Active Directory and the Registry.

The default value is 3.

DefaultAgingState

Boolean that indicates whether aging is enabled for AD-integrated zones. The default value is FALSE (not enabled).

DefaultNoRefreshInterval

For AD-integrated zones, the default no-refresh interval in hours. The default value is 168 (one week).

DefaultRefreshInterval

For AD-integrated zones, the default refresh interval in hours. The default value is 168 (one week).

DisableAutoReverseZones

Boolean that determines whether the name server automatically creates reverse zones for 0.in-addr.arpa, 127.in-addr.arpa, and 255.in-addr.arpa. The default value is FALSE (the reverse zones are created).

DisjointNets

Boolean that indicates whether the default port binding for a socket used to send queries to remote name servers can be overridden.

DsAvailable

Boolean that indicates whether Active Directory is available on the server.

DsPollingInterval

For AD-integrated zones, the interval in minutes to poll Active Directory for updates. The default value is 5 minutes.

DsTombstoneInterval

For AD-integrated zones, the length of time in seconds for which tombstoned (i.e., deleted) records should remain in Active Directory. In 99.99% of deployments the default of 604800 (one week) should not need changing.

EdnsCacheTimeout

Length of time, in seconds, that the Extension Mechanisms for DNS (EDNS0) version information about a remote name server is cached. (You can find more information on EDNS0 in RFC 2671.) Valid values range from 3600 (one hour) to 15724800 (182 days). The default value is 604800 (one week).

EnableDirectoryPartitionSupport

Boolean that indicates whether application partition support has been enabled. Valid only for domain controllers in a forest at the Windows Server 2003 functional level.

EnableDnsSec

Flag indicating whether DNSSEC resource records are returned if queried. The value of this property can be one of the following:


0

DNSSEC records are returned only if the query specifically queried for it.


1

Return DNSSEC records according to RFC 2535 only if the client query includes an OPT record


2

DNSSEC records are always returned, basically according to RFC 2535 regardless of whether the client is using EDNSO.

The default is 1.

EnableEDnsProbes

When TRUE, the name server probes other DNS servers to determine if they support EDNSO. The default is 1 (TRUE).

EventLogLevel

Determines the type of events (i.e., errors or warnings) that are logged to the DNS Event Log. The value of this property can be one of the following:


0

Log nothing.


1

Log errors.


2

Log errors and warnings.


4

Log all events.

The default value is 4.

ForwardDelegations

Determines whether queries for data in delegated subzones are sent to forwarders or follow the delegation. The value of this property can be one of the following:


0

Automatically send queries referring to delegated subzones to the appropriate subzone.


1

Forward queries referring to the delegated subzone to the existing forwarders.

The default value is 0.

Forwarders

Array of IP addresses the server forwards queries to.

ForwardingTimeout

Time in seconds to wait for a response from a forwarded query. The default value is 5 seconds.

IsSlave

Boolean that indicates how the name server responds when forwarded queries do not receive a response. If FALSE, the server attempts to resolve the query and if TRUE the server returns a failure. The default value is FALSE.

ListenAddresses

Array of addresses the name server can receive queries on.

LocalNetPriority

If TRUE, the name server orders records that have a similar IP address to it at the top of the response. If FALSE, then no priority is given based on IP address. This is called "netmask ordering" in the DNS console. The default value is TRUE.

LogFileMaxSize

Maximum size in bytes of the DNS debug log. The default value is 500000000.

LogFilePath

Filename and path to the DNS debug log. The default is %SystemRoot%\system32\dns\dns.log.

LogIPFilterList

Array of IP addresses used to filter entries written to the DNS debug log

LogLevel

Determines which events should be written to the debug log. The value of this property can be the sum of any of the following values:


1

Query


16

Notify


32

Update


254

Nonquery transactions


256

Questions


512

Answers


4096

Send


8192

Receive


16384

UDP


32768

TCP


65535

All packets


65536

AD write transaction


131072

AD update transaction


16777216

Full packets


2147483648

Write through

LooseWildcarding

Boolean that indicates whether the server supports wildcards. The default value is FALSE (do not use loose wildcarding).

MaxCacheTTL

Maximum time-to-live value, in seconds, to accept for records from a remote name server. The default value is 86400 (one day).

MaxNegativeCacheTTL

Maximum time-to-live value, in seconds, to accept from a remote name server for a negative response (e.g., one that indicates that a particular domain name doesn't exist). The default value is 86400 (one day).

Name

Domain name or IP address of server

NameCheckFlag

Indicates the set of eligible characters to be used in domain names. The value for this property can be one of the following:


0

Strict RFC ANSI


1

Non-RFC ANSI


2

Multibyte UTF8


3

All characters

The default value is 2.

NoRecursion

Boolean indicating whether the name server processes recursive queries. The default value is FALSE, which means the name server performs recursive resolution.

RecursionRetry

Time in seconds before retrying a recursive look up. The default value is 3 seconds.

RecursionTimeout

Time in seconds before the name server gives up on processing a recursive query. The default value is 15 seconds.

RoundRobin

Boolean that indicates whether the name server round-robins addresses in responses that return multiple A records. The default value is TRUE.

RpcProtocol

Protocol to run administrative RPC over. The value of this property can be any sum of the following:


0

None


1

TCP


2

Named Pipes


3

LPC

The default value is all protocols.

ScavengingInterval

Interval in hours between scavenging runs. The default value is 168 hours (one week).

SecureResponses

Boolean that indicates whether the name server exclusively caches records of names in the same subtree as the server that provided them. If FALSE, all records are cached, but if TRUE, records are cached only if the name server that responded to the forwarded query is in the same subtree as the returned record. The default value is TRUE. This setting is called "Secure cache against pollution" in the DNS console.

SendPort

Port number from which the name server sends UDP queries to other name servers. The default value is 0, which means a port number is randomly selected.

ServerAddresses

Array of IP addresses for the server.

StrictFileParsing

Boolean that indicates whether the name server parses zone files strictly, which means that if bad data is encountered, the zone fails to load. The default value is FALSE, which means the server continues to load the zone.

UpdateOptions

Flag that restricts the type of records that can be updated via DDNS. Used in conjunction with AllowUpdate. The value of this property can be any sum of the following values:


0

No restrictions.


1

Exclude SOA records.


2

Exclude NS records.


4

Exclude delegation NS records.


8

Exclude server host records.


256

Exclude SOA records for secure dynamic updates.


512

Exclude root NS records for secure dynamic updates.


783

On standard dynamic updates, exclude NS, SOA, and server host records for dynamic updates, and for secure dynamic updates, exclude root NS and SOA records. Allows delegations and server host updates.


1024

On secure dynamic updates, exclude delegation NS records.


2048

Exclude server host records for secure dynamic updates.


16777216

Exclude DS records.


2147483648

Disable dynamic update.

The default value is 0.

Version

Name server version.

WriteAuthorityNS

Boolean that indicates whether the server includes NS and SOA records in the authority section of all successful authoritative responses. The default is FALSE, which means it writes NS records in the Authority section for referrals only, per RFC 2181.

XfrConnectTimeout

Number of seconds the name server waits for a successful TCP connection to a remote name server when attempting a zone transfer. The default value is 30 seconds.

The MicrosoftDNS_Server class also provides a few methods to initiate certain actions on the name server. Two of the most useful are StartService and StopService, which allow you to start and stop the DNS Server service. Table 14-2 lists MicrosoftDNS_Server methods.

Table 14-2. MicrosoftDNS_Server class methods

Method name

Method description

GetDistinguishedName

For AD-integrated zones, gets the DN of the zone.

StartScavenging

Start the scavenging process for zones that have scavenging enabled.

StartService

Start the DNS service.

StopService

Stop the DNS service.

14.3.1 Listing a Name Server's Properties

The first step to programmatically managing your name server's configuration is to see what settings you currently have in place and determine whether any need to be modified. With WMI, it's really easy to list all properties for a name server. The following example shows how to do it:

strServer = "terminator.movie.edu"

' Instantiate a WMI object for the target server
set objDNS = GetObject("winmgmts:\\" & strServer & "\root\MicrosoftDNS")
' Get an instance of the MicrosoftDNS_Server  class
set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""")

' Iterate over each property using Properties_
Wscript.Echo objDNSServer.Properties_.Item("Name") & ":"
for each objProp in objDNSServer.Properties_
   if IsNull(objProp.Value) then
      Wscript.Echo " " & objProp.Name & " : NULL"
   else
      if objProp.IsArray = TRUE then
         For I = LBound(objProp.Value) to UBound(objProp.Value)
             wscript.echo " " & objProp.Name & " : " & objProp.Value(I)
         next
      else
         wscript.echo " " & objProp.Name & " : " & objProp.Value
      end if
   end if 
next

After getting a WMI object for the DNS Provider (root\MicrosoftDNS), we get a MicrosoftDNS_Server object by looking for the "." instance. Since there can be only one instance of MicrosoftDNS_Server running on any given computer, we do not need to worry about multiple objects. After getting a MicrosoftDNS_Server object, we iterate through all the properties of the object and print each one out. Note that we have added special checks for values that contain arrays in order to print each element of the array. In that case, we use Lbound and Ubound to iterate over all the values for the array.

14.3.2 Configuring a Name Server

Now that we can see what values have been set on our name server, we can change some of them. We simply need to set the property method (e.g., EventLogLevel) to the correct value. This example shows how to do it:

strServer = "terminator.movie.edu"

on error resume next

set objDNS = GetObject("winMgmts:\\" & strServer & "\root\MicrosoftDNS")
set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""")

Wscript.Echo objDNSServer.Name & ":"
' See Table 14-1 for an explanation of each of these settings
objDNSServer.EventLogLevel = 4
objDNSServer.LooseWildcarding = TRUE
objDNSServer.MaxCacheTTL = 900
objDNSServer.MaxNegativeCacheTTL = 60
objDNSServer.AllowUpdate = 3
objDNSServer.Put_

if Err then
   Wscript.Echo " Error occurred: " & Err.Description
else 
   WScript.Echo " Change successful"
end if

Note that we had to call Put_ at the end. If we hadn't, none of the changes would have been committed. This is similar to ADSI's SetInfo method, which must be called after modifying an object's property cache to make the change actually take effect.

14.3.3 Restarting the DNS Server Service

Some changes you make to a DNS Server require the service to be restarted for the changes to take effect. We can utilize the StopService and StartService methods as shown in the following example to do this:

strServer = "terminator.movie.edu"

on error resume next

set objDNS = GetObject("winMgmts:\\" & strServer & "\root\MicrosoftDNS")
set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""")

objDNSServer.StopService
if Err Then
  WScript.Echo "StopService failed: " & Err.Description
  Wscript.Quit
end if

objDNSServer.StartService
if Err Then
  WScript.Echo "StartService failed: " & Err.Description
  Wscript.Quit
end if

WScript.Echo "Restart successful"

14.3.4 Putting It Together: Configuration Check Script

Building on the examples we've used so far in this chapter, we can now write a robust script to check name server configurations. Such a script can be very important, especially in large environments with many name servers. Unless you have a script that routinely checks the configuration on all of your name servers, it's very likely that those servers will not have an identical configuration. If they don't have identical configurations, then when problems pop up, you may end up spending a lot of time troubleshooting because of the discrepancies between the name servers.

To perform the configuration checking, we store each setting in a VBScript Dictionary object. For those accustomed to other languages such as Perl, a Dictionary object is the VBScript analog to a hash or associative array. Another option would be to store the settings in a text file and read them into a Dictionary object when the script starts up. The following example shows the configuration check code:

option explicit
on error resume next

Dim arrServers
Dim strUsername, strPassword
Dim dicDNSConfig

' Array of DNS servers to check
arrServers = Array("terminator.movie.edu","fx.movie.edu")

' User and password that can modify the config on the DNS servers
strUsername = "dnsadmin"
strPassword = "dnspwd"

' This dictionary object will contain the key value pairs for all the settings
' that you want to check and configure on the DNS servers
Set dicDNSConfig = CreateObject("Scripting.Dictionary") 
dicDNSConfig.Add "AllowUpdate",             1
dicDNSConfig.Add "LooseWildCarding",        TRUE
dicDNSConfig.Add "MaxCacheTTL",             900
dicDNSConfig.Add "MaxNegativeCacheTTL",     60
dicDNSConfig.Add "EventLogLevel",           0
dicDNSConfig.Add "StrictFileParsing",       TRUE
dicDNSConfig.Add "DisableAutoReverseZones", TRUE

Dim arrDNSConfigKeys
arrDNSConfigKeys = dicDNSConfig.keys

Dim objLocator
Set objLocator = CreateObject("WbemScripting.SWbemLocator")

Dim x, y, boolRestart
For x = LBound(arrServers) to UBound(arrServers)
   boolRestart = False

   WScript.echo arrServers(x)

   Dim objDNS, objDNSServer
   Set objDNS = objLocator.ConnectServer(arrServers(x), "root\MicrosoftDNS", _
                                         strUserName, strPassword)
   set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""")

   for y = 0 To dicDNSConfig.Count - 1
      Dim strKey
      strKey = arrDNSConfigKeys(y)

      WScript.Echo "  Checking " & strKey
      if dicDNSConfig.Item(strKey) <> objDNSServer.Properties_.Item(strKey) then
         objDNSServer.Properties_.Item(strKey).value = dicDNSConfig(strKey)
         objDNSServer.Put_     
         boolRestart = TRUE
         if Err Then
            WScript.Echo "    Error setting " & strKey & " : " & Err.Description
            Wscript.Quit
         else
            WScript.Echo "    " & strKey & " updated"
         end if
      end if
   Next 

   if boolRestart then
      objDNSServer.StopService
      if Err Then
         WScript.Echo "StopService failed: " & Err.Description
         Wscript.Quit
      end if

      objDNSServer.StartService
      if Err Then
         WScript.Echo "StartService failed: " & Err.Description
         Wscript.Quit
      end if
      WScript.Echo "Restarted"
   end if

   WScript.Echo ""
next

Besides the use of the Dictionary object, most of the script is a combination of the other three examples shown so far in this chapter. We added a server array so that you can check multiple servers at once. For each server, the script simply checks each key in the Dictionary object to see if its value matches the key on the name server. If not, it modifies the server and commits the change via Put_. After it's done looping through all the settings, it restarts the DNS Server service if a change has been made to its configuration. It then proceeds to the next server.

One enhancement that would make the process even more automated would be to dynamically query the list of name servers instead of hard-coding them in an array. You would need to look up the NS records for one or more zones that your name servers are authoritative for. As long as an NS record is added for each new name server, the script would automatically discover new name servers on subsequent runs. Later in the chapter, we show how to query name servers with the DNS Provider.

14.3.5 Monitoring Server Performance

If you've ever wanted a programmatic way to access the output of the dnscmd /statistics command, now you have one. The MicrosoftDNS_Statistic class provides complete access to all the performance metrics you can get using dnscmd or Performance Monitor. And it's easy too! Check out this script, which prints out all of the statistics:

strServer = "terminator.movie.edu "

set objDNS = GetObject("winMgmts:\\" & strServer & "\root\MicrosoftDNS")
set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""")
set objStats = objDNS.ExecQuery("Select * from MicrosoftDNS_Statistic ")
for each objStat in objStats
   WScript.Echo " " & objStat.Name & " : " & objStat.Value
next

And if you want to access only a subset of the metrics (for example, all of the entries that start with "Records") you only need to modify the WQL query slightly:

set objStats = objDNS.ExecQuery("Select * from MicrosoftDNS_Statistic " & _
                                 where Name like 'Records%' ")