There are close to 50 different settings that can be configured on a Microsoft DNS server. They range from default scavenging and logging settings to settings that customize the DNS server behavior, such as how zone transfers will be sent to secondaries and whether to round-robin multiple A record responses.
The DNS provider is mapped to the root\MicrosoftDNS namespace. A DNS server is represented by an instance of a MicrosoftDNS_Server class, which is derived from the CIM_Service class. Table 27-1 contains all the property methods available in the MicrosoftDNS_Server class.
Property name |
Property description |
---|---|
AddressAnswerLimit |
Max number of records to return for address requests (e.g., A records). |
AllowUpdate |
Determines whether DDNS updates are allowed. |
AutoConfigFileZones |
Indicates which standard primary zones that are authoritative for the name of the DNS server must be updated when the name server changes. |
AutoCacheUpdate |
Indicates whether the DNS server will dynamically attempt to update its root hints (also known as cache) file. |
BindSecondaries |
Determines the format zone transfers (AXFR) will be sent as to non-Microsoft DNS servers. |
BootMethod |
Determines where the server will read its zone information. |
DefaultAgingState |
For AD-integrated zones, the default scavenging interval in hours. |
DefaultNoRefreshInterval |
For AD-integrated zones, the default no-refresh interval in hours. |
DefaultRefreshInterval |
For AD-integrated zones, the default refresh interval in hours. |
DisableAutoReverseZones |
Determines whether the server automatically creates reverse zones. |
DisjointsNets |
Indicates whether the default port binding for a socket used to send queries to remote DNS servers can be overridden. |
DsAvailable |
Indicates whether Active Directory is available on the server. |
DsPollingInterval |
For AD-integrated zones, the interval in seconds to poll Active Directory for updates. |
DsTombstoneInterval |
For AD-integrated zones, the length of time in seconds that tombstoned records (i.e. deleted) should remain in Active Directory. |
EdnsCacheTimeout |
Length of time, in seconds, the cached EDNS version information is cached. |
EnableDirectoryPartitionSupport |
Flag indicating whether application partition support has been enabled. |
EnableEDnsProbes |
When TRUE, the DNS server always responds with OPT resource records according to RFC 2671, unless the remote server has indicated it does not support EDNS in a prior exchange. If FALSE, the DNS server responds to queries with OPTs only if OPTs are sent in the original query. |
EnableDnsSec |
Flag indicating whether DNSSEC resource records are returned if queried. |
EventLogLevel |
Determines the type of events (e.g., errors or warnings) that will be logged to the DNS Event Log. |
Forwarders |
List of IPs the server forwards queries to. |
ForwardDelegations |
Determines whether queries to delegated subzones are forwarded. |
ForwardingTimeout |
Time in seconds to wait for a response from a forwarded query. |
IsSlave |
Indicates whether the DNS server is a slave. |
ListenAddresses |
List of addresses the DNS server can receive queries on. |
LocalNetPriority |
If TRUE, records for IPs on the same net are given a higher priority. |
LogFileMaxSize |
Max size in bytes of the DNS server log. |
LogFilePath |
Filename and path to DNS server log. |
LogIPFilterList |
List of IPs used to filter entries written to the DNS server log. |
LogLevel |
Determines what events should be written to the system log. |
LooseWildcarding |
Indicates whether the server supports wildcarding (e.g., * MX records). |
MaxCacheTTL |
Max time in seconds to leave a recursive query in the local cache. |
MaxNegativeCacheTTL |
Max time in seconds to leave a recursive query that resulted in an error in the local cache. |
Name |
FQDN or IP of server. |
NameCheckFlag |
Indicates the set of eligible characters to be used in DNS names. |
NoRecursion |
Flag indicating whether the server will perform recursive lookups. |
RecursionRetry |
Time in seconds before retrying a recursive lookup. |
RecursionTimeout |
Time in seconds before the DNS server gives up recursive query. |
RoundRobin |
Flag indicating whether the server will round-robin addresses returned from a query that returns multiple A records. |
RpcProtocol |
Protocol to run administrative RPC over. |
ScavengingInterval |
Interval in hours between initiating scavenges. |
SecureResponses |
Indicates whether the DNS server exclusively saves records of names in the same subtree as the server that provided them. |
SendPort |
Port on which the DNS server sends UDP queries to other servers. |
ServerAddresses |
List of IP addresses for the server. |
StrictFileParsing |
Indicates whether the DNS server parses zone file strictly, which means if bad data is encountered, the zone will fail to load. |
UpdateOptions |
Flag that restricts the type of records that can be updated via DDNS. |
Version |
DNS server version |
WriteAuthorityNS |
Flag indicating whether the server includes NS and SOA records in the authority section on successful response. |
XfrConnectTimeout |
Number of seconds server waits for a successful TCP connection to a remote server when attempting a zone transfer. |
The MicrosoftDNS_Server class also provides a few methods to initiate certain actions on the DNS server. Perhaps two of the most useful are StartService and StopService, which allow you to start and stop the DNS service. Table 27-2 contains the list of methods available to the MicrosoftDNS_Server class
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. |
The first step in programmatically managing your DNS server configuration is to see what settings you currently have and determine whether any need to be modified. With WMI, it is really easy to list all properties for the server. The following example shows how to do it:
Set objDNS = GetObject("winMgmts:root\MicrosoftDNS") set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""") 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 only be 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 to print each element of the array. In that case, we use Lbound and Ubound to iterate over all the values for the array.
Now that we can see what values have been set on our DNS server, we may want to change some of them. To do so is very straightforward. We simply need to set the property method (e.g., EventLogLevel) to the correct value. This example shows how it can be done:
on error resume next Set objDNS = GetObject("winMgmts:root\MicrosoftDNS") set objDNSServer = objDNS.Get("MicrosoftDNS_Server.Name="".""") Wscript.Echo objDNSServer.Name & ":" 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 didn't, none of the changes would have been committed.
After making changes to DNS settings, you typically will need to restart the DNS service for them to take effect. We can utilize the StopService and StartService methods as shown in the following example to do this:
on error resume next Set objDNS = GetObject("winMgmts: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"
Building on the examples we've used so far in this chapter, we can now move forward with writing a robust DNS server configuration check script. A configuration check script can be very important, especially in large environments where you may have many DNS servers. Unless you have a script that routinely checks the configuration on all of your DNS servers, it is very likely that those servers will not have an identical configuration. If this is true, when problems pop up over time, you may end up spending considerably more time troubleshooting because of the discrepancies between the servers.
To accomplish the configuration checking, we will store each setting in a VBScript Dictionary object. For those coming from other languages such as Perl, a Dictionary object is the VBScript analog of a hash or associative array. It is not extremely flexible but works well in situations such as what we need. Another option would be to store the settings in a text file and read them into a Dictionary object when the script starts up. Example 27-1 contains 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("dns1.mycorp.com","dns2.mycorp.com") ` 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. Then for each server, the script simply checks each key in the Dictionary object to see whether the value for it matches that on the DNS 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 service if a change has been made to its configuration. If a change has not been made, it proceeds to the next server.
One enhancement that would make the process even more automated would be to dynamically query the list of DNS servers instead of hardcoding them in an array. You simply would need to query the NS record for one or more zones that your DNS servers are authoritative for. As long as an NS record is added for each new name server, the script would automatically pick it up in subsequent runs. Later in the chapter, we will show how to query DNS with the DNS provider.