6b190a2e2f
Skript und README hinzugefuegt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
199 lines
5.4 KiB
PowerShell
199 lines
5.4 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
dig-artiger DNS-Lookup fuer Windows PowerShell, basierend auf Resolve-DnsName.
|
|
|
|
.DESCRIPTION
|
|
Bildet die wichtigsten dig-Aufrufe nach, damit sich unter Windows die gleiche
|
|
Syntax wie mit dig unter Linux verwenden laesst. Argumente koennen wie bei dig
|
|
in beliebiger Reihenfolge stehen.
|
|
|
|
.PARAMETER Args
|
|
Freie dig-artige Argumente:
|
|
name abzufragender Name (z.B. example.com)
|
|
type Record-Typ (A, AAAA, MX, TXT, NS, CNAME, SOA, SRV, PTR, ...)
|
|
@server zu verwendender DNS-Server (z.B. @8.8.8.8)
|
|
-x <ip> Reverse-Lookup (PTR) fuer eine IPv4-/IPv6-Adresse
|
|
+short nur die reinen Antwortwerte ausgeben
|
|
|
|
.EXAMPLE
|
|
.\dig.ps1 example.com
|
|
.\dig.ps1 MX example.com
|
|
.\dig.ps1 example.com MX @1.1.1.1
|
|
.\dig.ps1 -x 8.8.8.8
|
|
.\dig.ps1 AAAA example.com +short
|
|
#>
|
|
|
|
# Alle Argumente einsammeln (bewusst als freies Array, dig-Stil).
|
|
$rest = $args
|
|
|
|
$name = $null
|
|
$type = $null
|
|
$server = $null
|
|
$short = $false
|
|
$reverse = $false
|
|
|
|
# Bekannte DNS-Record-Typen, die Resolve-DnsName unterstuetzt.
|
|
$knownTypes = @(
|
|
'A','AAAA','A_AAAA','CNAME','MX','NS','PTR','SOA','SRV','TXT',
|
|
'CAA','DNSKEY','DS','NAPTR','NSEC','NSEC3','RRSIG','ANY','ALL'
|
|
)
|
|
|
|
# Argumente parsen (Reihenfolge egal).
|
|
for ($i = 0; $i -lt $rest.Count; $i++) {
|
|
$arg = [string]$rest[$i]
|
|
|
|
if ($arg -eq '-x') {
|
|
$reverse = $true
|
|
# naechstes Argument ist die IP-Adresse
|
|
if ($i + 1 -lt $rest.Count) {
|
|
$name = [string]$rest[$i + 1]
|
|
$i++
|
|
}
|
|
continue
|
|
}
|
|
|
|
if ($arg.StartsWith('@')) {
|
|
$server = $arg.Substring(1)
|
|
continue
|
|
}
|
|
|
|
if ($arg -eq '+short') {
|
|
$short = $true
|
|
continue
|
|
}
|
|
|
|
if ($arg.StartsWith('+')) {
|
|
# weitere +optionen aktuell ignorieren
|
|
continue
|
|
}
|
|
|
|
if ($knownTypes -contains $arg.ToUpper()) {
|
|
$type = $arg.ToUpper()
|
|
continue
|
|
}
|
|
|
|
# alles andere ist der Name
|
|
if (-not $name) {
|
|
$name = $arg
|
|
}
|
|
}
|
|
|
|
if (-not $name) {
|
|
Write-Host "Verwendung: dig.ps1 [type] name [@server] [+short] | dig.ps1 -x <ip> [+short]"
|
|
exit 1
|
|
}
|
|
|
|
# Reverse-Lookup: IP in .in-addr.arpa / .ip6.arpa umwandeln.
|
|
function ConvertTo-PtrName([string]$ip) {
|
|
$parsed = $null
|
|
if (-not [System.Net.IPAddress]::TryParse($ip, [ref]$parsed)) {
|
|
return $ip # kein gueltiges IP-Literal, unveraendert zurueck
|
|
}
|
|
|
|
if ($parsed.AddressFamily -eq 'InterNetwork') {
|
|
# IPv4: Oktette umdrehen
|
|
$octets = $ip.Split('.')
|
|
[array]::Reverse($octets)
|
|
return ($octets -join '.') + '.in-addr.arpa'
|
|
}
|
|
else {
|
|
# IPv6: vollstaendige Nibble-Darstellung, umgedreht
|
|
$bytes = $parsed.GetAddressBytes()
|
|
$nibbles = foreach ($b in $bytes) {
|
|
'{0:x2}' -f $b
|
|
}
|
|
$hex = ($nibbles -join '')
|
|
$chars = $hex.ToCharArray()
|
|
[array]::Reverse($chars)
|
|
return (($chars -join '.') + '.ip6.arpa')
|
|
}
|
|
}
|
|
|
|
if ($reverse) {
|
|
$name = ConvertTo-PtrName $name
|
|
$type = 'PTR'
|
|
}
|
|
|
|
if (-not $type) {
|
|
$type = 'A'
|
|
}
|
|
|
|
# Resolve-DnsName-Parameter zusammenbauen.
|
|
$params = @{
|
|
Name = $name
|
|
Type = $type
|
|
ErrorAction = 'Stop'
|
|
}
|
|
if ($server) {
|
|
$params['Server'] = $server
|
|
}
|
|
|
|
try {
|
|
$records = Resolve-DnsName @params
|
|
}
|
|
catch {
|
|
Write-Host ";; Fehler bei der Aufloesung von '$name' ($type): $($_.Exception.Message)"
|
|
exit 1
|
|
}
|
|
|
|
# Nur echte Antwort-Records (keine Query-Hinweiszeilen).
|
|
$answers = $records | Where-Object { $_.Section -ne 'Question' }
|
|
|
|
# Wert eines Records typgerecht als String formatieren.
|
|
function Get-RecordData($r) {
|
|
switch -Wildcard ($r.Type) {
|
|
'A' { return $r.IPAddress }
|
|
'AAAA' { return $r.IPAddress }
|
|
'CNAME' { return $r.NameHost }
|
|
'NS' { return $r.NameHost }
|
|
'PTR' { return $r.NameHost }
|
|
'MX' { return "$($r.Preference) $($r.NameExchange)" }
|
|
'SOA' { return "$($r.PrimaryServer) $($r.NameAdministrator) $($r.SerialNumber) $($r.TimeToZoneRefresh) $($r.TimeToZoneFailureRetry) $($r.TimeToExpiration) $($r.DefaultTTL)" }
|
|
'SRV' { return "$($r.Priority) $($r.Weight) $($r.Port) $($r.NameTarget)" }
|
|
'TXT' { return '"' + ($r.Strings -join '" "') + '"' }
|
|
'CAA' { return "$($r.Flags) $($r.Tag) `"$($r.Value)`"" }
|
|
default {
|
|
# Fallback: sinnvolles Feld suchen
|
|
foreach ($p in 'NameHost','IPAddress','NameTarget','Strings') {
|
|
if ($r.PSObject.Properties[$p] -and $r.$p) {
|
|
return ($r.$p -join ' ')
|
|
}
|
|
}
|
|
return ($r | Out-String).Trim()
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($short) {
|
|
# +short: nur die Werte, eine pro Zeile.
|
|
foreach ($r in $answers) {
|
|
Get-RecordData $r
|
|
}
|
|
exit 0
|
|
}
|
|
|
|
# dig-artige Ausgabe.
|
|
$srvText = if ($server) { $server } else { '(System-Resolver)' }
|
|
|
|
Write-Host ""
|
|
Write-Host "; <<>> dig.ps1 <<>> $name $type" -ForegroundColor DarkGray
|
|
Write-Host ";; Server: $srvText"
|
|
Write-Host ""
|
|
Write-Host ";; QUESTION SECTION:"
|
|
Write-Host (";{0}`t`tIN`t{1}" -f $name, $type)
|
|
Write-Host ""
|
|
|
|
if ($answers) {
|
|
Write-Host ";; ANSWER SECTION:"
|
|
foreach ($r in $answers) {
|
|
$ttl = if ($r.PSObject.Properties['TTL']) { $r.TTL } else { 0 }
|
|
$data = Get-RecordData $r
|
|
Write-Host ("{0}`t{1}`tIN`t{2}`t{3}" -f $r.Name, $ttl, $r.Type, $data)
|
|
}
|
|
Write-Host ""
|
|
}
|
|
else {
|
|
Write-Host ";; keine Antworten (ANSWER SECTION leer)"
|
|
Write-Host ""
|
|
}
|