Windows Firewall ile Gelişmiş Gelen ve Giden Trafik Kuralları
Yıllar içinde kaç tane “firewall açık mı?” sorusunu Slack’te cevapladım bilemiyorum. Genelde arkasından şu gelir: “Bak ping atıyorum ama bağlanmıyorum.” Windows Firewall, yanlış anlaşılan ve çoğu zaman ya tamamen kapatılan ya da hiç dokunulmayan bir bileşen. Oysa düzgün yapılandırıldığında son derece güçlü bir araç. Bu yazıda sadece “şu kuralı ekle çalışır” seviyesinde değil, gerçekten ne yaptığını anlayarak firewall yönetimi yapmayı ele alacağız.
Windows Firewall’ın Gerçek Mimarisi
Çoğu sysadmin Windows Firewall’ı GUI üzerinden, “Windows Defender Firewall with Advanced Security” konsolundan yönetir. Bu konsol yeterli ama yetersiz. Altında yatan motor Windows Filtering Platform (WFP) denen ve Vista’dan beri var olan kernel-level bir filtreleme katmanı. Bunu bilmek neden önemli? Çünkü bazı güvenlik ürünleri (antivirüsler, VPN istemcileri) bu katmana doğrudan yazıyor ve kendi kurallarını firewall UI’da görmeden uyguluyorlar.
Üç profil var ve bunların farkını anlamak kritik:
- Domain Profile: Makine domain’e bağlıyken aktif. Active Directory ortamlarında kullanılan profil.
- Private Profile: Ev/iş ağı olarak işaretlenmiş ağlarda aktif.
- Public Profile: Tanımlanmamış, güvensiz ağlarda aktif. En kısıtlayıcı olması gerekir.
Bir makine birden fazla ağ arayüzüne bağlıysa, her arayüz kendi profiline göre davranır. Bunu unutup “domain profilinde açtım, neden çalışmıyor” diye saatler harcayanları gördüm.
netsh ve PowerShell: Hangi Zaman Hangisi?
İki temel komut satırı aracımız var. netsh advfirewall eski ama hala işlevsel. PowerShell’deki NetSecurity modülü ise çok daha esnek ve scripting için tercih edilmeli.
Mevcut durumu görmek için:
# Tüm profillerin durumunu göster
netsh advfirewall show allprofiles
# Sadece aktif profili göster
netsh advfirewall show currentprofile
# PowerShell ile profil durumu
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction
Şu çıktıya dikkat edin: DefaultInboundAction değeri Block olmalı, DefaultOutboundAction ise genelde Allow. Bu en temel güvenlik postürü. Eğer her ikisi de Allow görünüyorsa, o firewall sadece dekoratif amaçlı çalışıyor demektir.
Gelen Trafik Kuralları: Gerçek Dünya Senaryoları
Senaryo 1: Sadece Belirli IP Bloğundan RDP İzni
Klasik problem: RDP’yi internet’e açmak zorunda kalmak ama bunu en azından kaynak IP kısıtlamasıyla yapmak. Şirket VPN havuzunun IP aralığı 10.50.0.0/24 olsun:
# Önce varsa eski genel RDP kuralını devre dışı bırak
Set-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)" -Enabled False
# Yeni kısıtlı kural ekle
New-NetFirewallRule `
-DisplayName "RDP - VPN Havuzundan" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3389 `
-RemoteAddress "10.50.0.0/24" `
-Action Allow `
-Profile Domain,Private `
-Enabled True
Burada -Profile parametresine dikkat edin. Public profilde bu kuralın açık olmasını istemiyoruz.
Senaryo 2: Uygulama Bazlı Kural
Port bazlı kurallar yetersiz kalabilir. Aynı port üzerinden farklı uygulamalar konuşuyorsa, uygulamayı temel alan kural daha güvenli:
# Belirli bir executable için kural
New-NetFirewallRule `
-DisplayName "MyApp - Inbound" `
-Direction Inbound `
-Program "C:Program FilesMyAppmyapp.exe" `
-Action Allow `
-Profile Any `
-Enabled True
# Servis adına göre kural (örnek: SQL Server)
New-NetFirewallRule `
-DisplayName "SQL Server - Inbound" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 1433 `
-Service "MSSQLSERVER" `
-Action Allow `
-Enabled True
Senaryo 3: ICMP Kontrolü
Ping’i tamamen kapatmak yerine sadece belirli kaynaklardan izin vermek genelde daha mantıklı:
# Monitoring sunucusundan ping izni (192.168.1.10)
New-NetFirewallRule `
-DisplayName "ICMP Allow - Monitoring" `
-Direction Inbound `
-Protocol ICMPv4 `
-IcmpType 8 `
-RemoteAddress "192.168.1.10" `
-Action Allow `
-Enabled True
# Diğer tüm ICMP'yi engelle
New-NetFirewallRule `
-DisplayName "ICMP Block - All" `
-Direction Inbound `
-Protocol ICMPv4 `
-Action Block `
-Enabled True
Kural önceliği konusunda kritik bir not: Windows Firewall’da Block kuralları her zaman Allow kurallarını ezer. Yani iki kural çakışıyorsa Block olan kazanır. Bu yüzden yukarıdaki sıralama önemli değil ama bunu bilmek hata ayıklamada hayat kurtarır.
Giden Trafik Kuralları: Genelde Göz Ardı Edilen Kısım
Outbound kuralları çoğu ortamda default Allow’da bırakılıyor. Bu, içeriden dışarıya herhangi bir şeyin çıkabileceği anlamına geliyor. Sunucu güvenliği söz konusu olduğunda bu kabul edilemez bir yaklaşım.
Önce varsayılan outbound davranışını Block’a çevirip sonra gerekli servislere izin vermek doğru yaklaşım:
# Outbound default'u Block'a çevir
Set-NetFirewallProfile -Profile Domain,Private,Public `
-DefaultOutboundAction Block
# DNS'e izin ver
New-NetFirewallRule `
-DisplayName "Outbound - DNS" `
-Direction Outbound `
-Protocol UDP `
-RemotePort 53 `
-RemoteAddress "10.0.0.1","10.0.0.2" `
-Action Allow `
-Enabled True
# HTTP/HTTPS'e izin ver (update sunucusu için)
New-NetFirewallRule `
-DisplayName "Outbound - Windows Update" `
-Direction Outbound `
-Protocol TCP `
-RemotePort 80,443 `
-RemoteAddress "windowsupdate.microsoft.com" `
-Action Allow `
-Enabled True
# NTP
New-NetFirewallRule `
-DisplayName "Outbound - NTP" `
-Direction Outbound `
-Protocol UDP `
-RemotePort 123 `
-Action Allow `
-Enabled True
Bu yaklaşımı production’a almadan önce mutlaka test ortamında deneyin. “Her şeyi kısıtladım, ne gerekirse açarım” mantığı kulağa güzel geliyor ama kritik bir servisi unuttuğunuzda gece 2’de alarm alırsınız.
Group Policy ile Merkezi Yönetim
Tek tek sunuculara gidip kural yazmak ölçeklenmiyor. Active Directory ortamında GPO ile firewall kuralları dağıtmak standart yaklaşım olmalı.
GPO path: Computer Configuration > Windows Settings > Security Settings > Windows Defender Firewall with Advanced Security
Buradan kuralları GUI üzerinden ekleyebilirsiniz ama PowerShell ile export edip import etmek çok daha hızlı:
# Mevcut kuralları export et
$rules = Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Custom-*"}
$rules | Export-Csv -Path "C:firewall_rules_backup.csv" -NoTypeInformation
# Kural detaylarını daha kapsamlı export etmek için
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Custom-*"} | ForEach-Object {
$rule = $_
$portFilter = $rule | Get-NetFirewallPortFilter
$addressFilter = $rule | Get-NetFirewallAddressFilter
[PSCustomObject]@{
DisplayName = $rule.DisplayName
Direction = $rule.Direction
Protocol = $portFilter.Protocol
LocalPort = $portFilter.LocalPort
RemotePort = $portFilter.RemotePort
RemoteAddress = $addressFilter.RemoteAddress
Action = $rule.Action
Enabled = $rule.Enabled
}
} | Export-Csv -Path "C:firewall_rules_detail.csv" -NoTypeInformation
GPO’da “Security Filtering” ile belirli OU’lara, bilgisayar gruplarına farklı kural setleri uygulayabilirsiniz. Web sunucuları için bir GPO, veritabanı sunucuları için başka bir GPO. Bu yapıyı kurmak başta zaman alıyor ama sonrasında hayatınızı kolaylaştırıyor.
Logging ve Sorun Giderme
Firewall çalışıyor ama bir şey neden bloklanıyor anlamıyorsunuz? Logging aktif olmadan kör uçuş yapıyorsunuz.
# Log ayarlarını yapılandır
Set-NetFirewallProfile -Profile Domain,Private,Public `
-LogBlocked True `
-LogAllowed False `
-LogMaxSizeKilobytes 32767 `
-LogFileName "C:WindowsSystem32LogFilesFirewallpfirewall.log"
Sadece bloklanmış trafiği loglamak genelde yeterli. Tüm allowed trafiği de loglarsanız dosya hızla dolacaktır.
Log dosyasını analiz etmek için:
# Son 50 satırı getir
Get-Content "C:WindowsSystem32LogFilesFirewallpfirewall.log" -Tail 50
# Belirli IP adresinden gelen bloklanmış trafiği filtrele
Select-String -Path "C:WindowsSystem32LogFilesFirewallpfirewall.log" `
-Pattern "DROP.*192.168.5.100"
# Bloklanmış portları say ve sırala
$log = Get-Content "C:WindowsSystem32LogFilesFirewallpfirewall.log"
$log | Where-Object {$_ -match "^DROP"} |
ForEach-Object {($_ -split " ")[7]} |
Group-Object |
Sort-Object Count -Descending |
Select-Object -First 10
Bu log analizi, hangi portlara erişim denemeleri yapıldığını görmek için de kullanılabilir. Dışarıdan 22 numaralı porta sürekli bağlantı geliyorsa, birisi SSH servisi arıyor demektir.
Gelişmiş Kural Özellikleri: Az Bilinen Parametreler
Bağlantı Güvenliği Kuralları
Normal firewall kurallarından farklı olarak, bağlantı güvenliği kuralları (connection security rules) IPSec entegrasyonu sağlar. İki sunucu arasındaki trafiği şifrelemek ya da kimlik doğrulamak için kullanılır:
# İki sunucu arasında IPSec gerektiren bağlantı güvenliği kuralı
New-NetIPsecRule `
-DisplayName "DB-App Server IPSec" `
-InboundSecurity Require `
-OutboundSecurity Request `
-LocalAddress "10.0.1.20" `
-RemoteAddress "10.0.1.10" `
-Enabled True
Bu özellik çoğu ortamda kullanılmıyor ama sıfır güven mimarisine geçiş yapıyorsanız değerlendirilmesi gereken bir seçenek.
Edge Traversal
NAT arkasındaki makinelere Teredo gibi protokollerle erişim söz konusuysa edge traversal ayarı önem kazanır:
# Edge traversal kontrolü
New-NetFirewallRule `
-DisplayName "Test App Inbound" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 8080 `
-EdgeTraversalPolicy Allow `
-Action Allow
-EdgeTraversalPolicy parametresi üç değer alır:
- Block: Edge traversal’a izin vermez (varsayılan)
- Allow: Edge traversal’a izin verir
- DeferToApp: Uygulamanın kararına bırakır
Dinamik Anahtar Kelimeler
Windows 10/Server 2019 ile gelen bir özellik: Dinamik anahtar kelimeler sayesinde IP aralıkları bir kez tanımlanıp birden fazla kuralda kullanılabilir. Kural merkezi değiştirilince tüm kurallar güncellenir.
Bu özelliği New-NetFirewallDynamicKeywordAddress cmdlet’i ile kullanabilirsiniz ama şu an için Intune/MEM entegrasyonuyla daha çok anlam ifade ediyor.
Toplu Kural Yönetimi ve Temizlik
Zamanla birikmiş, ne işe yaradığı bilinmeyen kuralları temizlemek gerekebilir. Önce mevcut durumu anlayalım:
# Devre dışı bırakılmış tüm kuralları listele
Get-NetFirewallRule | Where-Object {$_.Enabled -eq "False"} |
Select-Object DisplayName, Direction, Action |
Format-Table -AutoSize
# "Custom-" prefix'i olmayan, default olmayan kuralları bul
Get-NetFirewallRule | Where-Object {
$_.Owner -eq $null -and
$_.DisplayName -notmatch "^(Core Networking|File and Printer|Remote Desktop|Windows)"
} | Select-Object DisplayName, Direction, Action
# Tüm custom kuralları temizle (dikkatli kullan!)
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Custom-*"} | Remove-NetFirewallRule
Bir naming convention belirlemek ve buna sadık kalmak, bu tür temizliklerde hayat kurtarır. Ben “Custom-“, “APP-“, “BLOCKED-” gibi prefix’ler kullanmayı tercih ediyorum. Kim ne zaman ekledi, ne için eklendi gibi bilgileri Description alanına yazmak da iyi pratik:
New-NetFirewallRule `
-DisplayName "APP-WebServer-HTTPS-In" `
-Description "2024-01 - Web sunucusu HTTPS trafiği - Ahmet K. tarafından eklendi" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 443 `
-Action Allow `
-Enabled True
Firewall Durumunu İzleme ve Otomatik Uyumluluk Kontrolü
Firewall kurallarının beklendiği gibi çalışıp çalışmadığını düzenli kontrol etmek önemli. Basit bir script ile bu kontrolü otomatize edebilirsiniz:
# Kritik kuralların aktif olup olmadığını kontrol et
$criticalRules = @(
"RDP - VPN Havuzundan",
"APP-WebServer-HTTPS-In",
"Outbound - DNS"
)
$report = foreach ($ruleName in $criticalRules) {
$rule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
[PSCustomObject]@{
RuleName = $ruleName
Exists = ($null -ne $rule)
Enabled = if ($rule) {$rule.Enabled} else {"N/A"}
Action = if ($rule) {$rule.Action} else {"N/A"}
}
}
$report | Format-Table -AutoSize
# Sorunlu kural varsa Event Log'a yaz
$problematic = $report | Where-Object {-not $_.Exists -or $_.Enabled -eq "False"}
if ($problematic) {
Write-EventLog -LogName Application -Source "FirewallCheck" `
-EventId 9001 -EntryType Warning `
-Message "Kritik firewall kuralları eksik veya devre dışı: $($problematic.RuleName -join ', ')"
}
Bu script’i Task Scheduler’a ekleyip günlük çalıştırabilirsiniz. Event Log entegrasyonu sayesinde SIEM sisteminiz bu olayları yakalayabilir.
Sık Yapılan Hatalar
Yıllar içinde en çok gördüğüm hatalar bunlar:
- Tüm profilleri aynı kurallarla yönetmek: Public profil çok daha kısıtlayıcı olmalı. Laptop’lar public WiFi’a bağlandığında domain kurallarıyla çalışmamalı.
- Block kuralını silmek yerine devre dışı bırakmak: Devre dışı bırakılan bir Block kuralı çalışmaz ama kafayı karıştırır. Kalıcı olarak istemiyorsanız silin.
- RemoteAddress olarak FQDN kullanmak: Firewall DNS çözümleme yapar ama bu gerçek zamanlı değil. IP değiştiğinde kural güncel kalmayabilir. Mümkünse IP aralıkları kullanın.
- Kural çakışmalarını test etmemek:
Test-NetConnectionvetracertkullanarak kural ekledikten sonra beklenen trafiğin gerçekten çalışıp çalışmadığını doğrulayın.
- Firewall’ı tamamen kapatmak: “Uygulama çalışmıyor, firewall mı engelliyordur” düşüncesiyle firewall’ı kapatmak ve unutmak. Production’da bu görüntüye şaşıracak kadar sık rastladım.
Sonuç
Windows Firewall, doğru yapılandırıldığında kurumsal düzeyde bir ağ güvenliği katmanı sağlayabilir. Temel mesele şu: Varsayılan ayarlarla bırakmak ya da “çalışmıyor” diye kapatmak değil, sistematik ve anlamlı kurallar oluşturmak.
En önemli çıkarımlar şunlar: Outbound trafiği de kontrol edin, sadece inbound yetmez. Logging’i açık tutun, olmadan sorun gidermek imkansız. GPO ile merkezi yönetin, sunucu sunucu gezip kural eklemeyin. İsimlendirme konvansiyonu belirleyin ve buna uyun.
Windows Filtering Platform’un derinliklerine indiğinizde çok daha fazlası var; callout driver’lar, sublayer’lar, provider context’ler. Ama günlük sysadmin hayatında burada anlattığım araçlar ve yaklaşımlar yüzde doksanı kapsıyor. Gerisini gerekince öğrenmek yeterli.
