PowerShell - Test-DnsServerScavenging.ps1
- Jon Boyette
- Jan 25, 2022
- 3 min read
Save as the above name, when used with examples, this becomes easy to check and set the intervals as follows: .EXAMPLE
./Test-DnsServerScavenging -ZoneName 'lan.example.com'
.EXAMPLE
./Test-DnsServerScavenging -ZoneName 'lan.example.com' -NoRefreshInterval (New-TimeSpan -Days 3) -RefreshInterval (New-TimeSpan -Days 7)
# Test-DnsServerScavenging v1.0 (c) Chris Redit
<#PSScriptInfo
.VERSION
1.0
.GUID
d9441570-2460-4c51-b906-a29c3736af35
.AUTHOR
Chris Redit
.COMPANYNAME
.COPYRIGHT
(c) 2017 Chris Redit. All rights reserved.
.TAGS
dns
.LICENSEURI
.PROJECTURI
https://github.com/chrisred/posh-scripts
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
#Test-DnsServerScavenging -ZoneName 'salelytics.local' | Export-csv c:\temp\DNSScavenging.csv | ft -Auto
#>
<#
.SYNOPSIS
Run a test DNS server scavenging event.
.DESCRIPTION
Runs a test DNS scavenging event and returns DNS resource records that are candidates for removal and considered stale.
By default the aging intervals of the DNS zone will be used, however a duration for the intervals can be chosen by passing a [TimeSpan] object to the -NoRefreshInterval and -RefreshInterval parameters.
Records that fall within either of the two intervals can be returned using the -Type parameter. The keyword "Stale" can be used to return records that fall outside both interval durations. This is the default behaviour.
.PARAMETER ZoneName
Specifies the DNS zone to query.
.PARAMETER RRType
Specifies the type of resource record.
.PARAMETER NoRefreshInterval
Specifies the period for the no-refresh interval, this must be at least 1 hour. The default is the current server setting.
.PARAMETER RefreshInterval
Specifies the period for the refresh interval, this must be at least 1 hour. The default is the current server setting.
.PARAMETER Type
Specifies which resource records will be returned, acceptable values are: NoRefresh, Refresh and Stale. The default is "Stale".
.PARAMETER ComputerName
Runs the cmdlet on the specified computer. The default is the local computer.
.OUTPUTS
$null or an array of [CimInstance] objects on success.
A non-terminiating error if the DNS zone name is invalid.
A terminiating error in all other cases.
.EXAMPLE
./Test-DnsServerScavenging -ZoneName 'lan.example.com'
.EXAMPLE
./Test-DnsServerScavenging -ZoneName 'lan.example.com' -NoRefreshInterval (New-TimeSpan -Days 3) -RefreshInterval (New-TimeSpan -Days 7)
#>
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[String]$ZoneName,
[String]$RRType = '',
[Nullable[TimeSpan]]$NoRefreshInterval = $null,
[Nullable[TimeSpan]]$RefreshInterval = $null,
[ValidateSet('NoRefresh','Refresh','Stale')]
[String]$Type = 'Stale',
[String]$ComputerName = $env:COMPUTERNAME
)
Begin
{
# import the modules we need if they are not already
if (-not (Get-Module -Name ActiveDirectory)) {Import-Module ActiveDirectory -EA Stop}
if (-not (Get-Module -Name DnsServer)) {Import-Module DnsServer -EA Stop}
}
Process
{
try
{
# DNS records are time stamped with the date accurate to the current hour, get the current date here in the same format for calculation later
$Now = (Get-Date(Get-Date -Format 'yyyy-MM-dd HH:00:00'))
$Aging = Get-DnsServerZoneAging -Name $ZoneName -ComputerName $ComputerName -EA Stop
if ($Aging.AgingEnabled -eq $false)
{
Write-Warning "Aging is not enabled for the zone $ZoneName, resource record timestamps will not be replicated."
}
if ($NoRefreshInterval -eq $null) {$NoRefreshInterval = $Aging.NoRefreshInterval}
if ($RefreshInterval -eq $null) {$RefreshInterval = $Aging.RefreshInterval}
if ($NoRefreshInterval.TotalHours -lt 1 -or $RefreshInterval.TotalHours -lt 1)
{
throw "The No-refresh and Refresh intervals must be at least 1 hour."
}
# stale records will be those older than the No-refresh and Refresh intervals combined
$StaleThreshold = ($NoRefreshInterval + $RefreshInterval)
$DnsParams = @{
'ComputerName' = $ComputerName;
'ZoneName' = $ZoneName;
'ErrorAction' = 'Stop'
}
if ($RRType) {$DnsParams['RRType'] = $RRType}
# return an array of DNS records filtered by the type requested
switch ($Type)
{
'NoRefresh' {Get-DnsServerResourceRecord @DnsParams | Where-Object {$_.TimeStamp -is [DateTime] -and $_.Timestamp -ge $Now.AddHours('-'+$NoRefreshInterval.TotalHours)}}
'Refresh' {Get-DnsServerResourceRecord @DnsParams | Where-Object {$_.TimeStamp -is [DateTime] -and $_.Timestamp -ge $Now.AddHours('-'+$StaleThreshold.TotalHours) -and $_.Timestamp -lt $Now.AddHours('-'+$NoRefreshInterval.TotalHours)}}
'Stale' {Get-DnsServerResourceRecord @DnsParams | Where-Object {$_.TimeStamp -is [DateTime] -and $_.Timestamp -lt $Now.AddHours('-'+$StaleThreshold.TotalHours)}}
}
}
catch [Microsoft.Management.Infrastructure.CimException]
{
# there appear to be some standard message IDs in the CimException objects
if ($_.Exception.MessageId -eq 'WIN32 9601')
{
# raise a non-terminating error for an invalid zone name
Write-Error "The DNS zone $ZoneName was not found. $($_.Exception.Message)"
}
elseif ($_.Exception.MessageId -eq 'WIN32 1722' -or $_.Exception.MessageId -eq 'WIN32 1753')
{
# raise a terminating error for an invalid computer name
throw "Computer $ComputerName is not a DNS server or is not responding. $($_.Exception.Message)"
}
else
{
# raise a terminating error for any other CimException exceptions
throw $_.Exception.Message
}
}
}
Comments