Windows Güvenlik Duvarı ile Gelişmiş Kural Yönetimi

Ağ güvenliğinde en çok ihmal edilen ama aslında en kritik katmanlardan biri, doğru yapılandırılmış bir güvenlik duvarıdır. Windows ortamlarında çalışan sysadminlerin büyük çoğunluğu Windows Güvenlik Duvarı’nı ya tamamen devre dışı bırakır ya da varsayılan ayarlarla bırakır. Bu yaklaşımın ne kadar tehlikeli olduğunu, özellikle Active Directory ortamlarında veya internete açık sunucularda çok net görürsünüz. Bu yazıda Windows Güvenlik Duvarı’nın gelişmiş kural yönetimini, PowerShell ile otomasyon senaryolarını ve gerçek dünyadan örnekleri ele alacağız.

Windows Güvenlik Duvarının Temel Mantığı

Windows Güvenlik Duvarı (Windows Defender Firewall with Advanced Security), üç farklı profil üzerinden çalışır:

  • Domain profili: Bilgisayar domain’e bağlıyken aktif olur
  • Private profil: Ev veya ofis ağı olarak işaretlenmiş ağlarda aktif olur
  • Public profil: Kafeler, havalimanları gibi güvenilmeyen ağlarda aktif olur

Bu profil yapısını anlamadan kural yazarsanız, yazdığınız kural yanlış profilde aktif olabilir ve beklediğiniz sonucu alamazsınız. Örneğin domain join edilmiş bir sunucuya yazdığınız kuralı sadece Domain profiline uygulamanız gerekir. Public profilini de açarsanız sunucunuz bir anda beklenmedik bir ağda açık hale gelebilir.

Güvenlik duvarı kuralları iki yönlü çalışır:

  • Inbound (Gelen): Dışarıdan sunucuya gelen bağlantıları kontrol eder
  • Outbound (Giden): Sunucudan dışarıya giden bağlantıları kontrol eder

Çoğu admin sadece Inbound kurallarını yazar ama Outbound kontrolü de kritiktir. Bir saldırgan sunucunuza sızdığında genellikle ilk iş reverse shell açmaya çalışır, yani outbound bağlantı kurar. Outbound kurallarınız sıkıysa bu girişim başarısız olur.

netsh ile Klasik Kural Yönetimi

Eski usul ama hala işe yarayan netsh komutlarıyla başlayalım. Özellikle eski sistemlerde veya script uyumluluğu gereken durumlarda netsh kullanmak zorunda kalabilirsiniz.

# Mevcut tüm firewall kurallarını listele
netsh advfirewall firewall show rule name=all

# Belirli bir kuralı görüntüle
netsh advfirewall firewall show rule name="Web Sunucusu HTTP"

# Domain profili durumunu kontrol et
netsh advfirewall show domainprofile

# Tüm profillerin durumunu göster
netsh advfirewall show allprofiles

Yeni kural eklemek için şu sözdizimini kullanırsınız:

# TCP 8080 portunu sadece belirli bir IP'den kabul et
netsh advfirewall firewall add rule ^
  name="Uygulama Sunucusu 8080" ^
  dir=in ^
  action=allow ^
  protocol=TCP ^
  localport=8080 ^
  remoteip=192.168.10.50 ^
  profile=domain ^
  enable=yes

# Outbound kuralı: DNS sorgularına sadece belirli sunuculara izin ver
netsh advfirewall firewall add rule ^
  name="DNS Outbound Kural" ^
  dir=out ^
  action=allow ^
  protocol=UDP ^
  remoteport=53 ^
  remoteip=192.168.1.10,192.168.1.11 ^
  profile=domain,private

# Mevcut bir kuralı sil
netsh advfirewall firewall delete rule name="Eski Kural"

netsh ile çalışırken dikkat etmeniz gereken nokta, kural adlarının büyük/küçük harf duyarlı olmadığı ama boşluk içeriyorsa tırnak işareti gerektirdiğidir.

PowerShell ile Modern Kural Yönetimi

PowerShell’deki NetSecurity modülü çok daha esnek ve okunaklı bir yönetim imkanı sunar. Windows Server 2012 ve sonrasında bu modül zaten yüklü gelir.

# Modülü kontrol et
Get-Module -ListAvailable -Name NetSecurity

# Tüm aktif inbound kurallarını listele
Get-NetFirewallRule -Direction Inbound -Enabled True | 
  Select-Object Name, DisplayName, Action, Profile |
  Format-Table -AutoSize

