Windows Üzerinde SSH Sunucu Kurma ve Güvenlik Sertleştirme

Klasik düşünce şu: “SSH zaten Linux’un işi, Windows’a ne gerek var?” Ama modern altyapılarda bu yaklaşım seni ciddi şekilde kısıtlıyor. Bir Windows sunucusuna uzaktan erişmek istediğinde RDP açmak zorunda kalmak, hem port yönetimi açısından hem de güvenlik profili açısından büyük bir yük. OpenSSH artık Windows’un resmi bir parçası ve doğru yapılandırıldığında production ortamında güvenle kullanılabilecek düzeyde.

Bu yazıda Windows üzerinde OpenSSH sunucu kurulumunu, güvenli yapılandırmasını ve gerçek dünya senaryolarında nasıl kullanacağını adım adım ele alacağız.

Neden Windows’ta SSH?

Şunu düşün: Bir hybrid ortamda çalışıyorsun. Linux sunucularına SSH ile bağlanıyorsun, Windows sunucularına ise RDP ile. Her iki protokolü de yönetmek, farklı güvenlik politikaları uygulamak ve farklı araçlar kullanmak zorunda kalıyorsun. Oysa SSH, Windows’ta da çalışıyorsa tüm altyapını tek bir protokol üzerinden yönetebilirsin.

Pratik avantajlar şöyle sıralanabilir:

  • Betik otomasyonu: Ansible, Python Fabric veya Bash betikleri ile Windows sunucularını da aynı pipeline’a dahil edebilirsin
  • Güvenli dosya transferi: SCP ve SFTP doğrudan çalışır, ek yazılım gerekmez
  • RDP’ye alternatif: 3389 portunu kapatıp sadece SSH üzerinden bağlanmak saldırı yüzeyini dramatik şekilde azaltır
  • Key tabanlı kimlik doğrulama: Parola tabanlı RDP erişiminin önüne geçmek kolaylaşır
  • Audit log: SSH oturum kayıtları Windows Event Log ile entegre çalışır

Windows Server 2019 ve üzeri, aynı zamanda Windows 10 1809 ve üzeri sürümlerde OpenSSH artık opsiyonel bir Windows özelliği olarak geliyor. Üçüncü parti yazılım kurmana gerek yok.

Kurulum

Windows Optional Feature Üzerinden Kurulum

PowerShell’i yönetici olarak açıp aşağıdaki komutu çalıştırıyoruz:

# Mevcut OpenSSH paketlerini listele
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

# OpenSSH Server'ı kur
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# OpenSSH Client'ı da kur (genellikle zaten kurulu geliyor)
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

Kurulum tamamlandıktan sonra servisi başlatıp otomatik başlangıca alıyoruz:

# SSH servisini başlat
Start-Service sshd

# Sistem başlangıcında otomatik başlaması için
Set-Service -Name sshd -StartupType 'Automatic'

# Servis durumunu kontrol et
Get-Service sshd

Firewall Kuralı Ekleme

Kurulum sırasında genellikle firewall kuralı otomatik oluşur ama bunu doğrulamak ve gerekirse manuel eklemek önemli:

# Mevcut SSH firewall kuralını kontrol et
Get-NetFirewallRule -Name *ssh*

# Kural yoksa manuel ekle
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

# Veya mevcut kuralı güncelle
Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -Enabled True

Şu an temel kurulum tamamlandı. Ama bu haliyle sistemi production’a almak doğru değil. Güvenlik yapılandırmasına geçiyoruz.

Temel Güvenlik Yapılandırması

sshd_config Dosyasını Düzenleme

Windows’taki OpenSSH yapılandırma dosyası şu konumda: C:ProgramDatasshsshd_config

Bu dosyayı düzenleyelim. Önce yedek alalım:

# Yapılandırma dosyasını yedekle
Copy-Item C:ProgramDatasshsshd_config C:ProgramDatasshsshd_config.bak

# Notepad ile düzenle
notepad C:ProgramDatasshsshd_config

Kritik güvenlik parametreleri şunlar:

Port: Varsayılan 22 yerine farklı port kullanmak brute force saldırılarını azaltır. Örneğin 2222 veya başka bir port seçebilirsin. Security by obscurity tek başına yeterli değil ama ek katman olarak işe yarıyor.

PermitRootLogin: Windows’ta doğrudan karşılığı “Administrator” hesabı. Bu hesapla doğrudan bağlantıya izin vermek riskli.

