RDP Güvenliğini Artırma ve Saldırıları Engelleme
Remote Desktop Protocol, Windows ortamlarında uzaktan yönetim için vazgeçilmez bir araç. Ama aynı zamanda saldırganların en çok hedef aldığı servislerden biri. Shodan’da “port:3389” araması yaptığınızda milyonlarca açık RDP portu göreceksiniz ve bunların büyük çoğunluğu ya varsayılan ayarlarla çalışıyor ya da hiç güvenlik yaması uygulanmamış durumda. Bu yazıda RDP güvenliğini katmanlı bir yaklaşımla nasıl güçlendireceğimizi, gerçek dünya saldırı senaryolarına karşı nasıl önlem alacağımızı ve saldırı girişimlerini nasıl tespit edip engelleyeceğimizi ele alacağız.
RDP Neden Bu Kadar Tehlikeli?
RDP’nin doğasında birkaç ciddi sorun var. Varsayılan olarak 3389 portu üzerinden çalışır, kimlik bilgisi tabanlı kimlik doğrulama kullanır ve internet üzerinden doğrudan erişilebilir durumdaysa brute force saldırılarına açık kapı bırakır. BlueKeep (CVE-2019-0708), DejaBlue gibi kritik güvenlik açıkları yıllar içinde ortaya çıktı ve yamalanmamış sistemlerde hala aktif olarak exploit ediliyor.
Tipik bir saldırı senaryosu şöyle işliyor: Saldırgan internete açık 3389 portunu tarıyor, bulduğu hedefte credential stuffing veya brute force saldırısı başlatıyor, başarılı girişin ardından sistemde persistence sağlıyor ve lateral movement yapıyor. Bu zinciri kırmak için her halkaya müdahale etmemiz gerekiyor.
Temel Güvenlik Adımları
Varsayılan Portu Değiştirme
İlk adım olarak RDP’nin varsayılan portunu değiştirmek, tam bir güvenlik çözümü değil ama otomatik tarayıcıların büyük çoğunluğunu engeller. Script kiddie seviyesindeki saldırıları ciddi ölçüde azaltır.
# Registry üzerinden RDP portunu değiştirme
$portNumber = 33890
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "PortNumber" -Value $portNumber -Type DWord
# Windows Firewall kuralını güncelleme
New-NetFirewallRule -DisplayName "RDP Custom Port" `
-Direction Inbound `
-Protocol TCP `
-LocalPort $portNumber `
-Action Allow
# Eski varsayılan kuralı devre dışı bırakma
Disable-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)"
# Servisi yeniden başlatma
Restart-Service -Name "TermService" -Force
Portu değiştirdikten sonra bağlantı kurarken sunucuadı:33890 formatını kullanmanız gerektiğini unutmayın.
Network Level Authentication (NLA) Zorunlu Hale Getirme
NLA, kullanıcının tam RDP oturumu kurulmadan önce kimlik doğrulaması yapmasını gerektirir. Bu özellik olmadan saldırgan Windows giriş ekranına kadar ulaşıp orada brute force yapabilir. NLA ile kimlik doğrulama çok daha erken gerçekleşir ve sistem kaynakları gereksiz yere tüketilmez.
# NLA'yı PowerShell ile zorunlu hale getirme
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "UserAuthentication" -Value 1 -Type DWord
# Group Policy ile de yapılabilir (domain ortamı için)
# Computer Configuration > Administrative Templates > Windows Components
# > Remote Desktop Services > Remote Desktop Session Host > Security
# "Require use of specific security layer for remote connections" = SSL
# "Require user authentication for remote connections by using NLA" = Enabled
# Mevcut NLA durumunu kontrol etme
Get-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "UserAuthentication" | Select-Object UserAuthentication
Firewall ile IP Kısıtlaması
Eğer RDP’ye erişecek IP adresleri belliyse, yalnızca bu adreslere izin vermek en etkili yöntemlerden biri.
# Belirli IP aralıklarına RDP erişimi tanımlama
$allowedIPs = @("192.168.1.0/24", "10.0.0.50", "203.0.113.25")
# Önce tüm RDP erişimini engelleyen kural
New-NetFirewallRule -DisplayName "Block RDP Default" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 33890 `
-Action Block `
-Priority 1000
# Sadece izin verilen IP'ler için kural
New-NetFirewallRule -DisplayName "Allow RDP Trusted IPs" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 33890 `
-RemoteAddress $allowedIPs `
-Action Allow `
-Priority 900
# Mevcut firewall kurallarını listeleme
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*RDP*"} |
Select-Object DisplayName, Enabled, Action
Brute Force Saldırılarını Engelleme
Account Lockout Policy Yapılandırması
Brute force saldırılarına karşı en temel savunma mekanizması hesap kilitleme politikasıdır.
# Hesap kilitleme politikasını yapılandırma
# Yerel politika için net accounts komutu
# 5 başarısız denemeden sonra kilitle
net accounts /lockoutthreshold:5
# 30 dakika kilitte tut
net accounts /lockoutduration:30
# Sayacı 30 dakikada bir sıfırla
net accounts /lockoutwindow:30
# Mevcut politikaları görüntüle
net accounts
# Domain ortamında Group Policy ile:
# Computer Configuration > Windows Settings > Security Settings
# > Account Policies > Account Lockout Policy
Fail2Ban Benzeri Çözüm: Windows’ta Otomatik IP Bloklama
Linux’ta Fail2Ban nasıl işe yarıyorsa, Windows’ta da Event Log tabanlı otomatik IP bloklama yapabiliriz. Aşağıdaki script, belirli bir süre içinde çok fazla başarısız giriş denemesi yapan IP adreslerini otomatik olarak engeller.
# RDP Brute Force Koruma Script'i
# Bu scripti Scheduled Task olarak çalıştırın
param(
[int]$MaxAttempts = 5,
[int]$TimeWindowMinutes = 10,
[int]$BlockDurationHours = 24
)
$logPath = "C:SecurityLogsrdp_blocked_ips.log"
$startTime = (Get-Date).AddMinutes(-$TimeWindowMinutes)
# Başarısız RDP girişimlerini Event Log'dan çekme (Event ID 4625)
$failedAttempts = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = $startTime
} -ErrorAction SilentlyContinue | ForEach-Object {
$xml = [xml]$_.ToXml()
$ip = ($xml.Event.EventData.Data |
Where-Object {$_.Name -eq "IpAddress"}).'#text'
if ($ip -and $ip -ne "-" -and $ip -ne "::1") {
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
IpAddress = $ip
}
}
}
# IP başına deneme sayısını grupla
$suspiciousIPs = $failedAttempts |
Group-Object IpAddress |
Where-Object {$_.Count -ge $MaxAttempts} |
Select-Object Name, Count
foreach ($entry in $suspiciousIPs) {
$ip = $entry.Name
$count = $entry.Count
# Mevcut bloklama kuralı var mı kontrol et
$existingRule = Get-NetFirewallRule -DisplayName "Block_$ip" -ErrorAction SilentlyContinue
if (-not $existingRule) {
# IP'yi engelle
New-NetFirewallRule -DisplayName "Block_$ip" `
-Direction Inbound `
-RemoteAddress $ip `
-Action Block `
-Enabled True | Out-Null
# Loglama
$logEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | BLOCKED | IP: $ip | Attempts: $count"
Add-Content -Path $logPath -Value $logEntry
Write-Host "Engellendi: $ip ($count deneme)" -ForegroundColor Red
}
}
# Süresi dolan bloklamaları kaldır
$allBlockRules = Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Block_*"}
foreach ($rule in $allBlockRules) {
$ruleIP = $rule.DisplayName -replace "Block_", ""
$logEntries = Get-Content $logPath -ErrorAction SilentlyContinue |
Where-Object {$_ -match $ruleIP -and $_ -match "BLOCKED"}
if ($logEntries) {
$lastBlock = [datetime]($logEntries[-1].Split("|")[0].Trim())
if ((Get-Date) -gt $lastBlock.AddHours($BlockDurationHours)) {
Remove-NetFirewallRule -DisplayName $rule.DisplayName
Write-Host "Engel kaldirildi: $ruleIP" -ForegroundColor Green
}
}
}
Bu scripti Scheduled Task ile her 5 dakikada bir çalıştırın:
# Scheduled Task oluşturma
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
-Argument "-NonInteractive -ExecutionPolicy Bypass -File C:ScriptsRDP-Protection.ps1"
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 5) -Once `
-At (Get-Date)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
Register-ScheduledTask -TaskName "RDP Brute Force Protection" `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Description "RDP brute force saldirilarini otomatik engeller"
VPN Arkasına Alma
En güvenli yaklaşım RDP’yi doğrudan internete açmamak. Bir VPN çözümü kullanarak RDP trafiğini VPN tüneli üzerinden geçirmek, saldırı yüzeyini dramatik biçimde küçültür. OpenVPN, WireGuard veya Windows’un kendi SSTP/IKEv2 çözümleri bu amaç için kullanılabilir.
WireGuard ile hızlı bir kurulum:
# Linux VPN sunucusunda WireGuard kurulumu
apt update && apt install -y wireguard
# Anahtar çifti oluşturma
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
SERVER_PRIVATE=$(cat /etc/wireguard/server_private.key)
# WireGuard konfigürasyonu
cat > /etc/wireguard/wg0.conf << EOF
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = $SERVER_PRIVATE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Windows RDP Sunucusu için peer
[Peer]
PublicKey = WINDOWS_SUNUCU_PUBLIC_KEY_BURAYA
AllowedIPs = 10.8.0.2/32
EOF
# IP forwarding aktif etme
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# WireGuard servisini başlatma
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
Bu yapılandırmayla RDP portu yalnızca VPN IP aralığından erişilebilir olur, internet üzerinden direkt erişim tamamen kapanır.
RDP Gateway Kurulumu
Kurumsal ortamlarda RDP Gateway çözümü, iç ağdaki sistemlere güvenli dış erişim sağlar. RDP Gateway, HTTPS (443) üzerinden tünelleme yaparak hem port yönetimini kolaylaştırır hem de sertifika tabanlı güvenlik sağlar.
# RD Gateway rolünü yükleme (Windows Server)
Install-WindowsFeature -Name RDS-Gateway -IncludeManagementTools
# Gateway politikası oluşturma (Connection Authorization Policy)
Import-Module RemoteDesktopServices
New-Item -Path "RDS:GatewayServerCAP" -Name "RDP_CAP_Policy" `
-UserGroups "Domain Users" `
-AuthMethod 1 # 1 = Password, 2 = Smart Card, 3 = Both
# Resource Authorization Policy
New-Item -Path "RDS:GatewayServerRAP" -Name "RDP_RAP_Policy" `
-UserGroups "Domain Users" `
-ComputerGroupType 2 # 2 = Any network resource
# SSL sertifikası atama
$cert = Get-ChildItem -Path Cert:LocalMachineMy |
Where-Object {$_.Subject -like "*rdgateway.sirket.com*"}
Set-Item -Path "RDS:GatewayServerSSLCertificateThumbprint" -Value $cert.Thumbprint
Log İzleme ve Anomali Tespiti
Saldırıları önlemek kadar tespit etmek de önemli. Windows Security Event Log’u düzenli izlemek kritik.
# RDP ile ilgili önemli Event ID'leri izleme
# Event ID 4624: Başarılı giriş
# Event ID 4625: Başarısız giriş
# Event ID 4634: Oturum kapatma
# Event ID 4778: RDP oturumu yeniden bağlandı
# Event ID 4779: RDP oturumu kesildi
# Son 1 saatteki şüpheli aktiviteleri raporlama
$reportTime = (Get-Date).AddHours(-1)
Write-Host "`n=== SON 1 SAATTEKİ RDP AKTİVİTESİ ===" -ForegroundColor Cyan
# Başarısız girişimler
$failed = Get-WinEvent -FilterHashtable @{
LogName = 'Security'; Id = 4625; StartTime = $reportTime
} -ErrorAction SilentlyContinue
Write-Host "`nBaşarısız Giriş Denemeleri: $($failed.Count)" -ForegroundColor Red
if ($failed) {
$failed | ForEach-Object {
$xml = [xml]$_.ToXml()
$username = ($xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetUserName"}).'#text'
$ip = ($xml.Event.EventData.Data | Where-Object {$_.Name -eq "IpAddress"}).'#text'
Write-Host " Kullanici: $username | IP: $ip | Zaman: $($_.TimeCreated)"
}
}
# Başarılı girişler
$success = Get-WinEvent -FilterHashtable @{
LogName = 'Security'; Id = 4624; StartTime = $reportTime
} -ErrorAction SilentlyContinue | Where-Object {
$xml = [xml]$_.ToXml()
($xml.Event.EventData.Data | Where-Object {$_.Name -eq "LogonType"}).'#text' -eq "10"
}
Write-Host "`nBasarili RDP Girisleri: $($success.Count)" -ForegroundColor Green
Ek Güvenlik Katmanları
Restricted Admin Mode
# Restricted Admin Mode aktif etme
# Bu mod, kimlik bilgilerinin uzak sistemde önbelleğe alınmasını engeller
Set-ItemProperty -Path "HKLM:SystemCurrentControlSetControlLsa" `
-Name "DisableRestrictedAdmin" -Value 0 -Type DWord
# Remote Credential Guard (domain ortamı için)
# Bu ayar Kerberos kullanarak kimlik bilgilerini korur
Set-ItemProperty -Path "HKLM:SystemCurrentControlSetControlLsa" `
-Name "DisableRestrictedAdmin" -Value 0 -Type DWord
# RDP bağlantısında Restricted Admin kullanımı
# mstsc.exe /restrictedAdmin /v:SUNUCU_ADI
Kullanıcı Erişim Kısıtlamaları
Prensip olarak en az yetki ilkesini uygulamalı, RDP erişimini yalnızca ihtiyaç duyan kullanıcılarla sınırlamalısınız.
# Remote Desktop Users grubunu temizleme ve yeniden yapılandırma
$rdpGroup = [ADSI]"WinNT://./Remote Desktop Users,group"
# Mevcut üyeleri listeleme
$rdpGroup.Members() | ForEach-Object {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
# Belirli bir kullanıcıyı gruba ekleme
Add-LocalGroupMember -Group "Remote Desktop Users" -Member "rdp_admin"
# Administrator hesabını RDP üzerinden devre dışı bırakma
# (GPO ile yapılması önerilir)
# Computer Configuration > Windows Settings > Security Settings
# > Local Policies > User Rights Assignment
# "Allow log on through Remote Desktop Services"
# Buradan sadece onaylı grupları ekleyin
# Yerleşik Administrator hesabını yeniden adlandırma
Rename-LocalUser -Name "Administrator" -NewName "SysAdmin_$(Get-Random -Maximum 9999)"
TLS/SSL Sertifika Yapılandırması
# RDP için güçlü şifreleme zorunlu kılma
# Minimum TLS 1.2 gerektirme
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "SecurityLayer" -Value 2 -Type DWord
# 0 = RDP Security, 1 = Negotiate, 2 = SSL/TLS
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" `
-Name "MinEncryptionLevel" -Value 3 -Type DWord
# 1 = Low, 2 = Client Compatible, 3 = High, 4 = FIPS
# TLS 1.0 ve 1.1'i devre dışı bırakma
$tlsPath = "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocols"
foreach ($version in @("TLS 1.0", "TLS 1.1")) {
New-Item -Path "$tlsPath$versionServer" -Force | Out-Null
Set-ItemProperty -Path "$tlsPath$versionServer" -Name "Enabled" -Value 0 -Type DWord
Set-ItemProperty -Path "$tlsPath$versionServer" -Name "DisabledByDefault" -Value 1 -Type DWord
}
Güvenlik Denetim Checklist
Yaptığınız yapılandırmaların etkinliğini test etmek için şu kontrolleri düzenli olarak yapın:
- Port taraması:
nmap -p 3389,33890 SUNUCU_IPile hangi portların açık olduğunu doğrulayın - NLA kontrolü:
nmap --script rdp-enum-encryption -p 33890 SUNUCU_IPile şifreleme seviyesini kontrol edin - Hesap kilitleme testi: 5’ten fazla yanlış şifre girildiğinde hesabın kilitlendiğini doğrulayın
- Log denetimi: Haftalık olarak Event Log’daki 4625 ID’li kayıtları inceleyin
- Yama durumu:
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10ile son yamalar kontrol edin - Aktif oturumlar:
query sessionkomutuyla mevcut RDP oturumlarını düzenli denetleyin - Firewall kuralları:
Get-NetFirewallRule | Where-Object {$_.Enabled -eq "True"}ile aktif kuralları gözden geçirin
Sonuç
RDP güvenliği tek bir önlemle sağlanamaz. Anlattığım katmanlı yaklaşımda her katman birbirini destekler: Port değişikliği otomatik tarayıcıları etkisiz kılar, NLA kimlik doğrulamayı güçlendirir, firewall kuralları erişimi kısıtlar, hesap kilitleme brute force’u yavaşlatır, otomatik IP bloklama aktif saldırıları durdurur, VPN veya Gateway çözümleri saldırı yüzeyini ortadan kaldırır.
Gerçek dünyada gördüğüm vakaların büyük çoğunluğu basit önlemlerle engellenebilirdi. İnternete açık, varsayılan portta, NLA olmadan, zayıf şifreli bir RDP sunucusu bugün değil yarın ele geçirilecektir. Özellikle küçük ve orta ölçekli işletmelerde bu ihmalin sonuçları fidye yazılımı, veri sızıntısı veya tam sistem ele geçirme şeklinde karşımıza çıkıyor.
Bu yazıda anlattığım önlemlerin hepsini birden uygulamanızı öneririm. Eğer ortamınız VPN kurulumuna uygun değilse en azından NLA, güçlü hesap kilitleme politikası ve otomatik IP bloklama scriptini devreye alın. Bu üç önlem bile saldırı başarısını dramatik biçimde düşürecektir.
