PowerShell ile DNS Sorgulama ve Yönetimi

DNS yönetimi, sistem yöneticilerinin günlük hayatında en sık karşılaştığı konulardan biri. Bir servis çalışmıyor, kullanıcılar bağlanamıyor, yeni bir sunucu devreye aldınız – hepsinin temelinde DNS var. PowerShell, Windows ortamında DNS sorgulama ve yönetimi için inanılmaz güçlü araçlar sunuyor. Hem hızlı troubleshooting hem de otomasyon senaryoları için bu araçları iyi bilmek, sizi ortalama bir sysadmin’den ayıran şeylerden biri.

Bu yazıda temel DNS sorgularından başlayıp, DNS sunucu yönetimine, toplu işlemlere ve gerçek dünya senaryolarına kadar her şeyi ele alacağız.

Temel DNS Sorgulama: Resolve-DnsName

PowerShell’de DNS sorgulamanın ana komutu Resolve-DnsName‘dir. Eski okul sysadminlerin nslookup’tan bildiği her şeyi yapıyor, üstüne de PowerShell’in tüm gücünü getiriyor.

# Basit A kaydı sorgusu
Resolve-DnsName -Name "www.example.com"

# Belirli bir DNS sunucusuna sorgu gönder
Resolve-DnsName -Name "www.example.com" -Server "8.8.8.8"

# Farklı kayıt tiplerini sorgula
Resolve-DnsName -Name "example.com" -Type MX
Resolve-DnsName -Name "example.com" -Type TXT
Resolve-DnsName -Name "example.com" -Type NS
Resolve-DnsName -Name "example.com" -Type SOA

# Ters DNS sorgusu (PTR)
Resolve-DnsName -Name "8.8.8.8" -Type PTR

Komutun temel parametreleri şunlar:

  • -Name: Sorgulanacak hostname veya IP adresi
  • -Type: DNS kayıt tipi (A, AAAA, MX, TXT, NS, SOA, PTR, CNAME, SRV)
  • -Server: Kullanılacak DNS sunucusu IP’si veya hostname’i
  • -DnsOnly: Yalnızca DNS üzerinden sorgula, hosts dosyasını yok say
  • -NoHostsFile: Hosts dosyasını atlayarak direkt DNS’e git
  • -TcpOnly: UDP yerine TCP kullanarak sorgula (büyük yanıtlar için)

Şimdi biraz daha işe yarar bir senaryo düşünelim. Sabah işe geldiniz, bir uygulama ekibi “bizim servis çalışmıyor” diye üstünüze çullanıyor. İlk adım DNS’i kontrol etmek:

# Kapsamlı DNS troubleshooting sorgusu
$hostname = "app.sirket.local"

Write-Host "=== DNS Troubleshooting: $hostname ===" -ForegroundColor Cyan

# Lokal DNS sunucusundan sorgula
Write-Host "`n[Lokal DNS]" -ForegroundColor Yellow
Resolve-DnsName -Name $hostname -ErrorAction SilentlyContinue | 
    Select-Object Name, Type, IPAddress, NameHost

# Google DNS ile karşılaştır
Write-Host "`n[Google DNS - 8.8.8.8]" -ForegroundColor Yellow
Resolve-DnsName -Name $hostname -Server "8.8.8.8" -ErrorAction SilentlyContinue | 
    Select-Object Name, Type, IPAddress, NameHost

# Cloudflare DNS ile karşılaştır
Write-Host "`n[Cloudflare DNS - 1.1.1.1]" -ForegroundColor Yellow
Resolve-DnsName -Name $hostname -Server "1.1.1.1" -ErrorAction SilentlyContinue | 
    Select-Object Name, Type, IPAddress, NameHost

Bu script birkaç farklı DNS sunucusundan aynı sorguyu yapıyor. Eğer lokal DNS farklı bir şey dönüyorsa, orada sorun var demektir. Basit ama hayat kurtarıcı.

DNS Kayıt Tiplerini Anlamak ve Sorgulamak

Her kayıt tipinin farklı kullanım senaryosu var. Bunları tek tek ele alalım.

Mail Sunucusu (MX) Kayıtları

E-posta problemi mi var? MX kayıtlarından başlayın:

# MX kayıtlarını öncelik sırasına göre listele
$domain = "example.com"
$mxRecords = Resolve-DnsName -Name $domain -Type MX | 
    Sort-Object Preference

