diff --git a/Tasks/Clean-StaleDNSRecord.ps1 b/Tasks/Clean-StaleDNSRecord.ps1 index 72c1815..b6bff3d 100644 --- a/Tasks/Clean-StaleDNSRecord.ps1 +++ b/Tasks/Clean-StaleDNSRecord.ps1 @@ -1,6 +1,6 @@ -<# +<# .SYNOPSIS - Cleans duplicate DNS records + Cleans duplicate DNS records .DESCRIPTION Searches DNS records for duplicates on the specified subnet. Also removes unresponsive clients from DNS. Useful for VPN records that aren't scrubbed @@ -12,67 +12,89 @@ Used for looking up zone name and filtering .PARAMETER Subnet - Search pattern for subnet. Astrisk is wildcard. + Search pattern for subnet. Astrisk is wildcard + +.PARAMETER NoPing + By default script will also ping clients to check connectivity. If ICMP is blocked or clients aren't configured to reply, use -NoPing to skip. .EXAMPLE - .\Clean-StaleDNSRecord.ps1 -domain "example.com" -subnet "10.20.*" + .\Clean-StaleDNSRecord.ps1 -domain "example.com" -subnet "10.20.*" #> [CmdletBinding(SupportsShouldProcess)] param ( - [string]$DNSServer, - [Parameter(Mandatory=$True)] - [string]$Domain, - [Parameter(Mandatory=$True)] - [string]$Subnet + [string]$DNSServer, + [Parameter(Mandatory=$True)] + [string]$Domain, + [Parameter(Mandatory=$True)] + [string]$Subnet, + [switch]$NoPing ) $DNSArgs = @{ - ZoneName = $Domain - RRType = 'A' + ZoneName = $Domain + RRType = 'A' } if ($DNSServer){ - $DNSArgs.Add('ComputerName',$DNSServer) + $DNSArgs.Add('ComputerName',$DNSServer) } -Write-Verbose 'Checking DNS records' -Verbose +Write-Verbose 'Pulling DNS records' -Verbose $DNSRecords = Get-DnsServerResourceRecord @DNSArgs | Where-Object {$_.RecordData.IPv4Address -like $Subnet -and ($_.Timestamp) -and $_.Hostname -notlike "*.$Domain"} |` - Select-Object Hostname,Timestamp,@{N="IPv4Address";E={$_.RecordData.IPv4Address}} + Select-Object Hostname,Timestamp,@{N="IPv4Address";E={$_.RecordData.IPv4Address}} | Sort-Object IPv4Address, Timestamp -Descending if (!$?){ - exit + exit +} + +#Remove duplicate records that are older than most recent +Write-Verbose 'Searching and removing duplicate IPs in DNS' -Verbose +$IPCount = 1 +Foreach ($Record in $DNSRecords){ + if ($Record.IPv4Address -eq $LastIP){ + $IPCount++ + }else{ + $IPCount = 1 + } + if ($IPCount -gt 1){ + Remove-DnsServerResourceRecord @DNSArgs -Name $Record.Hostname -RecordData $Record.IPv4Address -Force -Verbose + } + $LastIP = $Record.IPv4Address } -$Script = { - param( - [string]$IP, - [string]$Hostname, - $DNSArgs - ) +$PingScript = { + param( + [string]$IP, + [string]$Hostname, + $DNSArgs + ) - if (!(Test-Connection $IP -Quiet)){ - Remove-DnsServerResourceRecord @DNSArgs -Name $Hostname -RecordData $IP -Force -Verbose - } + if (!(Test-Connection $IP -Quiet)){ + Remove-DnsServerResourceRecord @DNSArgs -Name $Hostname -RecordData $IP -Force -Verbose + } } + #check for orphaned jobs Get-Job -Name DNSCleanup -ErrorAction SilentlyContinue | Remove-Job -Write-Verbose 'Checking connectivity of addresses in DNS' -Verbose -foreach($Record in $DNSRecords){ - Start-Job -Name DNSCleanup -ScriptBlock $Script -ArgumentList $Record.IPv4Address,$Record.Hostname,$DNSArgs > $null -} +if (!$NoPing){ + Write-Verbose 'Checking connectivity of addresses in DNS' -Verbose + foreach($Record in $DNSRecords){ + Start-Job -Name DNSCleanup -ScriptBlock $PingScript -ArgumentList $Record.IPv4Address,$Record.Hostname,$DNSArgs > $null + } -$JobsRunning = (Get-Job -Name DNSCleanup | where {$_.State -eq 'Running'}).Count -while ($JobsRunning -gt 0){ - Write-Host "`rChecking " -NoNewline - Write-Host "$JobsRunning " -ForegroundColor Yellow -NoNewline - Write-Host 'records...' -NoNewline - Start-Sleep -Seconds 1 - $JobsRunning = (Get-Job -Name DNSCleanup | where {$_.State -eq 'Running'}).Count -} -Write-Host + $JobsRunning = (Get-Job -Name DNSCleanup | where {$_.State -eq 'Running'}).Count + while ($JobsRunning -gt 0){ + Write-Host "`rChecking " -NoNewline + Write-Host "$JobsRunning " -ForegroundColor Yellow -NoNewline + Write-Host 'records...' -NoNewline + Start-Sleep -Seconds 1 + $JobsRunning = (Get-Job -Name DNSCleanup | where {$_.State -eq 'Running'}).Count + } + Write-Host -#Print results -$EndJobs = Get-Job -Name DNSCleanup -$EndJobs | Receive-Job -$EndJobs | Remove-Job + #Print results + $EndJobs = Get-Job -Name DNSCleanup + $EndJobs | Receive-Job + $EndJobs | Remove-Job +}