PowerShell ile Windows Firewall Kuralları Yönetimi

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: Inbound veya Outbound
  • -Protocol: TCP, UDP, ICMP, Any
  • -LocalPort: Port numarası, port aralığı (1000-2000) veya Any
  • -RemoteAddress: Kaynağı IP ile kısıtlamak için
  • -Action: Allow veya Block
  • -Profile: Domain, Private, Public veya bunların kombinasyonu
  • -Program: Kural belirli bir uygulamaya uygulanacaksa exe yolu
  • -Enabled: True veya False
  • -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 -Profile belirtmezseniz 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-NetFirewallRule ile 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.

Yorum yapın