Saat uyumsuzlukları küçük bir rahatsızlık gibi görünse de, Active Directory ortamlarında Kerberos kimlik doğrulaması 5 dakikadan fazla saat farkına tahammül etmez ve bu durum kullanıcıların sisteme giremediği ciddi sorunlara yol açar. Üretim ortamında bu tür bir felaketi yaşamadan önce NTP yapılandırmasını düzgün oturtmak, her Windows Server yöneticisinin öncelikli görevlerinden biri olmalı.
NTP ve Windows Zaman Servisi Temelleri
Windows’ta zaman senkronizasyonu Windows Time Service (W32tm) üzerinden yönetilir. Bu servis, hem komut satırı aracı olan w32tm.exe hem de PowerShell cmdlet’leri aracılığıyla kontrol edilebilir. Modern ortamlarda PowerShell tercih edilir çünkü hem daha okunabilir hem de otomasyon için çok daha uygundur.
Bir Active Directory ortamında zaman hiyerarşisi şöyle işler:
- PDC Emulator rolündeki Domain Controller, dış NTP sunucusundan zaman alır
- Diğer Domain Controller’lar PDC’den senkronize olur
- Üye sunucular ve istemciler, kendi DC’lerinden senkronize olur
- Workgroup makineler doğrudan NTP sunucusundan veya manuel olarak yapılandırılmış kaynaktan alır
Bu hiyerarşiyi anlamak, neyi nereye yapılandıracağınızı bilmek açısından kritik önem taşır.
Mevcut NTP Yapılandırmasını Kontrol Etmek
Bir şeyi yapılandırmadan önce mevcut durumu anlamak gerekir. Aşağıdaki komutlarla sunucunun zaman durumunu hızlıca görebilirsiniz.
# Mevcut NTP yapılandırmasını görüntüle
w32tm /query /configuration
# Zaman kaynağı ve senkronizasyon durumunu kontrol et
w32tm /query /status
# NTP sunucusunu ve stratum bilgisini göster
w32tm /query /source
Bu komutları çalıştırdığınızda karşınıza birkaç önemli alan çıkar. Source alanı hangi sunucudan zaman alındığını, Stratum ise zaman kaynağının kalitesini gösterir. Stratum 1 doğrudan atomik saatten, Stratum 2 Stratum 1’den beslendiğini ifade eder. Kurumsal ortamlarda genellikle Stratum 2 veya 3 kaynaklar kullanılır.
PowerShell ile daha ayrıntılı bilgi almak için:
# Windows Time Service durumunu PowerShell ile sorgula
Get-Service W32Time | Select-Object Name, Status, StartType
# Registry üzerinden NTP sunucu listesini oku
$regPath = "HKLM:SYSTEMCurrentControlSetServicesW32TimeParameters"
Get-ItemProperty -Path $regPath | Select-Object NtpServer, Type
PDC Emulator’ü Dış NTP Sunucusuna Bağlamak
Gerçek dünya senaryosu: Şirketin Active Directory ortamında PDC Emulator rolü DC01.firma.local sunucusunda. Bunu Türkiye NTP havuzlarına veya güvenilir halka açık NTP sunucularına bağlamamız gerekiyor.
# PDC Emulator'ü dış NTP sunucularına bağla
# NTP.org Türkiye havuzunu ve yedek olarak Google NTP kullan
$ntpServers = "0.tr.pool.ntp.org,0x9 1.tr.pool.ntp.org,0x9 time.google.com,0x9"
w32tm /config /manualpeerlist:$ntpServers /syncfromflags:manual /reliable:yes /update
# Windows Time Service'i yeniden başlat
Restart-Service W32Time
# Hemen senkronizasyon başlat
w32tm /resync /force
Burada virgülden sonra gelen 0x9 değeri önemli. Bu, SpecialInterval flagidir ve sunucuya “bu kaynağı özel aralıklarla kullan, ağırlıklı kaynak olarak işaretle” anlamına gelir. 0x8 ise UseAsFallbackOnly yani sadece yedek olarak kullan demektir.
Yapılandırmayı doğrulamak için:
# Yapılandırmanın uygulandığını doğrula
w32tm /query /configuration | Select-String "NtpServer|Type|Enabled"
# Senkronizasyon kaynağını kontrol et (birkaç dakika sonra)
w32tm /query /source
# Detaylı durum raporu
w32tm /query /status /verbose
PowerShell ile Toplu NTP Yapılandırması
Tek bir sunucu için komut çalıştırmak basit, ama 50 üye sunucuyu yapılandırmanız gerektiğinde işler değişir. Aşağıdaki script, remote sunucularda NTP yapılandırmasını merkezi olarak yönetmenizi sağlar.
# Uzak sunucularda NTP yapılandırması uygula
$sunucuListesi = @(
"WEBSRV01",
"WEBSRV02",
"DBSRV01",
"FILESRV01"
)
$ntpSunucusu = "dc01.firma.local"
foreach ($sunucu in $sunucuListesi) {
Write-Host "[$sunucu] Yapılandırılıyor..." -ForegroundColor Yellow
try {
Invoke-Command -ComputerName $sunucu -ScriptBlock {
param($ntp)
# NTP sunucusunu domain hierarchy olarak ayarla
w32tm /config /syncfromflags:domhier /update
# Servisi yeniden başlat
Restart-Service W32Time -Force
# Senkronizasyonu zorla
Start-Sleep -Seconds 3
w32tm /resync /force
# Sonucu döndür
$durum = w32tm /query /source
return $durum
} -ArgumentList $ntpSunucusu -ErrorAction Stop
Write-Host "[$sunucu] Basarili!" -ForegroundColor Green
}
catch {
Write-Host "[$sunucu] HATA: $_" -ForegroundColor Red
}
}
Domain Controller Olmayan Sunucular İçin Yapılandırma
Workgroup makineler veya domain dışındaki sunucular için yapılandırma biraz farklıdır. Bu makinelerde NT5DS tipi çalışmaz, doğrudan NTP kaynağı belirtmeniz gerekir.
# Workgroup makinesi veya domain dışı sunucu için NTP ayarı
function Set-NTPKonfigurasyon {
param(
[string[]]$NTPSunuculari = @("time.cloudflare.com", "time.google.com", "tr.pool.ntp.org"),
[string]$BilgisayarAdi = $env:COMPUTERNAME
)
$ntpString = ($NTPSunuculari | ForEach-Object { "$_,0x9" }) -join " "
Write-Host "NTP Sunuculari: $ntpString" -ForegroundColor Cyan
# Windows Time Service'i aktif et
Set-Service -Name W32Time -StartupType Automatic
Start-Service -Name W32Time
# NTP tipini Manual olarak ayarla
$params = @{
Path = "HKLM:SYSTEMCurrentControlSetServicesW32TimeParameters"
Name = "Type"
Value = "NTP"
}
Set-ItemProperty @params
# NTP sunucularını ayarla
w32tm /config /manualpeerlist:$ntpString /syncfromflags:manual /reliable:YES /update
# Servisi yeniden başlat ve senkronize et
Restart-Service W32Time -Force
Start-Sleep -Seconds 5
w32tm /resync /force
# Sonucu göster
Write-Host "`nYeni Konfigurasyon:" -ForegroundColor Green
w32tm /query /status
}
# Kullanım
Set-NTPKonfigurasyon -NTPSunuculari @("time.cloudflare.com", "time.google.com")
NTP Senkronizasyonunu İzleme ve Raporlama
Yapılandırma sonrası izleme yapmak en az yapılandırma kadar önemlidir. Özellikle büyük ortamlarda hangi makinenin ne kadar sapma gösterdiğini periyodik olarak kontrol etmek gerekir.
# Tüm sunucularda saat sapmasını kontrol eden script
function Get-ZamanSapmaRaporu {
param(
[string[]]$Sunucular,
[int]$MaxSapmaSaniye = 30
)
$rapor = @()
foreach ($sunucu in $Sunucular) {
try {
$sonuc = Invoke-Command -ComputerName $sunucu -ScriptBlock {
$durum = w32tm /query /status
$kaynak = w32tm /query /source
# Offset değerini parse et
$offsetSatir = $durum | Where-Object { $_ -match "Time Offset|Clock Offset" }
[PSCustomObject]@{
Sunucu = $env:COMPUTERNAME
Kaynak = ($kaynak | Select-Object -First 1).Trim()
Offset = $offsetSatir
Zaman = Get-Date -Format "dd.MM.yyyy HH:mm:ss"
}
} -ErrorAction Stop
$rapor += $sonuc
# Kritik sapma uyarısı
if ($sonuc.Offset -match "(d+.d+)s") {
$saniye = [double]$Matches[1]
if ($saniye -gt $MaxSapmaSaniye) {
Write-Warning "[$sunucu] Kritik sapma tespit edildi: $saniye saniye!"
}
}
}
catch {
$rapor += [PSCustomObject]@{
Sunucu = $sunucu
Kaynak = "ERISIM HATASI"
Offset = "N/A"
Zaman = Get-Date -Format "dd.MM.yyyy HH:mm:ss"
}
}
}
return $rapor
}
# Çalıştır ve sonuçları göster
$sunucuListesi = @("DC01", "DC02", "WEBSRV01", "DBSRV01")
$rapor = Get-ZamanSapmaRaporu -Sunucular $sunucuListesi -MaxSapmaSaniye 15
$rapor | Format-List
Güvenlik Duvarı ve NTP Portlarını Kontrol Etmek
NTP UDP 123 portu üzerinden çalışır. Özellikle güvenlik duvarı arkasındaki sunucularda veya Azure/AWS gibi bulut ortamlarında bu portu açmanız gerekebilir.
# Windows Firewall'da NTP portunu kontrol et
Get-NetFirewallRule | Where-Object { $_.DisplayName -like "*NTP*" -or $_.DisplayName -like "*Time*" }
# NTP için outbound kural oluştur
New-NetFirewallRule `
-DisplayName "NTP Outbound UDP 123" `
-Direction Outbound `
-Protocol UDP `
-RemotePort 123 `
-Action Allow `
-Profile Any `
-Description "NTP zaman senkronizasyonu icin outbound kural"
# NTP sunucusu olarak çalışan makinede inbound kural gerekir
New-NetFirewallRule `
-DisplayName "NTP Inbound UDP 123" `
-Direction Inbound `
-Protocol UDP `
-LocalPort 123 `
-Action Allow `
-Profile Domain `
-Description "NTP sunucu inbound trafigi"
# NTP bağlantısını test et
Test-NetConnection -ComputerName "time.cloudflare.com" -Port 123
Hyper-V ve Sanal Makinelerde Özel Dikkat Gerektiren Durumlar
Sanal makine ortamlarında NTP yapılandırması ekstra dikkat ister. Hyper-V, varsayılan olarak VM’lerin zamanını host ile senkronize eder ve bu durum bazen NTP yapılandırmanızla çakışır.
Gerçek dünya senaryosu: Üretim ortamında bir VM’in saati sürekli geri gidiyordu. Sorunun kaynağı, hem NTP hem de Hyper-V Integration Services’ın zaman senkronizasyonunun aynı anda etkin olmasıydı. İkisi birbirine girince saat kararsız hale geliyordu.
# Hyper-V zaman senkronizasyonunu kontrol et (Hyper-V Host'ta çalıştır)
Get-VMIntegrationService -VMName "UretimSunucu01" |
Where-Object { $_.Name -eq "Time Synchronization" }
# Domain Controller olan VM'lerde Hyper-V zaman senkronizasyonunu devre dışı bırak
Disable-VMIntegrationService -VMName "DC01" -Name "Time Synchronization"
# VM içinde NTP'nin düzgün çalıştığını doğrula
Invoke-Command -VMName "DC01" -Credential (Get-Credential) -ScriptBlock {
w32tm /query /status
w32tm /query /source
}
Önemli not: Domain Controller rolü taşıyan sanal makinelerde Hyper-V zaman senkronizasyonunu mutlaka devre dışı bırakın. DC’ler PDC Emulator hiyerarşisi üzerinden zamanı almalıdır, host makine üzerinden değil.
NTP Loglarını Analiz Etmek
Senkronizasyon sorunlarını teşhis ederken Windows Event Log ve w32tm debug logları çok değerlidir.
# Windows Time Service event loglarını görüntüle
Get-WinEvent -LogName "System" -MaxEvents 50 |
Where-Object { $_.ProviderName -eq "Microsoft-Windows-Time-Service" } |
Select-Object TimeCreated, LevelDisplayName, Message |
Format-List
# W32tm debug logunu etkinleştir
w32tm /debug /enable /file:C:Logsw32tm.log /size:10000000 /entries:0-116
# Birkaç dakika bekle, sonra kapat
Start-Sleep -Seconds 120
w32tm /debug /disable
# Log dosyasını analiz et
Get-Content "C:Logsw32tm.log" |
Where-Object { $_ -match "error|warn|sync|NTP" -and $_ -ne "" } |
Select-Object -Last 30
# Event Log'dan kritik hataları filtrele
Get-WinEvent -FilterHashtable @{
LogName = "System"
ProviderName = "Microsoft-Windows-Time-Service"
Level = 2 # Error
StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Message
Yaygın Sorunlar ve Çözümleri
Sorun 1: “The service has not been started” hatası
W32Time servisi durdurulmuş olabilir. Önce servisin durumunu kontrol edin, sonra başlatın ve otomatik başlangıç olarak ayarlayın.
Get-Service W32Time
Set-Service W32Time -StartupType Automatic
Start-Service W32Time
w32tm /resync /force
Sorun 2: “Access Denied” hatası
NTP yapılandırma komutlarını çalıştırırken yetki hatası alıyorsanız PowerShell’i Yönetici olarak çalıştır ile açmanız gerekir. Bunu script içinde kontrol etmek için:
# Script başında yetki kontrolü ekle
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Error "Bu scripti Administrator olarak calistirmaniz gerekiyor!"
exit 1
}
Write-Host "Yetki dogrulamasi basarili, devam ediliyor..." -ForegroundColor Green
Sorun 3: NTP sunucusuna ulaşılamıyor
Güvenlik duvarı veya ağ politikası UDP 123 portunu engelliyor olabilir. Test için:
# UDP port testi (NTP için özel)
$udpClient = New-Object System.Net.Sockets.UdpClient
$udpClient.Connect("time.cloudflare.com", 123)
Write-Host "NTP portuna erisim basarili"
$udpClient.Close()
Sorun 4: Saat düzelmiyor, sürekli sapıyor
Bu genellikle VM ortamında Hyper-V Integration Services çakışmasından veya donanım saatinin bozuk olmasından kaynaklanır. Önce Hyper-V senkronizasyonunu kontrol edin, sonra w32tm /resync /rediscover /force komutu ile yeni bir kaynak keşfi yaptırın.
GPO ile Merkezi NTP Dağıtımı
Kurumsal ortamlarda tek tek sunucuya gidip yapılandırma yapmak yerine Group Policy ile NTP ayarlarını tüm domain’e dağıtabilirsiniz. PowerShell ile GPO oluşturmak da mümkündür.
# Group Policy üzerinden NTP ayarları için registry değerlerini belirle
# Bu değerleri GPO > Computer Configuration > Preferences > Registry altında uygulayın
$gpoAyarlari = @{
"HKLM:SYSTEMCurrentControlSetServicesW32TimeParametersNtpServer" = "dc01.firma.local,0x9"
"HKLM:SYSTEMCurrentControlSetServicesW32TimeParametersType" = "NT5DS"
"HKLM:SYSTEMCurrentControlSetServicesW32TimeConfigMaxPosPhaseCorrection" = 3600
"HKLM:SYSTEMCurrentControlSetServicesW32TimeConfigMaxNegPhaseCorrection" = 3600
}
# Registry ayarlarını doğrulama scripti (GPO uygulandıktan sonra çalıştırın)
foreach ($key in $gpoAyarlari.Keys) {
$bolumler = $key -split "\"
$deger = $bolumler[-1]
$yol = ($bolumler[0..($bolumler.Length - 2)]) -join ""
$mevcutDeger = (Get-ItemProperty -Path $yol -Name $deger -ErrorAction SilentlyContinue).$deger
$beklenenDeger = $gpoAyarlari[$key]
if ($mevcutDeger -eq $beklenenDeger) {
Write-Host "[OK] $deger : $mevcutDeger" -ForegroundColor Green
} else {
Write-Warning "[UYARI] $deger : Beklenen '$beklenenDeger', Mevcut '$mevcutDeger'"
}
}
Scheduled Task ile Düzenli NTP Kontrolü
Üretime aldığınız NTP yapılandırmasının sağlığını periyodik olarak kontrol etmek için bir Scheduled Task kurabilirsiniz.
# Her 6 saatte bir NTP durumunu kontrol eden görev oluştur
$scriptIcerik = @'
$logDosyasi = "C:LogsNTP_Check.log"
$tarih = Get-Date -Format "dd.MM.yyyy HH:mm:ss"
$durum = w32tm /query /status
$kaynak = w32tm /query /source
"[$tarih] NTP Kaynak: $kaynak" | Add-Content $logDosyasi
# 60 saniyeden fazla sapma varsa zorla senkronize et
if ($durum -match "(d+.d+)s" -and [double]$Matches[1] -gt 60) {
"[$tarih] KRITIK: $($Matches[1]) saniye sapma! Zorla senkronize ediliyor." | Add-Content $logDosyasi
w32tm /resync /force
}
'@
$scriptYolu = "C:ScriptsNTP_Monitor.ps1"
$scriptIcerik | Set-Content -Path $scriptYolu -Encoding UTF8
# Scheduled Task oluştur
$eylem = New-ScheduledTaskAction -Execute "PowerShell.exe" `
-Argument "-NonInteractive -NoProfile -File `"$scriptYolu`""
$tetikleyici = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Hours 6) -Once `
-At (Get-Date)
$ayarlar = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -StartWhenAvailable
Register-ScheduledTask -TaskName "NTP Durum Kontrolu" `
-Action $eylem `
-Trigger $tetikleyici `
-Settings $ayarlar `
-RunLevel Highest `
-User "SYSTEM" `
-Description "Her 6 saatte bir NTP senkronizasyon durumunu kontrol eder"
Sonuç
NTP yapılandırması, “bir kez yap unut” kategorisinde görülse de özellikle Active Directory ortamlarında düzenli takip gerektiren kritik bir altyapı bileşenidir. PDC Emulator’ün güvenilir bir dış kaynakla senkronizasyonu, üye sunucuların domain hiyerarşisini doğru takip etmesi ve sanal makine ortamlarında Hyper-V Integration Services çakışmasının önlenmesi, sağlıklı bir zaman altyapısının üç temel direğidir.
PowerShell ile bu yapılandırmaları tek tek sunucuda yapmaktan öte, merkezi ve tekrarlanabilir scriptler haline getirmek hem operasyonel verimliliği artırır hem de yapılandırma farklılıklarından kaynaklanan sorunları minimuma indirir. İzleme ve raporlama scriptlerini de ortamınıza entegre ettiğinizde, Kerberos hatalarıyla uğraşmak yerine gerçek işlerinize vakit ayırabilirsiniz.
Son bir hatırlatma: Üretim ortamına yapılandırma uygulamadan önce mutlaka test ortamında deneyin ve mevcut yapılandırmanın yedeğini alın. w32tm /query /configuration > C:Backupntp_backup.txt komutu beş saniyenizi alır ama sizi büyük baş ağrısından kurtarabilir.