PasswordAuthentication: Key tabanlı kimlik doğrulamaya geçtikten sonra bunu kapatmak zorunlu.

MaxAuthTries: Kaç başarısız deneme sonrası bağlantının kesileceği.

LoginGraceTime: Kimlik doğrulama için verilen süre.

Yapılandırma dosyasında şu değerleri ayarla:

# sshd_config içeriği - kritik satırlar
Port 2222
AddressFamily inet
ListenAddress 0.0.0.0

# Kimlik doğrulama
PermitRootLogin no
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30

# Key tabanlı kimlik doğrulama
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

# Parola girişini kapat (key kurulumu sonrası)
PasswordAuthentication no
PermitEmptyPasswords no

# Diğer güvenlik ayarları
X11Forwarding no
AllowTcpForwarding no
PrintLastLog yes

Yapılandırmayı kaydettikten sonra servisi yeniden başlat:

Restart-Service sshd

Key Tabanlı Kimlik Doğrulama Kurulumu

Bu adım güvenlik açısından en kritik kısım. Parola tabanlı kimlik doğrulamayı tamamen kapatıp SSH key kullanımına geçiyoruz.

Sunucu Tarafında Host Key Kontrolü

# Host key'lerin oluşturulduğunu doğrula
ls C:ProgramDatassh

# Beklenen dosyalar:
# ssh_host_dsa_key, ssh_host_ecdsa_key, ssh_host_ed25519_key, ssh_host_rsa_key
# ve bunların .pub versiyonları

İstemci Tarafında Key Oluşturma

Bağlanacak makinede (Linux veya Windows olabilir) key çifti oluşturuyoruz:

# Ed25519 algoritmasıyla key oluştur (RSA'dan daha güvenli ve modern)
ssh-keygen -t ed25519 -C "windows-server-access" -f ~/.ssh/windows_server_key

# RSA kullanmak zorundaysan en az 4096 bit kullan
ssh-keygen -t rsa -b 4096 -C "windows-server-access" -f ~/.ssh/windows_server_key

Public Key’i Windows Sunucusuna Kopyalama

Windows’ta bu adım Linux’tan biraz farklı işliyor. Önce normal kullanıcılar için, sonra yönetici hesapları için ayrı ayrı ele alalım.

Normal kullanıcı için:

# Windows sunucusunda PowerShell ile .ssh dizinini oluştur
New-Item -ItemType Directory -Force -Path C:Userskullanici_adi.ssh

# authorized_keys dosyasını oluştur ve public key'i ekle
# Public key içeriğini kopyala ve şu komutla ekle:
Add-Content -Path C:Userskullanici_adi.sshauthorized_keys -Value "ssh-ed25519 AAAA...pubkey...icerik windows-server-access"

# Dosya izinlerini ayarla (bu kritik!)
icacls C:Userskullanici_adi.sshauthorized_keys /inheritance:r /grant "kullanici_adi:(F)" /grant "SYSTEM:(F)"

Administrators grubundaki hesaplar için:

Windows’ta yönetici hesapları için authorized_keys farklı bir konumda aranıyor. Bu sshd_config dosyasındaki özel bir direktifle belirleniyor:

# sshd_config dosyasında şu satırı bul ve düzenle
# Varsayılan olarak şöyle gelir:
Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

# Administrators grubundaki kullanıcılar için merkezi authorized_keys dosyası
# Bu dosyayı oluştur:
New-Item -ItemType File -Path "C:ProgramDatasshadministrators_authorized_keys"

# Public key ekle
Add-Content -Path "C:ProgramDatasshadministrators_authorized_keys" -Value "ssh-ed25519 AAAA...key...icerigi"

# İzinleri ayarla - sadece SYSTEM ve Administrators erişebilmeli
icacls C:ProgramDatasshadministrators_authorized_keys /inheritance:r /grant "SYSTEM:(F)" /grant "Administrators:(F)"

Bağlantıyı Test Et

# İstemci tarafından bağlantı testi
ssh -i ~/.ssh/windows_server_key -p 2222 kullanici_adi@windows-sunucu-ip

# Bağlantı başarılıysa password authentication'ı kapat
# sshd_config'de: PasswordAuthentication no
# Sonra servisi yeniden başlat

Gelişmiş Güvenlik Önlemleri

Fail2Ban Alternatifi: Windows Güvenlik Duvarı ile Brute Force Koruması