foreach ($record in $mxRecords) {
    Write-Host "Öncelik: $($record.Preference) - Sunucu: $($record.NameExchange)"
    
    # Her MX sunucusunun IP'sini de çöz
    $ip = Resolve-DnsName -Name $record.NameExchange -Type A -ErrorAction SilentlyContinue
    if ($ip) {
        Write-Host "  IP: $($ip.IPAddress)"
    }
}

SPF ve DKIM Kontrolü

E-posta güvenliği için TXT kayıtlarını düzenli kontrol etmek gerekiyor:

# SPF kaydını kontrol et
$domain = "example.com"
$txtRecords = Resolve-DnsName -Name $domain -Type TXT

foreach ($record in $txtRecords) {
    if ($record.Strings -like "*v=spf1*") {
        Write-Host "SPF Kaydı Bulundu:" -ForegroundColor Green
        Write-Host $record.Strings
    }
    if ($record.Strings -like "*v=DMARC1*") {
        Write-Host "DMARC Kaydı Bulundu:" -ForegroundColor Green
        Write-Host $record.Strings
    }
}

# DKIM için selector sorgula
$selector = "default"
Resolve-DnsName -Name "$selector._domainkey.$domain" -Type TXT -ErrorAction SilentlyContinue

Windows DNS Sunucusu Yönetimi: DnsServer Modülü

Eğer bir Windows DNS sunucusu yönetiyorsanız, DnsServer modülü tam size göre. Bu modül RSAT ile birlikte geliyor ve DNS sunucusunu uzaktan yönetmenizi sağlıyor.

Önce modülün yüklü olup olmadığını kontrol edin:

# Modülü kontrol et ve yükle
if (-not (Get-Module -ListAvailable -Name DnsServer)) {
    Write-Host "DnsServer modülü bulunamadı. RSAT yükleniyor..." -ForegroundColor Yellow
    Add-WindowsFeature RSAT-DNS-Server
}

Import-Module DnsServer

# DNS sunucusundaki zone'ları listele
Get-DnsServerZone -ComputerName "dns-sunucu01"

# Belirli bir zone'daki tüm kayıtları getir
Get-DnsServerResourceRecord -ZoneName "sirket.local" -ComputerName "dns-sunucu01"

# Sadece A kayıtlarını getir
Get-DnsServerResourceRecord -ZoneName "sirket.local" -RRType A -ComputerName "dns-sunucu01"

Kayıt Ekleme, Güncelleme ve Silme

Günlük operasyonların belki de en sık yapılan kısmı DNS kayıtlarını yönetmek:

