Windows DNS Log Analizi ve Hata Ayıklama
DNS loglarına bakmak, çoğu Windows sistem yöneticisinin “gerekmedikçe uğramam” dediği ama bir şeyler patladığında koşarak gittiği o karanlık köşelerden biridir. Yıllar içinde öğrendim ki DNS sorunlarının yüzde seksenini log analizi çözüyor, geri kalanı da genellikle “ama ben firewall’a dokunmadım” türünden açıklamalarla netleşiyor. Bu yazıda Windows DNS Server’ın log mekanizmasını, debug logging özelliklerini ve gerçek hayatta karşılaşılan senaryoların nasıl çözüldüğünü ele alacağız.
Windows DNS Log Sistemi Nedir ve Nerede Bulunur?
Windows DNS Server, varsayılan olarak iki farklı log kaynağı sunar. Birincisi Event Viewer altındaki DNS Server event logları, ikincisi ise manuel olarak aktifleştirmeniz gereken debug log dosyası. Çoğu kişi sadece birinci kaynağa bakıp “log yok, sorun yok” diye geçiyor. Bu büyük bir hata.
Event Viewer’daki DNS loglarına şuradan ulaşırsınız:
Applications and Services Logs > Microsoft > Windows > DNS-Server > Audit
Bu log altında zone transfer’lar, dinamik DNS güncellemeleri, konfigürasyon değişiklikleri gibi yönetimsel olaylar kayıt altına alınır. Ama gerçek anlamda paket düzeyinde analiz için debug logging şart.
Debug log dosyası varsayılan olarak şu konumdadır:
C:WindowsSystem32dnsdns.log
Ancak bu dosya varsayılan kurulumda boş gelir çünkü debug logging kapalıdır. Açmak için DNS Manager’ı kullanabilirsiniz ya da PowerShell yolunu tercih edebilirsiniz.
Debug Logging’i Aktifleştirme
DNS Manager üzerinden: DNS Server’a sağ tıklayın, Properties’e girin, Debug Logging sekmesine tıklayın. Buradan hangi paket türlerini loglamak istediğinizi seçebilirsiniz.
Ama işin pratik tarafı PowerShell ile yapmak. Üretim ortamında bir şeyler ayarlarken GUI’ye tıklamak yerine şunu çalıştırıyorum:
# Debug logging'i aktifleştir
Set-DnsServerDiagnostics -ComputerName "DNS01" `
-Queries $true `
-Answers $true `
-Send $true `
-Receive $true `
-UdpPackets $true `
-TcpPackets $true `
-QuestionTransactions $true `
-UnmatchedResponse $true `
-LogFilePath "C:DNS_Logsdns_debug.log" `
-MaxMBFileSize 500
Dikkat etmeniz gereken şey şu: debug logging’i sonsuza kadar açık bırakmayın. Yoğun bir DNS sunucusunda bu log birkaç saatte gigabaytlara ulaşabilir ve disk performansını ciddiye alır. Sorunu yakalayın, logu kapatın.
Mevcut debug logging durumunu kontrol etmek için:
# Mevcut diagnostic ayarlarını görüntüle
Get-DnsServerDiagnostics -ComputerName "DNS01" |
Select-Object Queries, Answers, LogFilePath, MaxMBFileSize
DNS Event Log’larını PowerShell ile Analiz Etme
Event Viewer’a tıklamak yerine komut satırından analiz yapmak hem hızlı hem de scriptlenebilir. Özellikle birden fazla DNS sunucunuz varsa bu yaklaşım hayat kurtarıyor.
# Son 24 saatteki DNS hata olaylarını çek
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -ComputerName "DNS01" -FilterHashtable @{
LogName = 'Microsoft-Windows-DNS-Server/Audit'
StartTime = $startTime
Level = 2,3 # 2: Error, 3: Warning
} | Select-Object TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
Event ID’leri bilmek analizi hızlandırır. En sık karşılaştıklarım:
- Event ID 408: DNS sunucusu DNS sorgusu için soket açamadı. Port çakışması veya ağ sorunu işareti.
- Event ID 414: Zone transfer başarısız oldu. AXFR/IXFR sorunlarına bakmanız gerekiyor.
- Event ID 4013: DNS sunucusu AD’den yüklenemedi. Domain Controller erişim sorunu.
- Event ID 6527: Zone imzalama hatası. DNSSEC kullanıyorsanız bu çıkabilir.
- Event ID 2: DNS sunucusu başlatıldı. Unexpected restart’ları yakalamak için iyi.
Belirli bir event ID’yi filtrelemek için:
# Zone transfer hatalarını filtrele
Get-WinEvent -ComputerName "DNS01" -FilterHashtable @{
LogName = 'Microsoft-Windows-DNS-Server/Audit'
Id = 414
StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Message |
Export-Csv "C:ReportsZoneTransferErrors.csv" -Encoding UTF8 -NoTypeInformation
Debug Log Dosyasını Analiz Etme
Debug log formatı ilk bakışta biraz şifreli görünüyor. Bir satır örneği şu şekilde görünür:
8/15/2024 14:23:41 PM 0F54 PACKET 000001A2B4C3D5E6 UDP Rcv 192.168.1.50 0001 Q [0001 D NOERROR] A (3)www(8)contoso(3)com(0)
Bu satırı parçalara ayıralım:
- 8/15/2024 14:23:41 PM: Zaman damgası
- 0F54: Thread ID (hex)
- PACKET: Log girdisi tipi
- UDP: Protokol
- Rcv: Receive (alınan paket), Snd olsaydı gönderilen demekti
- 192.168.1.50: İstemci IP adresi
- Q: Query (sorgu)
- A: Sorgu tipi (A record)
- (3)www(8)contoso(3)com(0): Sorgulanan hostname
Bu formatı PowerShell ile parse etmek için basit bir yaklaşım:
# DNS debug logunu parse et ve analiz et
$logPath = "C:WindowsSystem32dnsdns.log"
$pattern = '(d{1,2}/d{1,2}/d{4}s+d{1,2}:d{2}:d{2})s+w+s+PACKET.*?(UDP|TCP)s+(Rcv|Snd)s+(d{1,3}.d{1,3}.d{1,3}.d{1,3})'
$results = Get-Content $logPath | Where-Object { $_ -match $pattern } |
ForEach-Object {
if ($_ -match $pattern) {
[PSCustomObject]@{
Timestamp = $matches[1]
Protocol = $matches[2]
Direction = $matches[3]
ClientIP = $matches[4]
}
}
}
# En fazla sorgu yapan IP'leri bul
$results | Group-Object ClientIP |
Sort-Object Count -Descending |
Select-Object -First 20 Name, Count
Bu script büyük log dosyalarında yavaş çalışabilir. Birkaç gigabaytlık bir log için Select-String kullanmak daha verimli olur.
Gerçek Dünya Senaryosu 1: “İnternet Gitmiyor” Şikayeti
Klasik senaryo: Pazartesi sabahı kullanıcılar internet erişiminin olmadığını söylüyor, ama ağ bağlantısı görünüşte sağlam. İlk yaptığım şey DNS’e bakmak.
Önce temel kontroller:
# DNS sunucusu sorgulara yanıt veriyor mu?
Resolve-DnsName -Name "google.com" -Server "192.168.1.10" -Type A
# Forwarder'lara ulaşıyor mu?
Test-NetConnection -ComputerName "8.8.8.8" -Port 53
# DNS sunucusu servis durumu
Get-Service -ComputerName "DNS01" -Name "DNS" |
Select-Object Name, Status, StartType
Eğer forwarder’lara ulaşılamıyorsa ve event logda Event ID 408 varsa, büyük ihtimalle firewall değişikliği yapılmış veya ISP tarafında bir sorun var. Ama asıl soru şu: sorun ne zaman başladı?
# DNS servisinin son restart zamanını bul
Get-WinEvent -ComputerName "DNS01" -FilterHashtable @{
LogName = 'System'
Id = 7036
} | Where-Object { $_.Message -like "*DNS Server*" } |
Select-Object -First 5 TimeCreated, Message
Bu sorgu DNS servisinin son ne zaman başlatıldığını ve durdurulduğunu gösterir. Eğer beklenmedik bir restart varsa oradan yola çıkarsınız.
Gerçek Dünya Senaryosu 2: Yavaş DNS Çözümlemesi
Kullanıcılar web sayfalarının yavaş açıldığını söylüyor ama bant genişliği tam, sunucular sağlıklı. DNS çözümleme süresi şüpheli.
# DNS çözümleme süresini ölç
function Measure-DnsResolution {
param(
[string[]]$Hostnames,
[string]$DnsServer,
[int]$Iterations = 10
)
foreach ($hostname in $Hostnames) {
$times = @()
for ($i = 0; $i -lt $Iterations; $i++) {
# Cache'i temizlemek için farklı subdomain kullanmıyoruz,
# ancak ilk sorgu sonrası cache devreye girer
$sw = [System.Diagnostics.Stopwatch]::StartNew()
try {
Resolve-DnsName -Name $hostname -Server $DnsServer -ErrorAction Stop | Out-Null
$sw.Stop()
$times += $sw.ElapsedMilliseconds
} catch {
$times += -1 # Hata durumu
}
}
[PSCustomObject]@{
Hostname = $hostname
AvgMs = [math]::Round(($times | Where-Object { $_ -ge 0 } |
Measure-Object -Average).Average, 2)
MaxMs = ($times | Measure-Object -Maximum).Maximum
ErrorCount = ($times | Where-Object { $_ -eq -1 }).Count
}
}
}
Measure-DnsResolution -Hostnames @("google.com","microsoft.com","github.com") `
-DnsServer "192.168.1.10" -Iterations 5
Eğer ortalama çözümleme süresi 200ms’nin üzerindeyse ve forwarder olarak harici DNS kullanıyorsanız, forwarder değiştirmeyi veya conditional forwarder eklemeyi düşünün.
DNS Cache Yönetimi ve Analizi
Bazen sorun eski veya hatalı cache kayıtlarından kaynaklanır. DNS cache’ini analiz etmek sorun tespitinde kritik olabilir.
# DNS sunucusu cache'ini görüntüle
Get-DnsServerCache -ComputerName "DNS01" |
Select-Object Name, RecordType, TimeToLive, RecordData |
Sort-Object TimeToLive |
Format-Table -AutoSize
# Belirli bir domain için cache kaydını ara
Get-DnsServerCache -ComputerName "DNS01" |
Where-Object { $_.Name -like "*contoso*" }
# Tüm cache'i temizle (dikkatli kullanın!)
Clear-DnsServerCache -ComputerName "DNS01" -Force
# Sadece belirli bir kaydı cache'den sil
Remove-DnsServerResourceRecord -ComputerName "DNS01" `
-ZoneName "cache" `
-Name "problematic-host" `
-RRType A -Force
Cache temizleme sonrası ilk birkaç dakika DNS sunucusu tüm sorguları forwarder’a iletecek, bu performans düşüşüne neden olabilir. Bunu mesai saatleri dışında yapmanızı öneririm.
Zone Transfer Sorunlarını Tespit Etme
Active Directory ortamında zone transfer sorunları genellikle AD replikasyon sorunlarıyla iç içe geçer. Ama standart primary/secondary DNS kurulumunda debug logging tam anlamıyla hayat kurtarıcı.
# Zone transfer durumunu kontrol et
Get-DnsServerZone -ComputerName "DNS01" |
Select-Object ZoneName, ZoneType, IsDsIntegrated, IsReverseLookupZone |
Where-Object { $_.ZoneType -eq "Secondary" }
# Secondary zone'u manual olarak güncelle (zone transfer tetikle)
Start-DnsServerZoneTransfer -ComputerName "DNS02" -Name "contoso.local" -FullTransfer
# Zone transfer ayarlarını görüntüle
Get-DnsServerZoneTransferPolicy -ComputerName "DNS01"
Zone transfer başarısız olduğunda event logda Event ID 414 görürsünüz. Mesajı okuyun, çünkü genellikle “Refused” veya “Connection refused” gibi net bir hata içerir. Bu durumda primary sunucudaki zone ayarlarını kontrol edin, secondary sunucunun IP’si zone transfer’a izin verilenler listesinde mi bakın.
DNS Sorgu İstatistiklerini İzleme
Uzun vadeli DNS sağlığı için istatistikleri düzenli toplamak lazım. Bunu yaparken hem sunucu yükünü hem de olağandışı sorgu kalıplarını yakalayabilirsiniz.
# DNS sunucusu istatistiklerini al
$stats = Get-DnsServerStatistics -ComputerName "DNS01"
# Genel sorgu istatistikleri
$stats.Query | Select-Object *
# Önemli metrikleri özet olarak göster
[PSCustomObject]@{
TotalQueries = $stats.Query.TotalQueries
RecursiveQueries = $stats.Query.RecursiveLookups
CacheHits = $stats.Cache.Hits
CacheMisses = $stats.Cache.Misses
CacheHitRatio = if ($stats.Cache.Hits + $stats.Cache.Misses -gt 0) {
[math]::Round($stats.Cache.Hits /
($stats.Cache.Hits + $stats.Cache.Misses) * 100, 2)
} else { 0 }
FailedQueries = $stats.Query.Failures
}
# İstatistikleri sıfırla (dikkatli kullanın)
# Clear-DnsServerStatistics -ComputerName "DNS01" -Force
Cache hit ratio’su yüzde yetmişin altındaysa TTL değerlerinizi gözden geçirmenizi öneririm. Çok kısa TTL değerleri gereksiz yere forwarder yükü oluşturur.
Suspicious DNS Query Analizi ve Güvenlik
DNS logları sadece sorun giderme için değil, güvenlik açısından da kritik. DNS üzerinden veri sızdırma (DNS tunneling), C2 iletişimi veya malware aktivitesi log analizi ile tespit edilebilir.
# Olağandışı uzun DNS sorgu isimlerini tespit et
# (DNS tunneling genellikle çok uzun hostname'ler kullanır)
$logPath = "C:WindowsSystem32dnsdns.log"
$suspiciousQueries = Get-Content $logPath |
Where-Object { $_ -match "((d+))" } |
ForEach-Object {
$lengths = [regex]::Matches($_, '((d+))') |
ForEach-Object { [int]$_.Groups[1].Value }
$maxLabel = ($lengths | Measure-Object -Maximum).Maximum
if ($maxLabel -gt 50) {
[PSCustomObject]@{
LogLine = $_
MaxLabel = $maxLabel
}
}
}
$suspiciousQueries | Select-Object MaxLabel, LogLine |
Sort-Object MaxLabel -Descending |
Format-List
# Yüksek frekanslı sorgu yapan IP'leri belirle (potansiyel DDoS veya scanner)
Get-Content $logPath |
Select-String -Pattern 'd{1,3}.d{1,3}.d{1,3}.d{1,3}' |
ForEach-Object {
if ($_.Line -match '(d{1,3}.d{1,3}.d{1,3}.d{1,3})') { $matches[1] }
} |
Group-Object |
Sort-Object Count -Descending |
Select-Object -First 10 Name, Count
DNS tunneling işaretlerini özetlemek gerekirse:
- Çok uzun hostname’ler (63 karakterden uzun label’lar)
- Aynı domain’e çok sık yapılan TXT veya NULL tip sorgular
- Encode edilmiş gibi görünen random string subdomain’ler
- Normal çalışma saatleri dışında yoğun DNS trafiği
Log Rotasyonu ve Arşivleme
Debug log dosyası büyüdükçe hem analizi zorlaştırır hem de disk’i yer. Düzgün bir log rotasyonu kurması lazım.
# DNS debug log rotasyon scripti
# Scheduled Task olarak günlük çalıştırın
$logDir = "C:DNS_Logs"
$archiveDir = "C:DNS_LogsArchive"
$maxAgeDays = 30
# Archive klasörü yoksa oluştur
if (-not (Test-Path $archiveDir)) {
New-Item -ItemType Directory -Path $archiveDir | Out-Null
}
# Mevcut log dosyasını tarihli olarak arşivle
$currentLog = Join-Path $logDir "dns_debug.log"
if (Test-Path $currentLog) {
$archiveName = "dns_debug_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Move-Item $currentLog (Join-Path $archiveDir $archiveName)
}
# DNS logging'i kısa süre durdur ve yeniden başlat
# (yeni boş log dosyası oluşturmak için)
Set-DnsServerDiagnostics -ComputerName $env:COMPUTERNAME -All $false
Start-Sleep -Seconds 2
Set-DnsServerDiagnostics -ComputerName $env:COMPUTERNAME `
-Queries $true -Answers $true `
-LogFilePath $currentLog `
-MaxMBFileSize 200
# 30 günden eski arşiv dosyalarını sil
Get-ChildItem $archiveDir -Filter "*.log" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$maxAgeDays) } |
Remove-Item -Force
Write-Output "$(Get-Date): Log rotasyonu tamamlandı."
Çoklu DNS Sunucu Ortamında Merkezi Log Toplama
Birden fazla DNS sunucunuz varsa her birine ayrı ayrı bağlanmak zaman kaybıdır. Merkezi bir yaklaşım şart.
# Çoklu DNS sunucudan event log topla
$dnsServers = @("DNS01", "DNS02", "DNS03")
$reportPath = "C:ReportsDNS_Health_$(Get-Date -Format 'yyyyMMdd').csv"
$allEvents = foreach ($server in $dnsServers) {
try {
Get-WinEvent -ComputerName $server -FilterHashtable @{
LogName = 'Microsoft-Windows-DNS-Server/Audit'
StartTime = (Get-Date).AddHours(-24)
Level = 2, 3
} -ErrorAction Stop |
Select-Object @{N='Server'; E={$server}},
TimeCreated, Id, LevelDisplayName, Message
} catch {
Write-Warning "$server sunucusuna erişilemedi: $_"
[PSCustomObject]@{
Server = $server
TimeCreated = Get-Date
Id = -1
LevelDisplayName = "Error"
Message = "Sunucuya erişilemedi: $_"
}
}
}
$allEvents | Export-Csv $reportPath -Encoding UTF8 -NoTypeInformation
Write-Output "Rapor oluşturuldu: $reportPath"
Sonuç
Windows DNS log analizi, görünürde basit ama uygulamada katmanlı bir konu. Event Viewer logları yönetimsel olaylar için yeterliyken, gerçek sorun tespiti için debug logging’i açmak kaçınılmaz. Ancak debug logging’i açık bırakmak da tehlikeli, disk ve performans üzerindeki etkisini göz ardı etmeyin.
En çok işe yarayan yaklaşım şu: sorun bildirimi geldiğinde debug logging’i aktifleştir, birkaç dakika bekle, logu al, logging’i kapat, analiz et. Bu döngüyü kırmak çoğu zaman gereksiz yere log biriktirmek anlamına gelir.
PowerShell tabanlı analiz araçlarını kendi ortamınıza göre uyarlayın ve scheduled task olarak çalışacak bir monitoring scripti kurun. Sorun çıkmadan önce baseline oluşturmak, bir şeyler patladığında “normal neydi” sorusunu çok hızlı yanıtlamanızı sağlar. DNS sorunları çoğunlukla basittir ama doğru yere bakmazsanız saatler alabilir. Log analizi o doğru yeri bulmakla ilgilidir.