# Belirli bir porta ait kuralları bul
Get-NetFirewallRule | 
  Get-NetFirewallPortFilter | 
  Where-Object { $_.LocalPort -eq "3389" } |
  Get-NetFirewallRule | 
  Select-Object DisplayName, Enabled, Profile, Direction, Action

Yeni kural oluşturmak çok daha temiz bir syntax sunar:

# SQL Server'a sadece uygulama sunucularından erişime izin ver
New-NetFirewallRule `
  -DisplayName "SQL Server - App Tier Only" `
  -Direction Inbound `
  -Protocol TCP `
  -LocalPort 1433 `
  -RemoteAddress "192.168.20.0/24" `
  -Action Allow `
  -Profile Domain `
  -Enabled True `
  -Description "Uygulama katmanından SQL erişimi - 2024-01-15"

# Bir uygulama için outbound kural oluştur
New-NetFirewallRule `
  -DisplayName "Chrome Outbound Block" `
  -Direction Outbound `
  -Program "C:Program FilesGoogleChromeApplicationchrome.exe" `
  -Action Block `
  -Profile Domain `
  -Enabled True

Var olan kuralları güncellemek için Set-NetFirewallRule kullanırsınız:

# Var olan bir kuralı devre dışı bırak
Set-NetFirewallRule -DisplayName "SQL Server - App Tier Only" -Enabled False

# Kuralın IP aralığını güncelle
Set-NetFirewallRule `
  -DisplayName "SQL Server - App Tier Only" `
  -RemoteAddress "192.168.20.0/24","192.168.30.0/24"

# Kuralı tamamen kaldır
Remove-NetFirewallRule -DisplayName "SQL Server - App Tier Only"

Gerçek Dünya Senaryosu 1: Web Sunucusu Sertleştirme

Diyelim ki internete açık bir IIS web sunucunuz var. Varsayılan Windows Güvenlik Duvarı ayarlarıyla çalışıyor ve ciddi riskler taşıyor. Şu adımları uygularsınız:

# Önce mevcut inbound kurallarını temizle ve sıfırdan başla
# DİKKAT: Bunu RDP bağlantısını kesmeden önce test ortamında dene

# Gerekli portları aç
$rules = @(
    @{Name="HTTP-80"; Port=80; Protocol="TCP"},
    @{Name="HTTPS-443"; Port=443; Protocol="TCP"},
    @{Name="RDP-Yonetim"; Port=3389; Protocol="TCP"}
)

foreach ($rule in $rules) {
    New-NetFirewallRule `
        -DisplayName "WEB-$($rule.Name)" `
        -Direction Inbound `
        -Protocol $rule.Protocol `
        -LocalPort $rule.Port `
        -Action Allow `
        -Profile Domain,Private,Public `
        -Enabled True
}

# RDP'yi sadece yönetim ağından erişime aç
Set-NetFirewallRule `
    -DisplayName "WEB-RDP-Yonetim" `
    -RemoteAddress "10.0.100.0/24"

# ICMP'yi sadece iç ağdan kabul et (monitoring için)
New-NetFirewallRule `
    -DisplayName "ICMP-Ping-Internal" `
    -Direction Inbound `
    -Protocol ICMPv4 `
    -IcmpType 8 `
    -RemoteAddress "10.0.0.0/8","192.168.0.0/16" `
    -Action Allow `
    -Profile Domain,Private

# Tüm diğer inbound trafiği engelle (Default Deny)
Set-NetFirewallProfile -Profile Domain,Private,Public -DefaultInboundAction Block

Bu script’i çalıştırdığınızda sunucunuz sadece 80, 443 ve belirli IP’lerden 3389 portuna cevap verir hale gelir. Default Deny yaklaşımı güvenliğin temelidir.

Gerçek Dünya Senaryosu 2: Active Directory Ortamında Port Yönetimi

AD ortamında çalışıyorsanız Domain Controller’lara erişimi kontrol etmek çok kritiktir. Saldırganların ilk hedefi her zaman DC’lerdir.

# DC'ye gerekli portları tanımla - bu listeyi bir değişkende tut
$dcPorts = @{
    "Kerberos-TCP"    = @{Port="88";   Protocol="TCP"}
    "Kerberos-UDP"    = @{Port="88";   Protocol="UDP"}
    "LDAP-TCP"        = @{Port="389";  Protocol="TCP"}
    "LDAPS-TCP"       = @{Port="636";  Protocol="TCP"}
    "SMB-TCP"         = @{Port="445";  Protocol="TCP"}
    "RPC-Endpoint"    = @{Port="135";  Protocol="TCP"}
    "DNS-TCP"         = @{Port="53";   Protocol="TCP"}
    "DNS-UDP"         = @{Port="53";   Protocol="UDP"}
    "GC-LDAP"         = @{Port="3268"; Protocol="TCP"}
    "GC-LDAPS"        = @{Port="3269"; Protocol="TCP"}
    "NetLogon-UDP"    = @{Port="138";  Protocol="UDP"}
}

# Sadece iç ağdan bu portlara izin ver
$internalNetworks = "10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"

foreach ($ruleName in $dcPorts.Keys) {
    $port = $dcPorts[$ruleName]
    New-NetFirewallRule `
        -DisplayName "DC-$ruleName" `
        -Direction Inbound `
        -Protocol $port.Protocol `
        -LocalPort $port.Port `
        -RemoteAddress $internalNetworks `
        -Action Allow `
        -Profile Domain `
        -Enabled True
    
    Write-Host "Kural olusturuldu: DC-$ruleName" -ForegroundColor Green
}

RPC dinamik port aralığını da yönetmeniz gerekebilir. AD replication ve bazı servisler rastgele portlar kullanır, bunları sınırlamak iyi bir pratiktir:

# RPC dinamik port aralığını kısıtla
netsh int ipv4 set dynamicport tcp start=49152 num=16384
netsh int ipv4 set dynamicport udp start=49152 num=16384

# Bu aralığı güvenlik duvarında aç (sadece iç ağdan)
New-NetFirewallRule `
    -DisplayName "DC-RPC-Dynamic-Range" `
    -Direction Inbound `
    -Protocol TCP `
    -LocalPort "49152-65535" `
    -RemoteAddress "10.0.0.0/8" `
    -Action Allow `
    -Profile Domain `
    -Enabled True

Connection Security Rules (IPSec Entegrasyonu)

Windows Güvenlik Duvarı’nın az bilinen ama çok güçlü özelliği Connection Security Rules’tur. Bu kurallarla iki sunucu arasındaki trafiği şifreleyebilir ve kimlik doğrulaması yapabilirsiniz. Özellikle hassas veri taşıyan sunucular arası iletişimde kullanışlıdır.

# İki sunucu arasında IPSec ile şifreli iletişim kur
New-NetIPsecRule `
    -DisplayName "DB-AppServer IPSec" `
    -InboundSecurity Require `
    -OutboundSecurity Require `
    -LocalAddress "192.168.10.20" `
    -RemoteAddress "192.168.10.30" `
    -Phase1AuthSet "ComputerKerberosSet" `
    -Phase2AuthSet "ComputerKerberosSet"

# Mevcut IPSec kurallarını kontrol et
Get-NetIPsecRule | Select-Object DisplayName, Enabled, InboundSecurity, OutboundSecurity

# Connection security kuralını görüntüle
Get-NetIPsecMainModeSA | Format-List

Bu yapıyı domain ortamında Kerberos authentication ile birleştirdiğinizde, sadece domain üyesi bilgisayarların birbirleriyle konuşmasına izin vermiş olursunuz. Lateral movement açısından bu ciddi bir engel oluşturur.

Group Policy ile Merkezi Kural Dağıtımı

Onlarca sunucuya tek tek kural yazmak yerine GPO üzerinden merkezi yönetim çok daha mantıklıdır. PowerShell ile GPO’ya kural ekleyebilirsiniz:

# GPO modülünü yükle
Import-Module GroupPolicy

# Yeni bir GPO oluştur
$gpo = New-GPO -Name "Sunucu Güvenlik Duvarı Kuralları" -Domain "firma.local"

# GPO'yu OU'ya bağla
New-GPLink `
    -Name "Sunucu Güvenlik Duvarı Kuralları" `
    -Target "OU=Sunucular,DC=firma,DC=local"

# GPO firewall ayarlarını PowerShell ile değil, 
# GPMC üzerinden veya şu yolla yapılandır:
# Computer Configuration > Windows Settings > 
# Security Settings > Windows Defender Firewall with Advanced Security

GPO’da dikkat etmeniz gereken nokta, GPO kuralları ile lokal kuralların birleşerek çalışmasıdır. Eğer lokal kuralların GPO kurallarını override etmesini istemiyorsanız GPO üzerinden lokal kural birleştirmeyi devre dışı bırakabilirsiniz:

# GPO üzerinden lokal kural birleştirmeyi engelle
# Bu ayar Group Policy Management Console'dan yapılır
# Computer Config > Windows Settings > Security Settings > 
# WDFW with Advanced Security > Properties > Settings sekmesi
# "Apply local firewall rules" = No

Firewall Log Analizi ve Monitoring

Kural yazmak yeterli değil, logları da takip etmeniz gerekiyor. Aksi halde kimin neye bağlanmaya çalıştığını hiç bilemezsiniz.

# Firewall loglama'yı aktif et
Set-NetFirewallProfile -Profile Domain `
    -LogAllowed True `
    -LogBlocked True `
    -LogMaxSizeKilobytes 32767 `
    -LogFileName "C:WindowsSystem32LogFilesFirewallpfirewall.log"

# Log dosyasını PowerShell ile parse et
$logPath = "C:WindowsSystem32LogFilesFirewallpfirewall.log"
$logs = Get-Content $logPath | Where-Object { $_ -notmatch "^#" }

# Engellenen bağlantıları filtrele
$blockedConnections = $logs | Where-Object { $_ -match "DROP" }

# En çok bağlantı deneyen IP'leri bul
$blockedConnections | 
    ForEach-Object { ($_ -split " ")[4] } | 
    Group-Object | 
    Sort-Object Count -Descending | 
    Select-Object -First 20 |
    Format-Table Name, Count -AutoSize

Windows Event Log’dan da firewall olaylarını çekebilirsiniz:

# Security event log'dan firewall olaylarını çek
# Event ID 5152: Paket engellendi
# Event ID 5157: Bağlantı engellendi  
# Event ID 5156: Bağlantıya izin verildi

$events = Get-WinEvent -LogName Security -FilterXPath `
    "*[System[(EventID=5157)]]" `
    -MaxEvents 100

$events | 
    Select-Object TimeCreated, 
        @{N="SourceIP"; E={$_.Properties[3].Value}},
        @{N="DestPort"; E={$_.Properties[7].Value}},
        @{N="Protocol"; E={$_.Properties[9].Value}} |
    Format-Table -AutoSize

Kural Denetimi ve Temizlik Stratejisi

Zamanla güvenlik duvarı kuralları birikir ve kim ne için ekledi bilinmez hale gelir. Periyodik denetim şarttır.

# Devre dışı bırakılmış tüm kuralları listele
Get-NetFirewallRule -Enabled False | 
    Select-Object DisplayName, Direction, Profile, Action |
    Sort-Object Direction |
    Format-Table -AutoSize

# Hiç port filtresi olmayan kuralları bul (tüm portları açık)
Get-NetFirewallRule -Direction Inbound -Action Allow -Enabled True |
    ForEach-Object {
        $portFilter = $_ | Get-NetFirewallPortFilter
        if ($portFilter.LocalPort -eq "Any") {
            [PSCustomObject]@{
                RuleName = $_.DisplayName
                Profile  = $_.Profile
                Program  = ($_ | Get-NetFirewallApplicationFilter).Program
            }
        }
    } | Format-Table -AutoSize

# Kural export'u - backup için
$exportPath = "C:BackupFirewallRules_$(Get-Date -Format 'yyyyMMdd').wfw"
netsh advfirewall export $exportPath
Write-Host "Kurallar dışa aktarıldı: $exportPath" -ForegroundColor Green

# Import (geri yükleme)
# netsh advfirewall import $exportPath

Kurallarınızı belgelerken şu bilgileri mutlaka kaydedin:

  • Kural adı: Amaç ve tarih içermeli (örn: “SQL-AppTier-Access-20240115”)
  • Oluşturan: Kim ekledi
  • Neden eklendi: Hangi ticket veya ihtiyaç için
  • Son kullanma tarihi: Geçici kurallar için özellikle önemli

Sorun Giderme Senaryoları

Gerçek hayatta en çok karşılaşılan durum, “Şu uygulama çalışmıyor, güvenlik duvarını kapat” baskısıdır. Buna boyun eğmek yerine hangi portun sorun çıkardığını bulmanız gerekir.

# Test-NetConnection ile port kontrolü
Test-NetConnection -ComputerName "db-server-01" -Port 1433

# Daha detaylı trace ile
Test-NetConnection -ComputerName "db-server-01" -Port 1433 -InformationLevel Detailed

# Netstat ile aktif bağlantıları ve dinleyen portları gör
netstat -ano | findstr "LISTENING"
netstat -ano | findstr ":1433"

# Process ID'den hangi uygulamanın o portu kullandığını bul
$pid = (netstat -ano | findstr ":1433" | findstr "LISTENING").Trim().Split(" ")[-1]
Get-Process -Id $pid | Select-Object Name, Id, Path

Bir servisin hangi portları kullandığını tespit etmek için:

# Belirli bir process'in açtığı bağlantıları izle
$processName = "sqlservr"
$pid = (Get-Process -Name $processName).Id

netstat -ano | findstr $pid

# Sysinternals TCPView alternatifi PowerShell ile
Get-NetTCPConnection -State Listen | 
    ForEach-Object {
        $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
        [PSCustomObject]@{
            Port        = $_.LocalPort
            ProcessName = $proc.Name
            ProcessId   = $_.OwningProcess
            State       = $_.State
        }
    } | 
    Sort-Object Port |
    Format-Table -AutoSize

Windows Firewall ile Zero Trust Yaklaşımı

Modern güvenlik anlayışında “güvenilen iç ağ” kavramı artık geçerli değil. Zero Trust modelinde her bağlantı doğrulanmalı. Windows Güvenlik Duvarı’nı bu yaklaşımla yapılandırmak için:

  • Her sunucu kendi güvenlik duvarını yönetmeli: Merkezi bir ağ firewall’una güvenmek yeterli değil
  • Default Deny politikası: İzin listesinde olmayan her şey engellenir
  • Servis bazlı kural yazma: Uygulama adı veya binary path ile kural oluşturun
  • Zaman bazlı kurallar: Maintenance window dışında bazı portları kapatın
  • Geo-blocking: Türkiye dışından RDP erişimi gerekmiyorsa engellemeniz mantıklıdır (bunu genellikle ağ katmanında yaparsınız ama Windows Firewall da destekler)

Outbound trafik kontrolü için minimal yetki prensibi uygulayın. Bir web sunucusunun outbound olarak sadece şunlara ihtiyacı vardır: DNS (53), NTP (123), Windows Update (443), belki SMTP (25 veya 587). Bunlar dışındaki tüm outbound trafiği bloklamak, olası bir compromise sonrası saldırganın hareket alanını ciddi ölçüde kısıtlar.

Sonuç

Windows Güvenlik Duvarı, doğru yapılandırıldığında son derece güçlü bir savunma katmanıdır. Pek çok sysadmin bunu ya gereksiz görür ya da yapılandırması zor olduğu için devre dışı bırakır. Oysa bu yazıda gördüğünüz gibi PowerShell ile kural yönetimi oldukça anlaşılır ve otomatize edilebilir.

Özet olarak dikkat etmeniz gereken noktalar şunlardır:

  • Profil farkındalığı: Domain, Private ve Public profilleri farklı davranır, kurallarınızı doğru profile yazın
  • Default Deny: Sadece ihtiyaç duyulan trafiğe izin verin, geri kalanını engelleyin
  • Outbound kontrolü: Gelen trafiği kontrol etmek kadar giden trafiği de yönetin
  • Kural dokümantasyonu: Her kural nedenini ve kim tarafından eklendiğini belgelemeli
  • Periyodik temizlik: En az 6 ayda bir kural denetimi yapın, gereksiz kuralları silin
  • Log analizi: Firewall loglarını izlemeden kuralları yazmak körü körüne çalışmaktır
  • Test ortamı: Yeni kural setlerini production’a almadan önce mutlaka test edin

GPO entegrasyonu ile tüm sunucu filonuza merkezi kural dağıtımı yapabilir, tek bir PowerShell script’iyle yüzlerce sunucunun güvenlik durumunu kontrol edebilirsiniz. Bu seviyede bir otomasyon kurduğunuzda, bir güvenlik açığı tespit ettiğinizde tüm ağa anında müdahale edebilirsiniz.

Son olarak şunu söyleyeyim: Güvenlik duvarı kuralları ne kadar katı olursa, operasyonel sürtüşme de o kadar artar. Uygulama ekipleri, geliştiriciler ve sistem adminleri arasında düzenli iletişim kurarak bu sürtüşmeyi yönetin. Güvenliği kolaylığın önüne koymak doğru yaklaşımdır ama bunu bir iş birliği kültürüyle yaparsanız çok daha sürdürülebilir olur.

Yorum yapın