# Yeni A kaydı ekle
Add-DnsServerResourceRecordA `
    -ZoneName "sirket.local" `
    -Name "yeni-sunucu" `
    -IPv4Address "192.168.1.50" `
    -TimeToLive 01:00:00 `
    -ComputerName "dns-sunucu01"

# CNAME kaydı ekle
Add-DnsServerResourceRecordCName `
    -ZoneName "sirket.local" `
    -Name "app" `
    -HostNameAlias "yeni-sunucu.sirket.local" `
    -ComputerName "dns-sunucu01"

# PTR kaydı ekle (ters DNS)
Add-DnsServerResourceRecordPtr `
    -ZoneName "1.168.192.in-addr.arpa" `
    -Name "50" `
    -PtrDomainName "yeni-sunucu.sirket.local" `
    -ComputerName "dns-sunucu01"

# Kaydı sil
Remove-DnsServerResourceRecord `
    -ZoneName "sirket.local" `
    -Name "eski-sunucu" `
    -RRType A `
    -RecordData "192.168.1.30" `
    -ComputerName "dns-sunucu01" `
    -Force

Gerçek Dünya Senaryosu 1: Toplu Sunucu DNS Kaydı Oluşturma

Yeni bir proje devreye alınıyor ve 20 yeni sanal makine oluşturuldu. Hepsinin DNS kaydını tek tek girmek yerine, bir CSV dosyasından okuyarak otomatize edelim:

# sunucular.csv formatı:
# Hostname,IP,Tip
# web-01,192.168.10.11,A
# db-01,192.168.10.20,A
# app-proxy,web-01.sirket.local,CNAME

$csvDosyasi = "C:Scriptssunucular.csv"
$zone = "sirket.local"
$dnsSunucu = "dns-sunucu01"
$logDosyasi = "C:Scriptsdns-log-$(Get-Date -Format 'yyyyMMdd').txt"

$sunucular = Import-Csv -Path $csvDosyasi
$basarili = 0
$basarisiz = 0

foreach ($sunucu in $sunucular) {
    try {
        # Kayıt zaten var mı kontrol et
        $mevcutKayit = Get-DnsServerResourceRecord `
            -ZoneName $zone `
            -Name $sunucu.Hostname `
            -ComputerName $dnsSunucu `
            -ErrorAction SilentlyContinue

        if ($mevcutKayit) {
            Write-Host "UYARI: $($sunucu.Hostname) zaten mevcut, atlanıyor." -ForegroundColor Yellow
            Add-Content $logDosyasi "$(Get-Date) - UYARI: $($sunucu.Hostname) zaten mevcut"
            continue
        }

        if ($sunucu.Tip -eq "A") {
            Add-DnsServerResourceRecordA `
                -ZoneName $zone `
                -Name $sunucu.Hostname `
                -IPv4Address $sunucu.IP `
                -ComputerName $dnsSunucu
        }
        elseif ($sunucu.Tip -eq "CNAME") {
            Add-DnsServerResourceRecordCName `
                -ZoneName $zone `
                -Name $sunucu.Hostname `
                -HostNameAlias $sunucu.IP `
                -ComputerName $dnsSunucu
        }

        Write-Host "BASARILI: $($sunucu.Hostname) eklendi" -ForegroundColor Green
        Add-Content $logDosyasi "$(Get-Date) - BASARILI: $($sunucu.Hostname) eklendi"
        $basarili++
    }
    catch {
        Write-Host "HATA: $($sunucu.Hostname) eklenemedi - $($_.Exception.Message)" -ForegroundColor Red
        Add-Content $logDosyasi "$(Get-Date) - HATA: $($sunucu.Hostname) - $($_.Exception.Message)"
        $basarisiz++
    }
}

Write-Host "`nSonuç: $basarili başarılı, $basarisiz başarısız" -ForegroundColor Cyan

Gerçek Dünya Senaryosu 2: DNS Tutarlılık Kontrolü

Birden fazla DNS sunucunuz varsa, zone transferlerinin düzgün çalışıp çalışmadığını düzenli kontrol etmek önemli. Bu script, primary ve secondary sunucular arasındaki kayıt farklılıklarını bulur:

# DNS tutarlılık kontrolü - Primary vs Secondary
$primaryDns = "dns-primary01"
$secondaryDns = "dns-secondary01"
$zone = "sirket.local"

Write-Host "DNS Tutarlılık Kontrolü Başlıyor..." -ForegroundColor Cyan

# Primary'deki kayıtları al
$primaryKayitlar = Get-DnsServerResourceRecord `
    -ZoneName $zone `
    -ComputerName $primaryDns | 
    Where-Object { $_.RecordType -in @("A", "CNAME", "MX", "TXT") }

# Secondary'deki kayıtları al
$secondaryKayitlar = Get-DnsServerResourceRecord `
    -ZoneName $zone `
    -ComputerName $secondaryDns | 
    Where-Object { $_.RecordType -in @("A", "CNAME", "MX", "TXT") }

# Primary'de olup Secondary'de olmayan kayıtlar
$primaryde_olan = $primaryKayitlar | 
    Where-Object { $_.HostName -notin $secondaryKayitlar.HostName }

if ($primaryde_olan) {
    Write-Host "`nSadece Primary'de olan kayıtlar:" -ForegroundColor Red
    $primaryde_olan | Select-Object HostName, RecordType | Format-List
} else {
    Write-Host "`nTüm kayıtlar Secondary'de mevcut." -ForegroundColor Green
}

# SOA serial numaralarını karşılaştır
$primarySOA = Get-DnsServerResourceRecord -ZoneName $zone -ComputerName $primaryDns -RRType SOA
$secondarySOA = Get-DnsServerResourceRecord -ZoneName $zone -ComputerName $secondaryDns -RRType SOA

Write-Host "`nSOA Kontrolü:" -ForegroundColor Yellow
Write-Host "Primary Serial: $($primarySOA.RecordData.SerialNumber)"
Write-Host "Secondary Serial: $($secondarySOA.RecordData.SerialNumber)"

if ($primarySOA.RecordData.SerialNumber -ne $secondarySOA.RecordData.SerialNumber) {
    Write-Host "UYARI: Serial numaraları farklı! Zone transfer sorunu olabilir." -ForegroundColor Red
}