Linux’taki Fail2Ban’in doğrudan Windows karşılığı yok ama PowerShell ile benzer bir mekanizma kurabilirsin. Aşağıdaki betik Windows Event Log’u izleyerek çok sayıda başarısız giriş denemesi yapan IP’leri engelliyor:

# Başarısız SSH girişlerini izle ve engelle
# Bu betiği bir Scheduled Task olarak çalıştır

$threshold = 5  # Kaç başarısız denemeden sonra engelle
$blockDuration = 3600  # Saniye cinsinden engelleme süresi (1 saat)

$events = Get-WinEvent -FilterHashtable @{
    LogName = 'OpenSSH/Operational'
    Id = 4  # Failed authentication event ID
    StartTime = (Get-Date).AddMinutes(-10)
} -ErrorAction SilentlyContinue

$ipGroups = $events | ForEach-Object {
    if ($_.Message -match '(d+.d+.d+.d+)') {
        $matches[1]
    }
} | Group-Object | Where-Object { $_.Count -ge $threshold }

foreach ($ipGroup in $ipGroups) {
    $ip = $ipGroup.Name
    Write-Host "Engelleniyor: $ip ($($ipGroup.Count) başarısız deneme)"
    
    # Firewall kuralı ekle
    $ruleName = "BlockSSH_$ip"
    if (-not (Get-NetFirewallRule -Name $ruleName -ErrorAction SilentlyContinue)) {
        New-NetFirewallRule -Name $ruleName -DisplayName "Block SSH Brute Force: $ip" `
            -Direction Inbound -Protocol TCP -LocalPort 2222 `
            -RemoteAddress $ip -Action Block
    }
}

SSH Erişimini Belirli IP Adresleriyle Sınırla

Eğer belirli IP bloklarından erişim olacaksa bunu hem firewall hem de sshd_config üzerinden kısıtlamak en güvenli yaklaşım:

