dig.ps1: dig-artiger DNS-Lookup fuer PowerShell
Skript und README hinzugefuegt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
<#
|
||||
.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 ""
|
||||
}
|
||||
Reference in New Issue
Block a user