DNS Cache Yönetimi

DNS cache sorunları troubleshooting’de sıkça karşılaşılan bir durum. PowerShell ile hem istemci hem de sunucu tarafında cache yönetimi yapabilirsiniz:

# İstemci DNS cache'ini görüntüle
Get-DnsClientCache

# Belirli bir kayıt için cache kontrolü
Get-DnsClientCache | Where-Object { $_.Entry -like "*example*" }

# İstemci DNS cache'ini temizle
Clear-DnsClientCache
Write-Host "DNS cache temizlendi." -ForegroundColor Green

# DNS sunucusundaki cache'i yönet (sunucu tarafı)
# Sunucudaki tüm cache kayıtlarını görüntüle
Get-DnsServerCache -ComputerName "dns-sunucu01"

# Sunucu cache'ini temizle
Clear-DnsServerCache -ComputerName "dns-sunucu01" -Force
Write-Host "Sunucu DNS cache'i temizlendi." -ForegroundColor Green

# Belirli bir kaydı cache'den sil
Clear-DnsServerCache -ComputerName "dns-sunucu01" -Force

DNS Zone Yönetimi

Zone oluşturma ve yapılandırma işlemleri de PowerShell ile kolayca yapılabiliyor:

# Yeni primary zone oluştur
Add-DnsServerPrimaryZone `
    -Name "yeniprojekt.local" `
    -ReplicationScope "Forest" `
    -DynamicUpdate Secure `
    -ComputerName "dns-sunucu01"

# Secondary zone oluştur
Add-DnsServerSecondaryZone `
    -Name "partner.local" `
    -ZoneFile "partner.local.dns" `
    -MasterServers "10.0.0.1" `
    -ComputerName "dns-sunucu01"

# Stub zone oluştur
Add-DnsServerStubZone `
    -Name "harici.local" `
    -MasterServers "172.16.0.1" `
    -ReplicationScope "Forest" `
    -ComputerName "dns-sunucu01"

# Zone özelliklerini görüntüle
Get-DnsServerZone -Name "sirket.local" -ComputerName "dns-sunucu01" | 
    Select-Object ZoneName, ZoneType, DynamicUpdate, ReplicationScope, IsDsIntegrated

# Zone'u sil (dikkatli kullanın!)
# Remove-DnsServerZone -Name "eskizone.local" -ComputerName "dns-sunucu01" -Force

Monitoring ve Raporlama

DNS sağlığını izlemek için düzenli çalışan bir script hazırlamak iyi bir pratik:

# DNS Sağlık Raporu
function Get-DnsHealthReport {
    param(
        [string[]]$DnsSunuculari = @("dns-sunucu01", "dns-sunucu02"),
        [string]$ZoneName = "sirket.local",
        [string]$RaporDosyasi = "C:Raporlardns-rapor-$(Get-Date -Format 'yyyyMMdd-HHmm').html"
    )

    $rapor = @()

    foreach ($sunucu in $DnsSunuculari) {
        $sunucuRapor = [PSCustomObject]@{
            Sunucu = $sunucu
            Durum = "Bilinmiyor"
            TotalKayit = 0
            AKayit = 0
            CNAMEKayit = 0
            SOASerial = 0
            ZoneDurumu = "Bilinmiyor"
        }

        try {
            # Zone bilgilerini al
            $zone = Get-DnsServerZone -Name $ZoneName -ComputerName $sunucu -ErrorAction Stop
            $sunucuRapor.ZoneDurumu = $zone.ZoneType

            # Kayıt sayılarını al
            $tumKayitlar = Get-DnsServerResourceRecord -ZoneName $ZoneName -ComputerName $sunucu
            $sunucuRapor.TotalKayit = $tumKayitlar.Count
            $sunucuRapor.AKayit = ($tumKayitlar | Where-Object RecordType -eq "A").Count
            $sunucuRapor.CNAMEKayit = ($tumKayitlar | Where-Object RecordType -eq "CNAME").Count

            # SOA serial
            $soa = $tumKayitlar | Where-Object RecordType -eq "SOA"
            $sunucuRapor.SOASerial = $soa.RecordData.SerialNumber

            $sunucuRapor.Durum = "OK"
            Write-Host "$sunucu - OK" -ForegroundColor Green
        }
        catch {
            $sunucuRapor.Durum = "HATA: $($_.Exception.Message)"
            Write-Host "$sunucu - HATA" -ForegroundColor Red
        }

        $rapor += $sunucuRapor
    }

    # Sonuçları göster
    $rapor | Format-List

    # CSV olarak kaydet
    $rapor | Export-Csv -Path ($RaporDosyasi -replace ".html$", ".csv") -NoTypeInformation -Encoding UTF8
    
    Write-Host "`nRapor kaydedildi." -ForegroundColor Cyan
    return $rapor
}