# Firewall kuralını sadece belirli IP'lere izin verecek şekilde güncelle
Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' `
    -RemoteAddress @('192.168.1.0/24', '10.0.0.50') `
    -Enabled True

# sshd_config'de AllowUsers veya AllowGroups direktifi ile de kısıtlayabilirsin
# AllowUsers kullanici1 kullanici2
# AllowGroups ssh-users

Windows Event Log ile SSH Audit Logging

OpenSSH Windows üzerinde çalışırken kendi log mekanizmasını Event Viewer ile entegre ediyor. Bunu aktif hale getirelim:

# OpenSSH operational log kanalını etkinleştir
wevtutil sl OpenSSH/Operational /e:true

# Son SSH olaylarını görüntüle
Get-WinEvent -LogName 'OpenSSH/Operational' -MaxEvents 20 | 
    Select-Object TimeCreated, Id, LevelDisplayName, Message | 
    Format-List

# Başarısız giriş denemelerini filtrele
Get-WinEvent -FilterHashtable @{LogName='OpenSSH/Operational'; Id=4} |
    Select-Object TimeCreated, Message

Gerçek Dünya Senaryosu: Ansible ile Windows Yönetimi

Diyelim ki bir ortamda 20 Linux ve 5 Windows sunucun var. Linux sunucular zaten Ansible ile yönetiliyor. Artık Windows sunucular da SSH desteklediğine göre, WinRM yerine SSH transport kullanabilirsin.

Ansible inventory dosyan şöyle görünebilir:

# inventory/hosts.yml içeriği
[windows_servers]
win-server-01 ansible_host=192.168.1.100
win-server-02 ansible_host=192.168.1.101

[windows_servers:vars]
ansible_user=ansible_service
ansible_ssh_private_key_file=~/.ssh/windows_ansible_key
ansible_port=2222
ansible_connection=ssh
ansible_shell_type=powershell

Bağlantıyı test etmek için:

# Ansible ping modülü ile test
ansible windows_servers -m ping -i inventory/hosts.yml

# Basit bir komut çalıştır
ansible windows_servers -m win_command -a "ipconfig /all" -i inventory/hosts.yml

Bu yaklaşım WinRM’in konfigure edilmesindeki karmaşıklığı tamamen ortadan kaldırıyor.

Kullanıcı ve Erişim Yönetimi

SSH Erişimi İçin Ayrı Servis Hesabı

Production ortamında her zaman SSH erişimi için ayrı bir servis hesabı oluşturmak iyi pratik:

# SSH erişimi için dedicated kullanıcı oluştur
$password = ConvertTo-SecureString "GucluBirParola123!" -AsPlainText -Force
New-LocalUser -Name "ssh-service" -Password $password -Description "SSH Service Account" -PasswordNeverExpires $true

# Kullanıcıya minimum gerekli hakları ver
# Administrators grubuna ekleme, sadece gerekli gruplara ekle
Add-LocalGroupMember -Group "Remote Management Users" -Member "ssh-service"

# sshd_config'e bu kullanıcıyı ekle
# AllowUsers ssh-service

SFTP Kullanımını Kısıtlama

Sadece dosya transferi yapması gereken kullanıcılar için SSH shell erişimini kapatıp sadece SFTP bırakabilirsin:

# sshd_config sonuna ekle
Match User sftp-only-user
    ForceCommand internal-sftp
    ChrootDirectory C:sftp-root%u
    AllowTcpForwarding no
    X11Forwarding no
    PasswordAuthentication no

Sorun Giderme

Bağlantı Sorunlarını Teşhis Etme

# SSH daemon'ı verbose modda çalıştır (test ortamında)
# Önce servisi durdur
Stop-Service sshd

# Manuel olarak verbose modda başlat
& "C:WindowsSystem32OpenSSHsshd.exe" -d

# İstemci tarafında da verbose mod kullan
ssh -vvv -i ~/.ssh/key -p 2222 kullanici@sunucu-ip

# Windows Firewall loglarını kontrol et
netsh advfirewall set allprofiles logging filename C:firewall.log
netsh advfirewall set allprofiles logging droppedconnections enable

Yaygın Sorunlar ve Çözümleri

authorized_keys dosyası tanınmıyor:

Bu sorunun en yaygın sebebi dosya izin hatası. Windows’ta bu izinler çok katı uygulanıyor:

# authorized_keys izinlerini sıfırla
icacls C:Userskullanici.sshauthorized_keys /reset
icacls C:Userskullanici.sshauthorized_keys /inheritance:r
icacls C:Userskullanici.sshauthorized_keys /grant:r "kullanici:(F)"
icacls C:Userskullanici.sshauthorized_keys /grant:r "SYSTEM:(F)"

# .ssh dizini izinleri
icacls C:Userskullanici.ssh /inheritance:r
icacls C:Userskullanici.ssh /grant:r "kullanici:(F)"
icacls C:Userskullanici.ssh /grant:r "SYSTEM:(F)"

Servis başlamıyor:

# Event log'a bak
Get-EventLog -LogName System -Source sshd -Newest 20

# sshd_config syntax kontrolü
& "C:WindowsSystem32OpenSSHsshd.exe" -t -f C:ProgramDatasshsshd_config

Sonuç

Windows üzerinde SSH sunucu kurmak artık zahmetli bir iş değil. Microsoft’un OpenSSH’ı Windows’a entegre etmesiyle birlikte, hybrid ortamların yönetimi çok daha tutarlı hale geldi. RDP’ye olan bağımlılığı azaltmak, key tabanlı kimlik doğrulamayı standart hale getirmek ve tüm altyapıyı tek bir protokol üzerinden yönetmek; hem güvenlik hem de operasyonel verimlilik açısından büyük kazanımlar sağlıyor.

Bu yazıda anlattıklarımı özetle bir kontrol listesi olarak şöyle sıralayabiliriz:

  • OpenSSH Server kurulumu ve servis yapılandırması
  • sshd_config ile port değiştirme, max deneme sınırı ve protocol güvenliği
  • Ed25519 key çiftleri oluşturma ve authorized_keys yapılandırması
  • Parola kimlik doğrulamasının kapatılması
  • Firewall kurallarının IP bazlı kısıtlanması
  • Event Log entegrasyonu ile audit trail
  • Brute force koruması için otomatik engelleme

Şunu da söyleyelim: Bu yapılandırma bir başlangıç noktası. Her ortamın ihtiyacı farklı. Bazı yerlerde SFTP kullanımı ön planda olabilir, bazı yerlerde Ansible entegrasyonu kritik öneme sahip. Temel güvenlik anlayışını kavradıktan sonra kendi ortamına göre adapte etmek zor olmayacak.

RDP portunu kapatıp SSH’a tam geçiş yapmadan önce mutlaka kapsamlı test et ve bir geri dönüş planı hazırla. Üretim ortamında bu adımı aceleyle atmak seni sistemin dışında bırakabilir; sysadmin’in en kötü kabusu budur.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir