Microsoft DNS & stale records
This post explains how to identify and report on stale records in a dynamically updated Microsoft DNS zone.
The time stamp taken from a DNS record represents the numbers of hours since 01/01/1601 00:00. The value can be converted into a useful date within a script. By default, all times are reported and tested in UTC.
A stale record is a record where both the No-Refresh Interval and Refresh Interval have passed without the time stamp updating. Ordinarily stale records would be removed by a Scavenging process. These scripts may be useful if trying to asses the impact of enabling Scavenging or reducing Aging intervals.
Listing stale records with VbScript
This script uses a WMI query to return all A records for a domain, then it sorts through each record, echoing when the time stamp is older than our pre-defined maximum age. The script will work best when run with cscript.
' No-Refresh + Refresh (in Days)
Const MAXIMUM_AGE = 4
' Connect to the MicrosoftDNS Namespace
Set objWMIService = _
GetObject("winmgmts:\\dc01.internal.highorbit.co.uk\root\MicrosoftDNS")
' Query A records with MicrosoftDNS_AType class where the record is not static
Set colItems = objWMIService.ExecQuery("SELECT * FROM MicrosoftDNS_AType " &_
" WHERE ContainerName='internal.highorbit.co.uk' AND TimeStamp<>0")
For Each objItem In colItems
' Convert the timestamp into a date and time
dtmTimeStamp = DateAdd("h", objItem.TimeStamp, "01/01/1601 00:00:00")
' Compare the date and time with MAXIMUM_AGE
If dtmTimeStamp <= (Date() - MAXIMUM_AGE) Then
' Echo the record details if it is older than the MAXIMUM_AGE
WScript.Echo objItem.OwnerName & VbTab & objItem.IPAddress &_
VbTab & dtmTimeStamp
End If
Next
Listing stale records with PowerShell
This snippet uses Get-WMIObject and a improved query to return only stale records rather than sorting after returning all dynamic records.
A timespan value is generated to represent the minimum value of TimeStamp for valid records.
# No-Refresh + Refresh (in Days)
$TotalAgingInterval = 4
$ServerName = "dc01.internal.highorbit.co.uk"
$ContainerName = "internal.highorbit.co.uk"
$MinTimeStamp = [Int](New-TimeSpan `
-Start $(Get-Date("01/01/1601 00:00")) `
-End $((Get-Date).AddDays(-$TotalAgingInterval))).TotalHours
Get-WMIObject -Computer $ServerName `
-Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_AType" `
-Filter `
"ContainerName='$ContainerName' AND TimeStamp<$MinTimeStamp AND TimeStamp<>0" `
| Select-Object OwnerName, `
@{n="TimeStamp";e={(Get-Date("01/01/1601")).AddHours($_.TimeStamp)}}
Reading Aging intervals with PowerShell
The Aging intervals and the date the zone can be scavenged set on a zone can be read using WMI using the MicrosoftDNS_Zone class. As with the TimeStamp the .AddHours method must be used to return a date.
$ServerName = "dc01.internal.highorbit.co.uk"
$ContainerName = "internal.highorbit.co.uk"
Get-WMIObject -Computer $ServerName `
-Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_Zone" `
-Filter "ContainerName='$ContainerName'" `
| Select-Object NoRefreshInterval, RefreshInterval, `
@{n="AvailForScavengeTime";e={
(Get-Date("01/01/1601")).AddHours($_.AvailForScavengeTime)}}
Localisation
As mentioned at the beginning of this post, all times are reported in UTC by default. By calling a the ToLocalTime method the date returned can be converted to local time, using the time zone configured on the system executing the query.
$ServerName = "dc01.internal.highorbit.co.uk"
$ContainerName = "internal.highorbit.co.uk"
$MinTimeStamp = [Int](New-TimeSpan `
-Start $(Get-Date("01/01/1601 00:00")) `
-End $((Get-Date).AddDays(-$TotalAgingInterval))).TotalHours
Get-WMIObject -Computer $ServerName `
-Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_AType" `
-Filter `
"ContainerName='$ContainerName' AND TimeStamp<$MinTimeStamp AND TimeStamp<>0" `
| Select-Object OwnerName, `
@{n="TimeStamp";e={
((Get-Date("01/01/1601")).AddHours($_.TimeStamp)).ToLocalTime()}}
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
Respond to this post