Created
August 25, 2020 13:47
-
-
Save AceOfNitwits/aafe78ef5181dfd745ebdf033678c3e2 to your computer and use it in GitHub Desktop.
Monitor for DNS Changes with PowerShell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Records and compares DNS entries, checking their expected values against their current values. | |
| .DESCRIPTION | |
| DNS entries are stored in XML files in the current path or the path specified by the -BasePath parameter. | |
| When run with the -AddDomain parameter, performs DNS lookups for SOA, NS, MX, TXT, and A records, as well as an A record for the autodiscover host and both an A and CNAME for the www host. Query responses are saved in .XML files in the current path or the path specified by the -BasePath parameter. | |
| When run with the -AddHost (and optional -QueryType) parameter, performs a DNS lookup for the specified host. Query responses are saved in .xml files in the current path or the path specified by the -BasePath parameter. | |
| When run with the -RunComparison parameter, performs DNS lookups for all previously-generated XML files in the current path, or the path specified by the -BasePath parameter. Alerts to any discrepencies found. | |
| .EXAMPLE | |
| ./Compare-DNS.ps1 -RunComparison | |
| Compares previously-generated files in the current path against current DNS queries. | |
| .EXAMPLE | |
| ./Compare-DNS.pst -AddDomain abc.com, xyz.com | |
| Creates .xml files for the specified domains in the current folder. | |
| .EXAMPLE | |
| ./Compare-DNS.pst -AddHost www.abc.com, autodiscover.abc.com -QueryType cname, a | |
| Creates .xml files for the specified hosts and specified query types in the current folder. | |
| .PARAMETER -RunComparison | |
| Runs the comparison against the previously generated files in the current folder. | |
| .PARAMETER -AddDomain | |
| Performs lookups and creates files for the domain(s) specified by this parameter. Uses the current folder or the -BasePath parameter to determine when to put the files. | |
| This parameter will also update existing files. | |
| .PARAMETER -BasePath | |
| Used to specify a non-default path for the .xml files.get | |
| .PARAMETER -DnsServer | |
| Specifies the DNS server to use for name resolution. Default will use the default server. | |
| .PARAMETER -Pause | |
| Require user to press Enter before the script will terminate. For use with Windows shortcut. | |
| To use in a shortcut: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "& 'C:\Users\Username\My Documents\Scripts\Compare-DNS.ps1' -runComparison -Pause" | |
| #> | |
| Param( | |
| [switch]$RunComparison=$false, | |
| [string[]]$AddHost, | |
| [string[]]$QueryType, | |
| [string[]]$AddDomain, | |
| [string]$BasePath = '.', | |
| [string]$DNSServer, | |
| [switch]$Pause | |
| ) | |
| <# | |
| Iterates through a folder of XML files that contain DNS query response objects. | |
| Figures out what the original query that generated them was and compares the two. | |
| #> | |
| Function Test-Resolutions { | |
| Get-ChildItem -Path $basePath -Filter "*.xml" | ForEach-Object { #Get the xml files and iterate through them. | |
| Write-Progress "Checking $_" #Write the name of the file currently being processed. | |
| $expectedResponse = Import-Clixml $_.FullName #Import the xml file so we can do an object comparison. | |
| If($expectedResponse){ #There might be a blank file, so we need to handle that. | |
| $queryName = $expectedResponse[0].Name #This gets the domain name | |
| $queryType = $expectedResponse[0].QueryType #This gets the query type | |
| # Create the parameter hash table to splat to the Resolve-DnsName cmdlet. | |
| $resolutionParameters = @{ | |
| Name = $queryName; | |
| Type = $queryType; | |
| DnsOnly = $true; | |
| NoHostsFile = $true; | |
| } | |
| # If the user selected a custom DNS server, add that to the hash table. | |
| # We can't reliably get the default DNS server, so this is how we do a conditional parameter. | |
| If($dnsserver){ | |
| $resolutionParameters += @{Server = $DNSServer} | |
| } | |
| $currentResponse = Resolve-DnsName @resolutionParameters #Run the original query that generated the file. | |
| If(Compare-Object $expectedResponse $currentResponse -Property Name,NameAdministrator,NameExchange,Preference,IP4Address,Strings,IPAddress,PrimaryServer,NameHost){ #Compare the original file to the result of the new query. If there's a difference this will return something. | |
| Write-Host "Difference Detected!!!" -BackgroundColor Red -ForegroundColor Black #Yikes! Something changed! | |
| #Compare-Object $expectedResponse $currentResponse -Property Name,NameAdministrator,NameExchange,Preference,IP4Address,Strings,IPAddress,PrimaryServer,NameHost,Strings | FT | |
| Write-Host "Expected response (from file $_, last modified on " $_.LastWriteTime ")" -ForegroundColor Yellow | |
| $expectedResponse | Select-Object -Property Type,Name,NameAdministrator,NameExchange,Preference,IP4Address,Strings,IPAddress,PrimaryServer,NameHost # Format-Table #Show me what you expected to get. | |
| Write-Host "Current Response:" -ForegroundColor Yellow | |
| $currentResponse | Select-Object -Property Type,Name,NameAdministrator,NameExchange,Preference,IP4Address,Strings,IPAddress,PrimaryServer,NameHost # Format-Table #Now show me what you got. | |
| } | |
| } | |
| } | |
| } | |
| <# | |
| Accepts an array of domain names in the following format | |
| domain1.com,domain2.com,domain3.com | |
| Generates XML files with DNS responses returned from various queries. | |
| #> | |
| Function Add-Domain ($domainList) { | |
| $myQueryTypes = ('soa', 'ns', 'mx', 'txt', 'a') | |
| Add-Record $domainList $myQueryTypes | |
| Foreach($domain in $domainList){ | |
| Add-Record "www.$domain" a, cname | |
| Add-Record "autodiscover.$domain" cname | |
| } | |
| } | |
| Function Add-Record ($hostList, $typeList) { | |
| If(-not $typeList){ # No query types were provided. | |
| $typeList = 'a' # Set the query type to 'a'. | |
| } | |
| Foreach($myHost in $hostList){ | |
| # The following lines reverse the components of the dns name so we can create a file name with the tld first. | |
| $hostArray = $myHost.Split('.') | |
| [array]::Reverse($hostArray) | |
| $reverseHost = [string]::join('.',$hostArray) | |
| foreach($type in $typeList){ | |
| # Create the parameter hash table to splat to the Resolve-DnsName cmdlet. | |
| $resolutionParameters = @{ | |
| Name = $myHost; | |
| Type = $type; | |
| DnsOnly = $true; | |
| NoHostsFile = $true; | |
| ErrorAction = 'STOP' | |
| } | |
| # If the user selected a custom DNS server, add that to the hash table. | |
| # We can't reliably get the default DNS server, so this is how we do a conditional parameter. | |
| If($dnsserver){ | |
| $resolutionParameters += @{Server = $DNSServer} | |
| } | |
| Write-Progress "Querying $type record for $host." | |
| try { | |
| Resolve-DnsName @resolutionParameters | Export-Clixml -Path "$basePath\$reverseHost.$type.xml" #Generate the record file. | |
| } | |
| catch { | |
| Write-Host "Could not resolve $type record for $myHost`: $_" -ForegroundColor Red | |
| } | |
| } | |
| } | |
| } | |
| If ($RunComparison){Test-Resolutions} | |
| If ($AddDomain){Add-Domain $AddDomain} | |
| If ($AddHost){Add-Record $AddHost $QueryType} | |
| If ($Pause){ | |
| Read-Host -Prompt "Press Enter to Continue" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment