#Requires -Version 5.1 <# .SYNOPSIS dnssec_check.ps1 - prueft fuer hinterlegte Domains, ob DNSSEC aktiviert und gueltig signiert ist. (Windows-Pendant zum Bash-Skript dnssec_check.) .DESCRIPTION Zielsystem : Windows 10/11 / Windows Server (Windows PowerShell 5.1 oder PowerShell 7+). Nutzt das native Cmdlet Resolve-DnsName (Modul DnsClient) - kein dig noetig. Status-Bedeutung: aktiv - Domain ist DNSSEC-signiert UND wurde vom Resolver ausgeliefert (Antwort erhalten + RRSIG-Records vorhanden) inaktiv - Domain ist NICHT signiert (Antwort erhalten, keine RRSIG) fail - DNSSEC vorhanden, aber Validierung schlaegt fehl / Fehler (Abfrage scheitert; Gegenprobe mit -DnssecCd bestaetigt DNSSEC) Hinweis: Resolve-DnsName liefert das AD-Header-Flag nicht zurueck. Statt des AD-Flags wird das Vorhandensein von RRSIG-Records ausgewertet. Ob der Resolver *wirklich* validiert, klaert der Selbsttest (kaputte Domain muss scheitern). Ohne validierenden Resolver ist die Pruefung nicht aussagekraeftig. .PARAMETER Resolver DNS-Resolver, der geprueft wird (Default: 127.0.0.1 = lokaler DNS). .PARAMETER QType Abfragetyp (Default: A). .PARAMETER SelfCheck Nur pruefen, ob der Resolver DNSSEC validiert (keine Domainliste). .PARAMETER Domains Optional: Domains, die statt der hinterlegten Liste geprueft werden. .EXAMPLE .\dnssec_check.ps1 .EXAMPLE .\dnssec_check.ps1 -Resolver 192.168.1.10 .EXAMPLE .\dnssec_check.ps1 -SelfCheck .EXAMPLE .\dnssec_check.ps1 isc.org dnssec-failed.org #> [CmdletBinding()] param( [string] $Resolver = "127.0.0.1", [string] $QType = "A", [switch] $SelfCheck, [Parameter(ValueFromRemainingArguments = $true)] [string[]] $Domains ) # ------------------------------------------------------------------ # Konfiguration # ------------------------------------------------------------------ # >>> Hier die zu pruefenden Domains eintragen <<< $DefaultDomains = @( "isc.org" # signiert -> erwartet: aktiv "dnssec-failed.org" # kaputt -> erwartet: fail "maier3000.de" # signiert -> erwartet: aktiv "maierch.de" # signiert -> erwartet: aktiv "maierchr.de" # signiert -> erwartet: aktiv "citeq.de" # unsigniert -> erwartet: inaktiv ) # Referenzdomains fuer den Selbsttest $SelfBadDomain = "dnssec-failed.org" # bewusst falsch signiert (Verisign) $SelfGoodDomain = "isc.org" # korrekt signiert # ------------------------------------------------------------------ # Ab hier nichts mehr aendern # ------------------------------------------------------------------ if (-not $Domains -or $Domains.Count -eq 0) { $Domains = $DefaultDomains } # Cmdlet vorhanden? if (-not (Get-Command Resolve-DnsName -ErrorAction SilentlyContinue)) { Write-Error "Resolve-DnsName nicht gefunden. Benoetigt Windows PowerShell 5.1+ mit dem Modul DnsClient (Windows)." exit 2 } # Eine DNSSEC-fuehrende Abfrage; gibt die Records zurueck oder wirft. function Invoke-DnsQuery { param( [string] $Name, [string] $Type, [switch] $Cd # -DnssecCd statt -DnssecOk (checking disabled) ) $common = @{ Name = $Name Type = $Type Server = $Resolver QuickTimeout = $true DnsOnly = $true ErrorAction = 'Stop' } if ($Cd) { Resolve-DnsName @common -DnssecCd } else { Resolve-DnsName @common -DnssecOk } } # Kernpruefung: liefert 'aktiv' | 'inaktiv' | 'fail' function Test-Domain { param([string] $Domain) try { $ans = Invoke-DnsQuery -Name $Domain -Type $QType } catch { # Fehler (SERVFAIL / NXDOMAIN / Timeout). Gegenprobe mit +cd: # kommt MIT checking-disabled eine Antwort, lag es an der Validierung. try { Invoke-DnsQuery -Name $Domain -Type $QType -Cd | Out-Null; return 'fail' } catch { return 'fail' } } # Antwort erhalten -> signiert, wenn RRSIG-Records dabei sind $hasRRSIG = @($ans | Where-Object { $_.Type -eq 'RRSIG' }).Count -gt 0 if ($hasRRSIG) { return 'aktiv' } else { return 'inaktiv' } } # Selbsttest: validiert der Resolver ueberhaupt? # Rueckgabe (ueber die Pipeline): 0 = validiert, 1 = nein, 2 = unklar/Netzfehler function Invoke-SelfCheck { # 1) kaputte Domain: OHNE cd muss sie scheitern $badFails = $false try { Invoke-DnsQuery -Name $SelfBadDomain -Type A | Out-Null; $badFails = $false } catch { $badFails = $true } # 2) kaputte Domain MIT cd sollte aufloesbar sein $cdOk = $false try { Invoke-DnsQuery -Name $SelfBadDomain -Type A -Cd | Out-Null; $cdOk = $true } catch { $cdOk = $false } # 3) gute Domain muss aufloesen und signiert sein $goodOk = $false; $goodSigned = $false try { $g = Invoke-DnsQuery -Name $SelfGoodDomain -Type A $goodOk = $true $goodSigned = @($g | Where-Object { $_.Type -eq 'RRSIG' }).Count -gt 0 } catch { $goodOk = $false } # Erreichbarkeitsproblem? (nichts geht durch) if (-not $cdOk -and -not $goodOk) { Write-Host "Resolver-Selbsttest: " -NoNewline Write-Host "UNKLAR" -ForegroundColor Yellow -NoNewline Write-Host " (Resolver $Resolver nicht erreichbar?)" return 2 } if ($badFails -and $cdOk -and $goodOk -and $goodSigned) { Write-Host "Resolver-Selbsttest: " -NoNewline Write-Host "VALIDIERT DNSSEC" -ForegroundColor Green -NoNewline Write-Host " ($SelfBadDomain scheitert, $SelfGoodDomain signiert+aufgeloest)" return 0 } else { Write-Host "Resolver-Selbsttest: " -NoNewline Write-Host "KEINE VALIDIERUNG" -ForegroundColor Red -NoNewline Write-Host (" (bad_fails={0}, cd_ok={1}, good_ok={2}, good_signed={3})" -f ` $badFails, $cdOk, $goodOk, $goodSigned) return 1 } } # ------------------------------------------------------------------ # Ausgabe # ------------------------------------------------------------------ $stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Nur Selbsttest gewuenscht? if ($SelfCheck) { Write-Host "Resolver: $Resolver ($stamp)" $rc = Invoke-SelfCheck exit $rc } Write-Host "DNSSEC-Pruefung ueber Resolver: $Resolver ($stamp)" # Zuerst pruefen, ob der Resolver validiert - sonst sind die Ergebnisse # darunter nur eingeschraenkt aussagekraeftig. $scRc = Invoke-SelfCheck if ($scRc -ne 0) { Write-Host "Hinweis: " -ForegroundColor Yellow -NoNewline Write-Host 'Resolver validiert nicht/unklar - "aktiv/fail" unten sind nur eingeschraenkt verlaesslich.' } Write-Host "" "{0,-40} {1}" -f "DOMAIN", "STATUS" | Write-Host "{0,-40} {1}" -f ("-" * 40), "--------" | Write-Host $exit = 0 foreach ($d in $Domains) { $st = Test-Domain -Domain $d switch ($st) { 'aktiv' { $col = 'Green' } 'inaktiv' { $col = 'Yellow' } default { $col = 'Red'; $exit = 1 } } Write-Host ("{0,-40} " -f $d) -NoNewline Write-Host $st -ForegroundColor $col } # Exit-Code: 0 = kein fail, 1 = mindestens ein fail (fuer Monitoring/Scheduled Task) exit $exit