# Fonksiyonu çalıştır
Get-DnsHealthReport -DnsSunuculari @("dns-sunucu01", "dns-sunucu02") -ZoneName "sirket.local"

Forwarder Yönetimi

DNS forwarder’ları yönetmek de sık karşılaşılan bir görev:

# Mevcut forwarder'ları listele
Get-DnsServerForwarder -ComputerName "dns-sunucu01"

# Yeni forwarder ekle
Add-DnsServerForwarder -IPAddress "8.8.8.8" -ComputerName "dns-sunucu01"
Add-DnsServerForwarder -IPAddress "8.8.4.4" -ComputerName "dns-sunucu01"

# Forwarder sil
Remove-DnsServerForwarder -IPAddress "8.8.8.8" -ComputerName "dns-sunucu01" -Force

# Conditional forwarder ekle (belirli domain için farklı DNS kullan)
Add-DnsServerConditionalForwarderZone `
    -Name "partner-sirket.local" `
    -MasterServers "10.100.0.1", "10.100.0.2" `
    -ComputerName "dns-sunucu01"

# Tüm conditional forwarder'ları listele
Get-DnsServerZone -ComputerName "dns-sunucu01" | 
    Where-Object ZoneType -eq "Forwarder" | 
    Select-Object ZoneName, MasterServers

Karşılaşılan Yaygın Sorunlar ve Çözümleri

DNS yanıt vermiyor: Resolve-DnsName timeout veriyorsa önce network bağlantısını, sonra DNS servisinin çalışıp çalışmadığını kontrol edin. Test-NetConnection -ComputerName "dns-sunucu01" -Port 53 ile port kontrolü yapın.

Cache tutarsızlıkları: Özellikle IP değişikliklerinden sonra hem sunucu hem istemci cache’ini temizlemek gerekiyor. Bunu otomatize etmek için Clear-DnsClientCache komutunu GPO script olarak dağıtabilirsiniz.

Zone transfer hataları: Serial numaraları aynı ama kayıtlar farklıysa, zone transfer’ı manuel tetikleyin. Start-DnsServerZoneTransfer -Name "sirket.local" -ComputerName "dns-secondary01" ile bunu yapabilirsiniz.

Scavenging ve Aging: Eski A kayıtları sistemde birikmesin diye DNS Aging/Scavenging’i etkinleştirmek gerekiyor:

# Zone için aging'i etkinleştir
Set-DnsServerZoneAging `
    -Name "sirket.local" `
    -Aging $true `
    -ScavengeServers "dns-sunucu01" `
    -ComputerName "dns-sunucu01"

# Scavenging ayarlarını görüntüle
Get-DnsServerZoneAging -Name "sirket.local" -ComputerName "dns-sunucu01"

Sonuç

PowerShell ile DNS yönetimi, hem troubleshooting hem de günlük operasyonlar açısından size büyük bir verimlilik artışı sağlar. Resolve-DnsName ile hızlı sorgular yapabilir, DnsServer modülü ile sunucu yönetimini otomatize edebilir, toplu işlemlerle saat süren manuel görevleri dakikalar içinde tamamlayabilirsiniz.

Özellikle CSV bazlı toplu kayıt oluşturma ve tutarlılık kontrol scriptleri, büyük ortamlarda gerçekten hayat kurtarıcı. Bu scriptleri kendi ortamınıza uyarlayın, Task Scheduler ile düzenli çalışacak şekilde ayarlayın ve DNS sorunlarını reaktif değil proaktif şekilde yönetmeye başlayın.

Son olarak şunu söyleyeyim: DNS konusunda en büyük tehlike “çalışıyor, dokunma” sendromudur. Düzenli raporlar çalıştırmak, eski kayıtları temizlemek ve tutarlılık kontrolü yapmak, büyük bir kriz çıkmadan önce sorunları yakalamanızı sağlar. PowerShell bu işleri otomatize etmek için tam olarak ihtiyacınız olan araç.

Yorum yapın