Powershell : liste des entrées DNS sans reverse

Ce script permet d'afficher la liste des enregistrements DNS "A" d'une zone qui n'ont pas d'enregistrements reverse DNS (PTR). Après affichage des enregistrements, un export CSV est réalisé permettant une exploitation plus simple dans Excel ou simplement une injection dans un autre script.

param([Parameter(Mandatory=$true)][string] $Zone, [Parameter(Mandatory=$true)][string] $DNSHost)

$records = Get-DnsServerResourceRecord -Computer $dnshost -ZoneName $zone -RRtype "A"
$output = @()
foreach($record in $records){
	$ipStr = $record.RecordData.IPv4Address.ToString()
	$ipB1 = $ipStr.SubString(0,$ipStr.IndexOf("."))
	$ipstr = $ipstr.SubString(($ipB1.Length)+1,($ipstr.Length-$ipB1.Length)-1)
	$ipB2 = $ipStr.SubString(0,$ipStr.IndexOf("."))
	$ipstr = $ipstr.SubString(($ipB2.Length)+1,($ipstr.Length-$ipB2.Length)-1)
	$ipB3 = $ipStr.SubString(0,$ipStr.IndexOf("."))
	$ipstr = $ipstr.SubString(($ipB3.Length)+1,($ipstr.Length-$ipB3.Length)-1)
	$ipB4 = $ipStr.Substring(0,$ipStr.Length)
	$zoneptr = $record.RecordData.IPv4Address.ToString().SubString(0,$ipB1.Length)+".in-addr.arpa"
	if($ipB1 -ne $lastzone) { $recptr = Get-DnsServerResourceRecord -Computer $dnshost -ZoneName $zoneptr }
    $lastzone = $ipB1
	$ipptr = $ipB4+"."+$ipB3+"."+$ipB2
	if(($recptr | Where-Object { $_.HostName -like $ipptr }) -eq $null) { 
		Write-Host $record.HostName";"$record.RecordData.IPV4Address 
		$noptr = New-Object PSCustomObject
		$noptr | Add-Member -Name "Hostname" -Value $record.HostName -MemberType NoteProperty
		$noptr | Add-Member -Name "IPV4Address" -Value $record.RecordData.IPV4Address -MemberType NoteProperty
		$output+=$noptr
		}
}
$output | Export-CSV DNSnoPTR.csv -Encoding UTF8

Le script prend en paramètre ZoneName le nom de la zone DNS que l'on souhaite scanner et DnsHost le nom du serveur DNS qui renverra les enregistrements. Le script pourra donc être appelé de cette manière :

.\win_dnsnoptr.ps1 -Zone intra.dundermifflin.inc -DNSHost dc01

Comme toujours, le script avec quelques commentaires est disponible en téléchargement.

Powershell : suppression d'enregistrements DNS depuis un import CSV

Ce snippet permet de supprimer les enregistrements DNS à partir d'une liste au format CSV passée en paramètre.

Le script sera appelé de cette manière :

.\win_dns-deletion.ps1 -zone superdomaine.local -csv exportdns.csv

Seuls les enregistrements de type A sont supprimés par ce code ; le paramètre peut se modifier pour cibler un autre type. Par défaut, la commande demande confirmation avant suppression ; le paramètre -Force permet de passer outre cette confirmation. Attention au moment d'exécuter le script.

param([string]$zone, [string]$csv)
 $records = Import-CSV $csv
 foreach($record in $records){
     Remove-DnsServerResourceRecord -ZoneName $zone -RRType "A" -Name $record.Name -Force
 }

Powershell : harmonisation de la configuration DNS

Afin d'harmoniser la configuration DNS sur des serveurs situés sur différents sites géographiques, j'ai développé un script Powershell lié à une GPO qui l'exécute au démarrage.

Ce script récupère grâce au nom du serveur son emplacement et applique en fonction de ce dernier les bonnes adresses IP. Naturellement, il faudra adapter l'extraction de l'emplacement dans le nom de la machine en fonction de l'environnement sur lequel le script sera déployé ; de plus, le domaine sur lequel la carte est connectée sert d'identification de la carte réseau employée pour la résolution DNS.

$location = (hostname).Substring(2,3)
switch($location){
"PAR" { $dnslist = '("192.168.1.1","192.168.1.2","192.168.2.1")' }
"BXL" { $dnslist = '("192.168.2.1","192.168.2.2","192.168.1.1")' }
"BER" { $dnslist = '("192.168.3.1","192.168.3.2","192.168.2.1")' }
"LDN" { $dnslist = '("192.168.4.1","192.168.4.2","192.168.3.1")' }
"NYC" { $dnslist = '("192.168.5.1","192.168.1.1","192.168.4.1")' }
}
$cards = Get-NetIPConfiguration
foreach($card in $cards){
if($card.NetProfile.Name -eq "dundermifflin.local") { $index = $card.InterfaceIndex }
}

