dnssec_check: DNSSEC-Status-Pruefung fuer Bash und PowerShell

Neue Skripte dnssec_check (Bash, dig) und dnssec_check.ps1 (PowerShell,
Resolve-DnsName): pruefen fuer hinterlegbare Domains den DNSSEC-Status
(aktiv/inaktiv/fail) inkl. Resolver-Selbsttest. README erweitert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
maierch
2026-07-10 19:13:36 +02:00
parent a2482df6af
commit 64138831a8
3 changed files with 499 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
#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