Windows ortamlarında güvenlik duvarı yönetimi, çoğu sysadmin’in GUI üzerinden halletmeye çalıştığı ama ölçeklenince kabusu haline gelen bir iş. Onlarca sunucuda aynı kuralı tek tek tıklamak yerine PowerShell ile bunu dakikalar içinde halledebilirsiniz. Bu yazıda Windows Firewall kurallarını PowerShell ile nasıl yönetebileceğinizi, gerçek dünya senaryolarıyla birlikte ele alacağız.
Neden PowerShell ile Firewall Yönetimi?
GUI üzerinden firewall yönetimi küçük ortamlar için kabul edilebilir, ancak 20-30 sunucunuz olduğunda ya da tutarlı kural seti uygulamanız gerektiğinde işler karmaşıklaşır. PowerShell size şu avantajları sunar:
- Tekrarlanabilirlik: Aynı kural setini yüzlerce sunucuya aynı şekilde uygulayabilirsiniz
- Versiyon kontrolü: Script’lerinizi Git’te tutarak hangi kuralın ne zaman eklendiğini takip edebilirsiniz
- Otomasyon: Yeni sunucu provisioning süreçlerine entegre edebilirsiniz
- Denetim: Mevcut kuralları export edip karşılaştırabilirsiniz
Windows Firewall yönetimi için iki temel cmdlet ailesi var: eski netsh komutları ve modern NetSecurity modülü. Biz modern yaklaşımı kullanacağız çünkü Windows Server 2012 R2 ve sonrasında gayet iyi çalışıyor.
Temel Kavramlar ve Modül Hazırlığı
PowerShell üzerinde firewall yönetimi için NetSecurity modülü kullanılır. Bu modül Windows Server ve Windows 10/11 üzerinde varsayılan olarak gelir, ayrıca bir şey kurmanıza gerek yoktur.
# Mevcut firewall cmdlet'lerini listele
Get-Command -Module NetSecurity
# Modülün yüklü olduğunu doğrula
Get-Module -ListAvailable -Name NetSecurity
Firewall kurallarında üç temel profil vardır:
- Domain: Makine domain’e bağlıyken aktif olan profil
- Private: Ev veya ofis ağı olarak işaretlenmiş ağlarda aktif
- Public: Genel ağlarda, kafede veya havalimanında bağlanıldığında aktif
Bu profil ayrımını anlamamak, “kural ekledim ama neden çalışmıyor” şikayetlerinin en büyük sebebidir.
Mevcut Firewall Kurallarını Görüntüleme
Önce mevcut durumu anlamak lazım. Sisteminizde kaç tane kural var, hangileri aktif, hangisi ne yapıyor?
# Tüm firewall kurallarını listele
Get-NetFirewallRule
# Sadece aktif kuralları göster
Get-NetFirewallRule -Enabled True
# Belirli bir kurala ait detayları getir
Get-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)"
# Kuralları daha okunabilir formatta göster
Get-NetFirewallRule | Select-Object DisplayName, Direction, Action, Enabled, Profile | Format-Table -AutoSize
# Inbound ve enabled olan kuralları filtrele
Get-NetFirewallRule -Direction Inbound -Enabled True | Select-Object DisplayName, Action, Profile
Burada dikkat etmeniz gereken şey: Get-NetFirewallRule size port bilgisini doğrudan göstermez. Port bilgisi için ayrı bir cmdlet kullanmanız gerekir.
# Kural adı ve port bilgisini birlikte getir
Get-NetFirewallRule -Enabled True | ForEach-Object {
$rule = $_
$portFilter = $rule | Get-NetFirewallPortFilter
[PSCustomObject]@{
DisplayName = $rule.DisplayName
Direction = $rule.Direction
Action = $rule.Action
LocalPort = $portFilter.LocalPort
Protocol = $portFilter.Protocol
Enabled = $rule.Enabled
}
} | Where-Object { $_.LocalPort -ne "Any" } | Sort-Object LocalPort
Bu script biraz yavaş çalışır çünkü her kural için ayrı sorgu yapıyor, ama sonuç olarak hangi portların açık olduğunu net biçimde görürsünüz.
Yeni Firewall Kuralı Oluşturma
Basit Inbound Kural Oluşturma
En sık yapılan işlem: belirli bir porta izin vermek.
# HTTP trafiğine izin ver
New-NetFirewallRule `
-DisplayName "Allow HTTP Inbound" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 80 `
-Action Allow `
-Profile Domain,Private `
-Enabled True
# HTTPS trafiğine izin ver
New-NetFirewallRule `
-DisplayName "Allow HTTPS Inbound" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 443 `
-Action Allow `
-Profile Domain,Private,Public `
-Enabled True
# Belirli bir uygulamaya izin ver
New-NetFirewallRule `
-DisplayName "Allow Custom App" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 8080 `
-Action Allow `
-Program "C:AppsMyAppmyapp.exe" `
-Enabled True
New-NetFirewallRule cmdlet’inin önemli parametreleri:
- -DisplayName: Kuralın görünen adı, anlamlı bir isim verin
- -Direction:
InboundveyaOutbound - -Protocol:
TCP,UDP,ICMP,Any - -LocalPort: Port numarası, port aralığı (1000-2000) veya
Any - -RemoteAddress: Kaynağı IP ile kısıtlamak için
- -Action:
AllowveyaBlock - -Profile:
Domain,Private,Publicveya bunların kombinasyonu - -Program: Kural belirli bir uygulamaya uygulanacaksa exe yolu
- -Enabled:
TrueveyaFalse - -Description: Kuralın amacını açıklayan metin, ileride size çok yardımcı olur
IP Adresi Kısıtlı Kural Oluşturma
Güvenlik açısından en iyi pratik, mümkün olduğunca kaynağı kısıtlamaktır. “Her yerden SSH açık” yerine “sadece jump server’dan SSH açık” demek çok daha güvenlidir.
# Sadece belirli IP'den gelen RDP trafiğine izin ver
New-NetFirewallRule `
-DisplayName "Allow RDP from Jump Server" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3389 `
-RemoteAddress "10.0.1.50" `
-Action Allow `
-Profile Domain `
-Enabled True `
-Description "RDP only allowed from Jump Server 10.0.1.50 - Added by sysadmin team"
# Bir subnet'ten gelen yönetim trafiğine izin ver
New-NetFirewallRule `
-DisplayName "Allow Management Subnet" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 22,3389,5985,5986 `
-RemoteAddress "192.168.100.0/24" `
-Action Allow `
-Profile Domain,Private `
-Enabled True
Mevcut Kuralları Güncelleme
Var olan bir kuralı silip yeniden oluşturmak yerine Set-NetFirewallRule ile güncelleyebilirsiniz. Bu özellikle script idempotency için önemlidir.
# Kuralı devre dışı bırak
Set-NetFirewallRule -DisplayName "Allow HTTP Inbound" -Enabled False
# Kuralın action'ını değiştir
Set-NetFirewallRule -DisplayName "Allow HTTP Inbound" -Action Block
# Port ekle veya değiştir
Set-NetFirewallRule -DisplayName "Allow Custom App" -LocalPort 8080,8443
# Profile güncelle
Set-NetFirewallRule -DisplayName "Allow HTTP Inbound" -Profile Domain,Private,Public
# Birden fazla özelliği aynı anda güncelle
Set-NetFirewallRule `
-DisplayName "Allow RDP from Jump Server" `
-RemoteAddress "10.0.1.50","10.0.1.51" `
-Enabled True `
-Description "Updated: Added secondary jump server"
Firewall Kuralı Silme
# İsme göre sil
Remove-NetFirewallRule -DisplayName "Allow HTTP Inbound"
# DisplayGroup'a göre toplu sil
Remove-NetFirewallRule -DisplayGroup "My Custom Rules"
# Devre dışı olan tüm kuralları sil (dikkatli kullanın!)
Get-NetFirewallRule -Enabled False | Remove-NetFirewallRule
# Onay adımı ekleyerek sil
Remove-NetFirewallRule -DisplayName "Allow HTTP Inbound" -Confirm
Silme işlemlerinde her zaman önce Get-NetFirewallRule ile neyi sileceğinizi doğrulayın. Özellikle toplu silme işlemlerinde “önce listele, sonra sil” prensibini uygulayın.
Gerçek Dünya Senaryo 1: Web Sunucusu Sertleştirme
Yeni bir IIS sunucusu kuruyorsunuz ve sadece gerekli portları açık bırakmak istiyorsunuz. İşte bunu yapacak bir script:
# Web Sunucusu Firewall Konfigürasyonu
# Tüm gereksiz kuralları devre dışı bırak, sadece gerekenleri aç
$logPath = "C:LogsFirewallConfig_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param($Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp - $Message" | Tee-Object -FilePath $logPath -Append
}
Write-Log "Web sunucusu firewall konfigürasyonu basliyor..."
# Mevcut custom kuralları temizle
$existingRules = Get-NetFirewallRule -DisplayGroup "WebServer-Custom" -ErrorAction SilentlyContinue
if ($existingRules) {
$existingRules | Remove-NetFirewallRule
Write-Log "Mevcut WebServer-Custom kurallari temizlendi"
}
# HTTP
New-NetFirewallRule `
-DisplayName "WebServer - HTTP" `
-DisplayGroup "WebServer-Custom" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 80 `
-Action Allow `
-Profile Domain,Private `
-Enabled True `
-Description "IIS HTTP traffic"
Write-Log "HTTP kurali eklendi"
# HTTPS
New-NetFirewallRule `
-DisplayName "WebServer - HTTPS" `
-DisplayGroup "WebServer-Custom" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 443 `
-Action Allow `
-Profile Domain,Private,Public `
-Enabled True `
-Description "IIS HTTPS traffic"
Write-Log "HTTPS kurali eklendi"
# Yonetim portlari sadece management subnet'ten
New-NetFirewallRule `
-DisplayName "WebServer - WinRM Management" `
-DisplayGroup "WebServer-Custom" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 5985,5986 `
-RemoteAddress "10.0.100.0/24" `
-Action Allow `
-Profile Domain `
-Enabled True `
-Description "WinRM only from management subnet"
Write-Log "WinRM yonetim kurali eklendi"
# RDP sadece jump server'dan
New-NetFirewallRule `
-DisplayName "WebServer - RDP Restricted" `
-DisplayGroup "WebServer-Custom" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3389 `
-RemoteAddress "10.0.1.10" `
-Action Allow `
-Profile Domain `
-Enabled True `
-Description "RDP only from jump server"
Write-Log "RDP kisitli erisim kurali eklendi"
Write-Log "Konfigürasyon tamamlandi. Log: $logPath"
Gerçek Dünya Senaryo 2: Toplu Sunucu Yönetimi
Birden fazla sunucuya aynı kuralı uygulamak için Invoke-Command kullanabilirsiniz:
# Birden fazla sunucuya firewall kuralı dağıt
$servers = @("WEB01", "WEB02", "WEB03", "APP01", "APP02")
$credential = Get-Credential -Message "Sunucu admin bilgileri"
$firewallScript = {
# Her sunucuda çalışacak script bloğu
$ruleName = "Allow Monitoring Agent"
# Kural zaten varsa güncelle, yoksa oluştur
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
if ($existingRule) {
Set-NetFirewallRule `
-DisplayName $ruleName `
-RemoteAddress "10.0.200.10","10.0.200.11" `
-Enabled True
Write-Output "$env:COMPUTERNAME - Kural guncellendi"
} else {
New-NetFirewallRule `
-DisplayName $ruleName `
-Direction Inbound `
-Protocol TCP `
-LocalPort 9100,9182 `
-RemoteAddress "10.0.200.10","10.0.200.11" `
-Action Allow `
-Profile Domain `
-Enabled True `
-Description "Prometheus/monitoring agent access"
Write-Output "$env:COMPUTERNAME - Kural olusturuldu"
}
}
# Tüm sunuculara uygula ve sonuçları topla
$results = Invoke-Command `
-ComputerName $servers `
-Credential $credential `
-ScriptBlock $firewallScript
$results | ForEach-Object { Write-Host $_ }
Firewall Durumunu Denetleme ve Raporlama
Düzenli denetim çok önemli. “Birileri elle kural eklemiş mi?” sorusunun cevabını bulmak için bir baseline ile karşılaştırma yapabilirsiniz.
# Firewall kurallarını CSV olarak export et (baseline almak için)
$exportPath = "C:ReportsFirewallBaseline_$(Get-Date -Format 'yyyyMMdd').csv"
Get-NetFirewallRule -Enabled True | ForEach-Object {
$rule = $_
$portFilter = $rule | Get-NetFirewallPortFilter
$addressFilter = $rule | Get-NetFirewallAddressFilter
[PSCustomObject]@{
DisplayName = $rule.DisplayName
Direction = $rule.Direction
Action = $rule.Action
Protocol = $portFilter.Protocol
LocalPort = $portFilter.LocalPort
RemoteAddress = $addressFilter.RemoteAddress
Profile = $rule.Profile
Enabled = $rule.Enabled
Description = $rule.Description
}
} | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8
Write-Host "Baseline kaydedildi: $exportPath"
# Firewall profillerinin durumunu kontrol et
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction
Bu export’u düzenli aldığınızda iki export arasındaki farkları Compare-Object ile bulabilirsiniz. Beklenmedik kural eklenmişse hemen görürsünüz.
Firewall Profilini Etkinleştirme ve Yapılandırma
Profil seviyesindeki ayarlar da PowerShell ile yönetilebilir:
# Tüm profilleri etkinleştir
Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled True
# Default inbound action'ı block yap (en güvenli ayar)
Set-NetFirewallProfile -Profile Domain,Private,Public `
-DefaultInboundAction Block `
-DefaultOutboundAction Allow
# Log ayarları
Set-NetFirewallProfile -Profile Domain `
-LogFileName "C:WindowsSystem32LogFilesFirewallpfirewall.log" `
-LogMaxSizeKilobytes 32767 `
-LogBlocked True `
-LogAllowed False
# Profil durumunu kontrol et
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, LogBlocked, LogFileName
Dropped paketleri loglamak (-LogBlocked True) başlangıçta fazla log üretir gibi görünse de güvenlik olaylarını takip etmek için kritiktir. Özellikle bir sunucuda beklenmedik bağlantı denemeleri varsa bunu bu loglardan anlarsınız.
ICMP (Ping) Kurallarını Yönetme
Ağ troubleshooting’de ping çok kritik ama çoğu ortamda gereksiz yere kapalı ya da tamamen açık bırakılmış olur:
# Sadece belirli subnet'ten ping'e izin ver
New-NetFirewallRule `
-DisplayName "Allow ICMP from Management Network" `
-Direction Inbound `
-Protocol ICMPv4 `
-IcmpType 8 `
-RemoteAddress "10.0.0.0/8" `
-Action Allow `
-Profile Domain,Private `
-Enabled True
# Tüm ICMP'yi engelle
New-NetFirewallRule `
-DisplayName "Block All ICMP Inbound" `
-Direction Inbound `
-Protocol ICMPv4 `
-Action Block `
-Profile Public `
-Enabled True
Sık Yapılan Hatalar ve Çözümleri
Yıllar içinde gördüğüm en yaygın hatalar:
- Profil seçmeyi unutmak: Kural oluştururken
-Profilebelirtmezseniz varsayılan olarak tüm profillere uygulanır. Çoğu zaman bu istemediğiniz bir durum olur.
- Kural önceliğini anlamamak: Windows Firewall’da “Block” kuralı her zaman “Allow” kuralını geçersiz kılar. Birbirine çelişen kurallar varsa block olan kazanır.
- Description yazmamak: Altı ay sonra “Bu kural ne için?” diye kendine sorarken içi boş description alanına bakacaksınız. Her kurala açıklayıcı bir description yazın.
- Test etmeden production’a uygulamak: Özellikle block kurallarını test ortamında doğrulayın. Yanlış yapılandırılmış bir firewall kuralı sizi sunucudan tamamen koparabilir.
- Çakışan kuralları fark etmemek: Eski ve yeni kurallar çakıştığında beklenmedik davranışlar olabilir. Düzenli olarak
Get-NetFirewallRuleile kural setinizi gözden geçirin.
Sonuç
PowerShell ile Windows Firewall yönetimi, GUI’ye kıyasla başlangıçta daha fazla öğrenme eğrisi gerektirse de uzun vadede çok daha kontrol edilebilir ve ölçeklenebilir bir ortam sağlar. Bu yazıda ele aldığımız konuları özetlersek:
Temel kural yönetimi için New-NetFirewallRule, Set-NetFirewallRule, Get-NetFirewallRule ve Remove-NetFirewallRule cmdlet’leri ihtiyacınızın büyük çoğunluğunu karşılar. Profil yönetimi için Set-NetFirewallProfile ve Get-NetFirewallProfile kullanın.
Gerçek dünya ortamlarında en çok işinize yarayacak pratikler şunlardır: Her kural değişikliğini script olarak tutun ve versiyon kontrolüne alın. Baseline alın ve düzenli karşılaştırmalar yapın. Toplu değişiklikler için Invoke-Command ile remote execution kullanın. Ve her zaman “en az yetki” prensibini uygulayın, yani kural yazarken mümkün olduğunca kaynak IP kısıtlaması ekleyin.
Firewall yönetimi salt teknik bir konu değil, aynı zamanda bir disiplin meselesi. “Açık bırakayım, sorun çıkınca düşünürüm” yaklaşımı güvenlik olaylarının davetiyesidir. PowerShell’i araç olarak, en az yetki prensibini de felsefe olarak benimsediğinizde Windows ortamlarınız çok daha güvenli bir hale gelir.