$query = "Set-DnsClientServerAddress -InterfaceIndex $index -ServerAddresses $dnslist"
Invoke-Expression $query

Ce snippet fonctionne si par exemple mes serveurs ont une nomenclature de nommage comme celle-ci : <OS><Environnement><Emplacement><Rôle><ID>, qui pourrait donner par exemple pour un contrôleur de domaine de production WPLDNDC01 ou un serveur PostgreSQL de recette LRBXLPG03.

Powershell : listing d'enregistrements DNS

J'ai développé un (plutôt deux, à vrai dire) script(s) Powershell permettant de remplacer la fonction de filtre présente sur la console DNS. En effet, celle-ci est un peu pénible à utiliser car il faut attendre que toute la zone soit chargée dans la console si le filtre n'est pas encore actif, puis il faut rafraîchir... et il est persistant après fermeture, ce qui fait qu'il faut réinitialiser le filtre et actualiser lorsqu'on souhaite revenir à une vision d'ensemble.

A l'exécution, le script demande le nom ou l'IP du serveur DNS à interroger, ainsi que la chaîne de caractères à trouver dans le nom de l'enregistrement. Le joker * est utilisable, ce qui permet à la fois de rechercher une expression ou une chaîne stricte.

La version basique du script renvoie ses résultats dans la console avec uniquement le nom de l'enregistrement :

Write-Host "=========================================="
Write-Host "DNS records listing script - Basic Version"
Write-Host "=========================================="
$dnsnode = Read-Host "DNS Server to query"
$lfseq = Read-Host "Character sequence to look for ('*' tokens accepted)"
Write-Host "Connecting to DNS Server and retrieving DNS zones"
$dnszones = Get-DNSServerZone -ComputerName $dnsnode | Where-Object {$_.IsReverseLookupZone -eq $false}
foreach($dnszone in $dnszones){
Write-Host "Zone currently parsed:" $dnszone.ZoneName
$dnsrecords = Get-DnsServerResourceRecord -ComputerName $dnsnode -ZoneName $dnszone.ZoneName | Where-Object {$_.HostName -like "$lfseq"} | ft HostName
if($dnsrecords.length -gt 0) { $dnsrecords }
else { Write-Host "No matching records found." }
Write-Host "`r"
}
Write-Host "Parsing over."
Write-Host "Bye."

La version améliorée renvoie les résultats dans la console, mais génère un fichier CSV offrant plus d'informations (type d'enregistrement et données de l'enregistrement) et effectue une suppression des doublons : nécessaire car la commande Powershell peut renvoyer plusieurs fois le même enregistrement si il est dans une sous-zone. Par exemple, en considérant la zone infra.local, si un enregistrement s'appelle sql dans la sous-zone prod, il apparaîtra alors deux fois : une fois en tant que sql.prod et une fois en tant que sql.prod.infra.local.

Write-Host "============================================="
Write-Host "DNS records listing script - Enhanced Version"
Write-Host "============================================="
$dnsnode = Read-Host "DNS Server to query"
$lfseq = Read-Host "Character sequence to look for ('*' tokens accepted)"
$today = Get-Date -f yyyyMMdd
$path = "dns-$today.csv"
$csvheader = "Hostname,Zone,RecordType,RecordData"
Add-Content -Value $csvheader -Path $path
Write-Host "Connecting to DNS Server and retrieving DNS zones"
$dnszones = Get-DNSServerZone -ComputerName $dnsnode | Where-Object {$_.IsReverseLookupZone -eq $false}
foreach($dnszone in $dnszones){
Write-Host "Zone currently parsed:" $dnszone.ZoneName
$dnsrecords = Get-DnsServerResourceRecord -ComputerName $dnsnode -ZoneName $dnszone.ZoneName | Where-Object {$_.HostName -like "$lfseq"}
if($dnsrecords.length -gt 0){
foreach($dnsrecord in $dnsrecords){
Write-Host "Record: "$dnsrecord.Hostname
switch($dnsrecord.RecordType){
"A" {$recorddata = $dnsrecord.RecordData.IPv4Address.IpAddressToString}
"CNAME" {$recorddata = $dnsrecord.RecordData.HostNameAlias}
}
if($dnsrecord.HostName.SubString($dnsrecord.HostName.Length-$dnszone.ZoneName.Length,$dnszone.ZoneName.Length) -ne $dnszone.ZoneName) {
$row = $dnsrecord.Hostname+","+$dnszone.ZoneName+","+$dnsrecord.RecordType+","+$recorddata
Add-Content -Value $row -Path $path
}
}
Write-Host "DNS records found:"$dnsrecords.length
}
else { Write-Host "No matching records found." }
Write-Host "`r"
}
Write-Host "Parsing over, cleaned duplicates, hence the difference between the number of lines in the CSV file and the number displayed in console. Please find the output CSV file named $path in $pwd."
Write-Host "Bye."
explorer $pwd