Windows DNS’te Split Brain DNS Yapılandırması
Kurumsal ağlarda DNS yönetiminin en kritik noktalarından biri, iç ve dış kullanıcıların aynı alan adı için farklı IP adreslerine yönlendirilmesi gereken senaryolardır. Buna Split Brain DNS ya da Split Horizon DNS diyoruz. Yıllarca farklı şirketlerde bu yapıyı kurmuş biri olarak şunu söyleyeyim: doğru yapılandırılmadığında hem güvenlik açığı hem de kafa karışıklığı kaynağı oluyor. Ama doğru yapıldığında, VPN’e gerek kalmadan iç kaynakları güvenle yönetmenin en temiz yolu bu.
Split Brain DNS Nedir ve Neden Gerekir?
Senaryo şu: Şirketinizin firma.com.tr alan adı var. Dışarıdan birisi mail.firma.com.tr adresine bağlandığında Exchange sunucunuzun public IP’sine gitmeli. Ama aynı kullanıcı ofise geldiğinde veya VPN üzerinden bağlandığında, trafiğin doğrudan iç network’teki Exchange sunucusunun private IP’sine gitmesi gerekiyor. Çünkü firewall üzerinden dönüp tekrar içeri girme (hairpin NAT) hem performans kaybına hem de bazı ortamlarda güvenlik politikası ihlallerine yol açıyor.
Split Brain DNS tam da bu problemi çözüyor. Aynı DNS adını, sorgu kaynağına göre farklı IP adresleriyle yanıtlıyorsunuz. İç DNS sunucusu iç IP’yi söylüyor, dış DNS sunucusu (genellikle hosting firmasındaki ya da Azure DNS) dış IP’yi söylüyor.
Windows DNS Server üzerinde bu yapıyı kurmanın birkaç farklı yöntemi var. En yaygın ve yönetimi en kolay olan yöntem, DNS Zone Scopes (DNS bölge kapsamları) kullanmak. Bu özellik Windows Server 2016 ile geldi ve PowerShell ile yönetiliyor. Bunun yanı sıra eski yöntem olan ayrı zone dosyaları tutmak da hâlâ geçerli.
Yapılandırma Öncesi Planlama
Ellerinizi klavyeye götürmeden önce şunları netleştirmeniz gerekiyor:
- Hangi alan adları split-brain gerektirecek? Tüm alan adı mı, yoksa sadece belirli subdomain’ler mi?
- İç ve dış IP adresleri neler? Bir tabloya yazın, karışıklık çok oluyor.
- DNS sunucularınızın topolojisi ne? Tek DNS sunucunuz mu var, yoksa Primary/Secondary yapısı mı?
- AD-Integrated zone mi kullanıyorsunuz? Bu kritik çünkü bazı yaklaşımlar AD-integrated zone’larla uyumsuzluk çıkarabiliyor.
- İstemcileriniz hangi DNS sunucusunu kullanıyor? DHCP’den mi alıyorlar, statik mi?
Örnek senaryomuzda şunu varsayalım: firma.com.tr alan adımız var. Dışarıda Cloudflare DNS’te bu zone yönetiliyor. İçeride Windows Server 2022 üzerinde AD-integrated zone var. Aşağıdaki subdomain’ler için split-brain gerekiyor:
mail.firma.com.tr– Exchange (dışarıda: 85.111.22.33, içeride: 192.168.10.50)vpn.firma.com.tr– VPN gateway (dışarıda: 85.111.22.34, içeride: 192.168.10.51)crm.firma.com.tr– CRM sistemi (dışarıda: 85.111.22.35, içeride: 192.168.10.52)
Yöntem 1: DNS Zone Scopes ile Split Brain (Önerilen)
Bu yöntem Windows Server 2016 ve sonrasında kullanılabilir. PowerShell ile yönetildiği için hem scriptlenebilir hem de audit edilebilir.
Zone Scope Oluşturma
Önce mevcut zone’umuzu kontrol edelim:
# PowerShell - Administrator olarak çalıştırın
Get-DnsServerZone -Name "firma.com.tr"
# Mevcut zone scope'larını listele
Get-DnsServerZoneScope -ZoneName "firma.com.tr"
Default olarak “.” adında bir scope görürsünüz. Bu, mevcut tüm kayıtların bulunduğu scope’tur. Şimdi bir “Internal” scope ekleyelim:
# Internal scope oluştur
Add-DnsServerZoneScope -ZoneName "firma.com.tr" -Name "Internal"
# Oluşturuldu mu kontrol et
Get-DnsServerZoneScope -ZoneName "firma.com.tr"
Scope’lara DNS Kayıtları Ekleme
Şimdi her scope için ayrı A kayıtları ekleyeceğiz. Default scope dış IP’leri, Internal scope iç IP’leri barındıracak:
# Default scope'a (dış kullanıcılar için) kayıt ekle
# Not: ZoneScope parametresi belirtilmezse default scope kullanılır
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "mail" `
-IPv4Address "85.111.22.33" `
-ZoneScope "."
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "vpn" `
-IPv4Address "85.111.22.34" `
-ZoneScope "."
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "crm" `
-IPv4Address "85.111.22.35" `
-ZoneScope "."
# Internal scope'a (iç kullanıcılar için) kayıt ekle
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "mail" `
-IPv4Address "192.168.10.50" `
-ZoneScope "Internal"
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "vpn" `
-IPv4Address "192.168.10.51" `
-ZoneScope "Internal"
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "crm" `
-IPv4Address "192.168.10.52" `
-ZoneScope "Internal"
Client Subnet Tanımlama
DNS Policy oluşturmadan önce, iç ağ IP bloğumuzu bir Client Subnet olarak tanımlamamız gerekiyor:
# İç ağ subnet'lerini tanımla
Add-DnsServerClientSubnet -Name "InternalSubnets" `
-IPv4Subnet @("192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12")
# Kontrol
Get-DnsServerClientSubnet
Birden fazla VLAN ya da farklı site subnet’leriniz varsa hepsini buraya eklemeyi unutmayın. Bunu gözden kaçıran sysadmin’lerin sonradan “neden bazı kullanıcılar dış IP’yi görüyor?” diye saat harcadığını gördüm.
DNS Policy Oluşturma
Artık kritik adıma geldik. DNS Policy, gelen sorgunun kaynağına göre hangi scope’un kullanılacağını belirliyor:
# Recursive (İstemci) sorguları için policy oluştur
Add-DnsServerQueryResolutionPolicy `
-Name "SplitBrainPolicy" `
-Action ALLOW `
-ClientSubnet "eq,InternalSubnets" `
-ZoneScope "Internal,1" `
-ZoneName "firma.com.tr" `
-ProcessingOrder 1
# Policy'i kontrol et
Get-DnsServerQueryResolutionPolicy -ZoneName "firma.com.tr"
Bu policy şunu diyor: “firma.com.tr zone’una gelen sorgularda, istemci InternalSubnets’te ise Internal scope’u kullan.” Bu subnet’te olmayan herkes default scope’taki kayıtları görür.
Yapılandırmayı Test Etme
Zone scope’ları ve policy’i uyguladıktan sonra test etmeden canlıya almayın. DNS Server servisini restart etmeye gerek yok ama yine de küçük bir kontrol yapalım:
# DNS Server servis durumunu kontrol et
Get-Service -Name DNS
# Policy'nin aktif olduğunu doğrula
Get-DnsServerQueryResolutionPolicy -ZoneName "firma.com.tr" |
Select-Object Name, Action, ProcessingOrder, IsEnabled
# İç ağdan test - bu 192.168.10.50 döndürmeli
Resolve-DnsName -Name "mail.firma.com.tr" -Server "192.168.10.10"
# Harici DNS'ten test (8.8.8.8 üzerinden)
Resolve-DnsName -Name "mail.firma.com.tr" -Server "8.8.8.8"
Tabii DNS sunucunuzu 8.8.8.8’den sorgulamak doğru bir test değil, bu sadece public DNS’i test eder. İç sunucunuzu iç olmayan bir IP’den simüle etmek için farklı bir subnet’ten ya da DMZ’den test yapmanız gerekiyor.
Yöntem 2: Ayrı Zone Dosyası Yaklaşımı (Eski Yöntem)
Zone Scope özelliği olmayan Windows Server 2012 R2 ve öncesi için, ya da bazı karmaşık AD replikasyon senaryolarında bu yöntemi kullanmak durumunda kalabilirsiniz. Mantık şu: firma.com.tr için iç ağda tamamen ayrı bir primary zone oluşturuyorsunuz ve bu zone sadece iç kayıtları barındırıyor.
DNS Manager üzerinden ya da PowerShell ile:
# Yeni primary zone oluştur (AD-integrated değil, sadece bu DNS sunucusunda)
Add-DnsServerPrimaryZone `
-Name "firma.com.tr" `
-ZoneFile "firma.com.tr.dns" `
-DynamicUpdate None
# İç kayıtları ekle
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "mail" `
-IPv4Address "192.168.10.50"
Add-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-A -Name "vpn" `
-IPv4Address "192.168.10.51"
# SOA ve NS kayıtlarını güncelle
Set-DnsServerResourceRecord -ZoneName "firma.com.tr" `
-OldInputObject (Get-DnsServerResourceRecord -ZoneName "firma.com.tr" -Name "@" -RRType SOA) `
-NewInputObject (...)
Bu yöntemin büyük dezavantajı: zone replikasyonu olmaz ve her iki zone’u da ayrı ayrı yönetmek zorundasınız. Bir kayıt eklediğinizde hem iç hem dış zone’u güncellemeniz gerekiyor. Bunu sıklıkla unutan ekipler ciddi sorunlarla karşılaşıyor.
AD Replikasyonu ve Split Brain
AD-integrated zone kullanıyorsanız dikkat etmeniz gereken önemli bir nokta var. Zone Scope’ları AD replikasyonu üzerinden taşınmıyor. Yani birden fazla Domain Controller’ınız varsa ve her birinde DNS çalışıyorsa, bu yapılandırmayı her DC üzerinde ayrı ayrı yapmanız gerekiyor.
Bunu otomatize etmek için bir PowerShell scripti hazırlamak mantıklı:
# Tüm DC'lere uygulayacak script
$DomainControllers = @("DC01", "DC02", "DC03")
$ZoneName = "firma.com.tr"
foreach ($DC in $DomainControllers) {
Write-Host "Configuring $DC..." -ForegroundColor Yellow
Invoke-Command -ComputerName $DC -ScriptBlock {
param($Zone)
# Zone scope kontrolü - yoksa oluştur
$ExistingScope = Get-DnsServerZoneScope -ZoneName $Zone -ErrorAction SilentlyContinue |
Where-Object {$_.ZoneScope -eq "Internal"}
if (-not $ExistingScope) {
Add-DnsServerZoneScope -ZoneName $Zone -Name "Internal"
Write-Host "Internal scope created on $env:COMPUTERNAME"
}
# Client subnet kontrolü
$ExistingSubnet = Get-DnsServerClientSubnet -Name "InternalSubnets" -ErrorAction SilentlyContinue
if (-not $ExistingSubnet) {
Add-DnsServerClientSubnet -Name "InternalSubnets" `
-IPv4Subnet @("192.168.0.0/16", "10.0.0.0/8")
}
# Policy kontrolü
$ExistingPolicy = Get-DnsServerQueryResolutionPolicy -ZoneName $Zone -ErrorAction SilentlyContinue |
Where-Object {$_.Name -eq "SplitBrainPolicy"}
if (-not $ExistingPolicy) {
Add-DnsServerQueryResolutionPolicy `
-Name "SplitBrainPolicy" `
-Action ALLOW `
-ClientSubnet "eq,InternalSubnets" `
-ZoneScope "Internal,1" `
-ZoneName $Zone `
-ProcessingOrder 1
}
} -ArgumentList $ZoneName
Write-Host "$DC configuration completed." -ForegroundColor Green
}
Bu scripti bir kez hazırlayın ve version control’e alın. İleride yeni DC eklediğinizde tek satırla çözüyorsunuz.
Yaygın Sorunlar ve Çözümleri
Yıllarca bu yapıyı kurarken bazı sorunlarla tekrar tekrar karşılaştım. Bunları paylaşmadan geçmek olmaz.
DNS Cache Sorunu: Split brain’i aktif ettikten sonra bazı istemciler hâlâ eski IP’yi görüyor olabilir. Bunun sebebi istemci tarafı DNS cache’i. Çözüm:
# İstemci tarafında cache temizleme
ipconfig /flushdns
# DNS Server tarafında cache temizleme
Clear-DnsServerCache -Force
# Belirli bir kayıt için cache'i temizle
Clear-DnsServerCache -Name "mail.firma.com.tr" -Force
Policy Sırası Problemi: Birden fazla policy varsa ProcessingOrder kritik. Daha spesifik kurallar daha düşük sayıya (daha yüksek önceliğe) sahip olmalı. Policy’leri listeleyin ve sırayı kontrol edin.
Conditional Forwarder Çakışması: Eğer DNS sunucunuzda firma.com.tr için bir conditional forwarder varsa, zone scope çalışmaz. Forwarder’ı kaldırmanız gerekiyor. Bu durumu tespit etmek için:
# Conditional forwarder'ları listele
Get-DnsServerZone | Where-Object {$_.ZoneType -eq "Forwarder"}
Zone Transfer Güvenliği: İç zone’unuzun zone transferine izin vermeyin. Dış DNS sunucusu iç zone’u keşfederse güvenlik problemi çıkar:
# Zone transfer'ı kısıtla
Set-DnsServerPrimaryZone -Name "firma.com.tr" -SecureSecondaries TransferToSecureServers
Monitoring ve Yönetim
Split Brain DNS yapısı kurulduktan sonra bunu izlemeniz gerekiyor. DNS Policy istatistiklerini şöyle alabilirsiniz:
# DNS istatistiklerini görüntüle
Get-DnsServerStatistics | Select-Object -ExpandProperty RecordStatistics
# Policy bazlı istatistik (varsa)
Get-DnsServerQueryResolutionPolicy -ZoneName "firma.com.tr" |
ForEach-Object {
Write-Host "Policy: $($_.Name)"
Write-Host "Processing Order: $($_.ProcessingOrder)"
Write-Host "Is Enabled: $($_.IsEnabled)"
Write-Host "---"
}
Ayrıca Windows Event Log’da DNS olaylarını takip edin. DNS Server olayları Applications and Services Logs > Microsoft > Windows > DNS-Server altında bulunuyor. Kritik policy hatalarını buradan yakalayabilirsiniz.
Rutin bakım için her ay şunu çalıştırmanızı öneririm: tüm zone scope kayıtlarını export edin, tarihli bir dosyaya kaydedin. Bir şeyler bozulduğunda geri dönüş noktanız olsun:
# Zone scope kayıtlarını export et
$ExportPath = "C:DNS-Backup$(Get-Date -Format 'yyyy-MM-dd')"
New-Item -ItemType Directory -Path $ExportPath -Force
Get-DnsServerResourceRecord -ZoneName "firma.com.tr" -ZoneScope "Internal" |
Export-Clixml -Path "$ExportPathInternal-Scope-Records.xml"
Get-DnsServerResourceRecord -ZoneName "firma.com.tr" -ZoneScope "." |
Export-Clixml -Path "$ExportPathDefault-Scope-Records.xml"
Write-Host "Backup completed: $ExportPath"
Güvenlik Notları
Split Brain DNS’in güvenlik boyutunu da göz ardı etmeyin:
- İç zone kayıtlarını minimum tutun. Sadece gerçekten ihtiyaç duyulan subdomain’leri iç scope’a ekleyin. Her iç IP adresini DNS’e açmak gerekmiyor.
- DNSSEC kullanıyorsanız split brain ile birlikte configure edilmesi karmaşık. Her scope için ayrı signing yapılması gerekiyor.
- Firewall kurallarınız DNS ile tutarlı olmalı. DNS iç IP’yi söylüyor ama firewall o trafiği bloke ediyorsa sorun çıkar. Bu tutarsızlıkları düzenli olarak gözden geçirin.
- Log kaydını aktif tutun. DNS debug logging’i production’da açık bırakmayın ama sorun anında hızlıca açıp kapayabilecek şekilde hazır olun.
Sonuç
Split Brain DNS, doğru yapılandırıldığında hem güvenlik hem de performans açısından önemli kazanımlar sağlıyor. İç kullanıcılar hairpin NAT’tan kurtulup doğrudan iç sunuculara ulaşıyor, dış kullanıcılar doğal olarak public IP’lere yönlendiriliyor. VPN kullanmayan çalışanlar için bile iç kaynakların doğru DNS yanıtı vermesi sağlanmış oluyor.
Windows Server 2016 ve sonrasında Zone Scope yaklaşımını kesinlikle tercih edin. PowerShell ile yönetimi kolay, scriptlenebilir ve audit edilebilir. Eski yöntemler artık gereksiz karmaşıklık yaratıyor.
Son olarak şunu vurgulayayım: bu yapıyı kurduktan sonra dokümantasyonunu hemen yazın. Birkaç ay sonra başka bir sysadmin ya da sizin kendiniz “bu neden böyle çalışıyor” diye saatler harcayabilirsiniz. Hangi subnet’lerin Internal scope’a yönlendirildiğini, hangi kayıtların hangi IP’ye gittiğini, policy sırasını yazılı hale getirin. DNS sorunları gece 02:00’de ortaya çıkar ve o saatte kafanız çalışmaz.
