PowerShell ile SSH Bağlantısı Kurma

Uzun yıllar boyunca Windows yöneticileri SSH bağlantıları için PuTTY, MobaXterm veya benzeri üçüncü parti araçlara muhtaç kaldı. Ama artık durum değişti. Windows 10 1809 ve Windows Server 2019 ile birlikte OpenSSH doğrudan işletim sistemine entegre edildi ve PowerShell üzerinden SSH bağlantısı kurmak son derece doğal bir hale geldi. Bu yazıda, PowerShell ile SSH bağlantısının nasıl kurulacağını, anahtar tabanlı kimlik doğrulamanın nasıl yapılandırılacağını ve günlük sysadmin hayatında işe yarayacak gerçek senaryoları ele alacağız.

Başlamadan Önce: OpenSSH Kurulumu

PowerShell üzerinden SSH kullanabilmek için öncelikle OpenSSH istemcisinin sisteminizde kurulu olması gerekiyor. Windows 10 ve Server 2019 üzerinde bu bileşen isteğe bağlı olarak geliyor, yani elle kurmanız gerekebilir.

Kurulu olup olmadığını kontrol etmek için:

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

Eğer State: NotPresent görüyorsanız, istemciyi kurmak için şu komutu çalıştırın:

Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

Sunucu tarafında SSH servisi de çalıştırmak istiyorsanız, yani Windows makinenize SSH ile bağlanılmasını istiyorsanız, sunucu bileşenini de kurmanız gerekiyor:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# Servisi başlat
Start-Service sshd

# Sistem açılışında otomatik başlaması için
Set-Service -Name sshd -StartupType Automatic

Güvenlik duvarı kuralının otomatik olarak eklendiğini doğrulamak için:

Get-NetFirewallRule -Name *ssh*

Bu adımları tamamladıktan sonra PowerShell terminalinizden doğrudan ssh komutunu kullanabilirsiniz.

Temel SSH Bağlantısı

En basit haliyle SSH bağlantısı şu şekilde kurulur:

ssh kullanici@sunucu-adresi

Örnek olarak, 192.168.1.50 IP adresindeki bir Linux sunucusuna bağlanmak için:

ssh [email protected]

Farklı bir port kullanıyorsanız -p parametresiyle belirtebilirsiniz:

ssh -p 2222 [email protected]

Önemli parametreler şunlar:

  • -p: Bağlantı portu belirtir (varsayılan 22)
  • -i: Kullanılacak özel anahtar dosyasını belirtir
  • -l: Kullanıcı adını ayrı olarak belirtir
  • -v: Ayrıntılı (verbose) çıktı verir, sorun gidermede işe yarar
  • -N: Uzak komut çalıştırmadan sadece tünel açar
  • -L: Yerel port yönlendirmesi yapılandırır
  • -o: OpenSSH yapılandırma seçeneklerini satır içi olarak geçirir

İlk kez bağlandığınızda sunucunun parmak izi (fingerprint) sorulacak. Bu soruyu yes diyerek geçerseniz, bilgiler ~/.ssh/known_hosts dosyasına kaydedilir ve bir daha sorulmaz.

SSH Anahtar Çifti Oluşturma

Parola ile bağlanmak hem güvensiz hem de otomasyona elverişsiz değil. Anahtar tabanlı kimlik doğrulama hem daha güvenli hem de scriptlerde kullanımı çok daha rahat. PowerShell üzerinden anahtar çifti oluşturmak için ssh-keygen komutunu kullanıyoruz:

ssh-keygen -t ed25519 -C "sunucu-yonetim-anahtari"

Bu komutu çalıştırdığınızda anahtarın nereye kaydedileceği ve parola koruması isteyip istemediğiniz sorulacak. Varsayılan konum C:UsersKullaniciAdi.sshid_ed25519 şeklinde olur.

Parametreler:

  • -t: Anahtar türü (ed25519, rsa, ecdsa)
  • -C: Anahtara yorum ekler, genellikle amaç veya e-posta adresi yazılır
  • -b: Anahtar uzunluğunu belirler (RSA için 4096 önerilir)
  • -f: Anahtar dosyasının adı ve konumunu belirtir

Farklı sunucular için farklı anahtarlar kullanmak iyi bir güvenlik pratiği. Örneğin:

ssh-keygen -t ed25519 -f "$env:USERPROFILE.sshuretim_sunucusu" -C "uretim-ortami-2024"

Genel Anahtarı Sunucuya Kopyalama

Anahtar çiftini oluşturduktan sonra genel anahtarı (public key) uzak sunucuya kopyalamanız gerekiyor. Linux sistemlerde ssh-copy-id komutu varken, Windows tarafında bu komutu doğrudan kullanamazsınız. Ancak PowerShell ile aynı işi yapabilirsiniz:

# Genel anahtar içeriğini oku
$PublicKey = Get-Content "$env:USERPROFILE.sshid_ed25519.pub"

# SSH üzerinden uzak sunucudaki authorized_keys dosyasına ekle
ssh [email protected] "mkdir -p ~/.ssh && echo '$PublicKey' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Eğer hedef sunucu da Windows ise ve OpenSSH Server kuruluysa, yönetici kullanıcılar için özel bir dosya kullanılıyor. Windows’ta yönetici hesapları için authorized_keys dosyası farklı bir konumda tutulur:

# Hedef Windows sunucusuna genel anahtarı kopyala
$PublicKey = Get-Content "$env:USERPROFILE.sshid_ed25519.pub"
ssh [email protected] "Add-Content -Path 'C:ProgramDatasshadministrators_authorized_keys' -Value '$PublicKey'"

SSH Config Dosyası ile Yönetim Kolaylaştırma

Onlarca sunucu yönetiyorsanız her seferinde IP adresi, kullanıcı adı ve anahtar dosyası yazmak can sıkıcı hale gelir. SSH config dosyası bu sorunu çözer. ~/.ssh/config dosyasını PowerShell ile oluşturalım:

$SSHConfig = @"
Host uretim-web
    HostName 192.168.1.50
    User webadmin
    IdentityFile ~/.ssh/uretim_sunucusu
    Port 22

Host uretim-db
    HostName 192.168.1.60
    User dbadmin
    IdentityFile ~/.ssh/uretim_sunucusu
    Port 22

Host test-sunucu
    HostName 10.0.0.100
    User testadmin
    IdentityFile ~/.ssh/test_anahtari
    Port 2222
"@

$SSHConfig | Out-File -FilePath "$env:USERPROFILE.sshconfig" -Encoding UTF8

Artık şu şekilde bağlanabilirsiniz:

ssh uretim-web

Bu kadar. IP adresi, kullanıcı adı, port, anahtar dosyası, hepsini config dosyası hallediyor.

PowerShell ile Uzak Komut Çalıştırma

SSH’nin gerçek gücü, etkileşimli oturum açmadan doğrudan komut çalıştırabilmek. Bu özellik otomasyon scriptlerinde çok işe yarıyor.

# Tek bir komut çalıştır
ssh [email protected] "df -h"

# Birden fazla komut
ssh [email protected] "uptime && free -m && df -h"

# Çıktıyı PowerShell değişkenine al
$DiskBilgisi = ssh [email protected] "df -h"
$DiskBilgisi

Birden fazla Linux sunucusunda aynı komutu çalıştırmak için döngü kullanabilirsiniz:

$Sunucular = @("192.168.1.50", "192.168.1.51", "192.168.1.52", "192.168.1.53")
$Komut = "df -h / | tail -1"

foreach ($Sunucu in $Sunucular) {
    Write-Host "=== $Sunucu ===" -ForegroundColor Cyan
    $Sonuc = ssh -i "$env:USERPROFILE.sshuretim_sunucusu" admin@$Sunucu $Komut
    Write-Host $Sonuc
    Write-Host ""
}

Bu script, tüm sunucularda disk kullanımını tek seferde kontrol etmenizi sağlar. Sabah rutin kontrolü için biçilmiş kaftan.

Gerçek Dünya Senaryosu: Toplu Güncelleme Scripti

Diyelim ki 10 tane Ubuntu sunucunuz var ve hepsinde aynı gece güvenlik güncellemelerini uygulamak istiyorsunuz. PowerShell ile SSH kullanarak bunu otomatize edebilirsiniz:

# Sunucu listesi
$Sunucular = @(
    @{IP="192.168.1.50"; Ad="web-01"},
    @{IP="192.168.1.51"; Ad="web-02"},
    @{IP="192.168.1.52"; Ad="app-01"},
    @{IP="192.168.1.60"; Ad="db-01"}
)

$AnahtarDosyasi = "$env:USERPROFILE.sshuretim_sunucusu"
$LogDosyasi = "C:Logsguncelleme_$(Get-Date -Format 'yyyyMMdd_HHmm').log"

foreach ($Sunucu in $Sunucular) {
    $Zaman = Get-Date -Format "HH:mm:ss"
    $Mesaj = "[$Zaman] $($Sunucu.Ad) ($($Sunucu.IP)) guncelleniyor..."
    
    Write-Host $Mesaj -ForegroundColor Yellow
    $Mesaj | Out-File -FilePath $LogDosyasi -Append

    try {
        $Sonuc = ssh -i $AnahtarDosyasi -o "StrictHostKeyChecking=no" `
            admin@$($Sunucu.IP) `
            "sudo apt-get update -q && sudo apt-get upgrade -y -q 2>&1 | tail -5"
        
        $BasariMesaji = "[$Zaman] $($Sunucu.Ad): BASARILI"
        Write-Host $BasariMesaji -ForegroundColor Green
        $BasariMesaji | Out-File -FilePath $LogDosyasi -Append
        $Sonuc | Out-File -FilePath $LogDosyasi -Append
    }
    catch {
        $HataMesaji = "[$Zaman] $($Sunucu.Ad): HATA - $_"
        Write-Host $HataMesaji -ForegroundColor Red
        $HataMesaji | Out-File -FilePath $LogDosyasi -Append
    }
}

Write-Host "`nTum islemler tamamlandi. Log: $LogDosyasi" -ForegroundColor Cyan

Gerçek Dünya Senaryosu: SCP ile Dosya Transferi

SSH bağlantısı kurulduktan sonra dosya transferi için SCP veya SFTP kullanabilirsiniz. OpenSSH paketi ile birlikte scp komutu da geliyor:

# Yerel dosyayı uzak sunucuya gonder
scp -i "$env:USERPROFILE.sshuretim_sunucusu" `
    C:Backupsconfig.tar.gz `
    [email protected]:/tmp/config.tar.gz

# Uzak sunucudan dosya al
scp -i "$env:USERPROFILE.sshuretim_sunucusu" `
    [email protected]:/var/log/nginx/error.log `
    C:Logsnginx_error_$(Get-Date -Format 'yyyyMMdd').log

# Dizin kopyalama (-r recursive)
scp -r -i "$env:USERPROFILE.sshuretim_sunucusu" `
    [email protected]:/etc/nginx `
    C:Backupsnginx_config

Birden fazla sunucudan log toplama senaryosu:

$Sunucular = @("web-01.sirket.local", "web-02.sirket.local", "app-01.sirket.local")
$HedefDizin = "C:LogsGunluk$(Get-Date -Format 'yyyy-MM-dd')"
New-Item -ItemType Directory -Path $HedefDizin -Force | Out-Null

foreach ($Sunucu in $Sunucular) {
    $HedefDosya = "$HedefDizin$Sunucu`_access.log"
    Write-Host "$Sunucu logları alınıyor..." -ForegroundColor Yellow
    
    scp -i "$env:USERPROFILE.sshuretim_sunucusu" `
        admin@${Sunucu}:/var/log/nginx/access.log `
        $HedefDosya
}

Write-Host "Tum loglar $HedefDizin dizinine kaydedildi." -ForegroundColor Green

SSH Port Yönlendirme (Tünel) Kullanımı

Port yönlendirme, özellikle güvenlik duvarı arkasındaki servislere erişmek için çok değerli. Örneğin, üretim veritabanı sunucunuz doğrudan erişime kapalı ama SSH üzerinden erişebiliyorsunuz. Bu durumda yerel port yönlendirme ile yerel makinenizden veritabanına bağlanabilirsiniz:

# Yerel 5433 portunu uzak sunucudaki 5432 (PostgreSQL) portuna yonlendir
ssh -L 5433:localhost:5432 -N -f [email protected]

# Artık yerel makinenizden bağlanabilirsiniz
# psql -h localhost -p 5433 -U dbkullanici -d veritabani

Parametreler:

  • -L: Yerel port yönlendirmesi (local_port:remote_host:remote_port)
  • -N: Komut çalıştırmadan sadece tünel açar
  • -f: Arka planda çalıştırır

Bu SSH tünelini bir PowerShell scriptiyle yönetmek için:

# Tunnel aç ve PID'ini kaydet
$SSHProcess = Start-Process -FilePath "ssh" `
    -ArgumentList "-L 5433:localhost:5432 -N [email protected]" `
    -PassThru

Write-Host "SSH tüneli açıldı. PID: $($SSHProcess.Id)"
Write-Host "Tunnel'ı kapatmak için: Stop-Process -Id $($SSHProcess.Id)"

# İşiniz bittiğinde tunnel'ı kapat
# Stop-Process -Id $SSHProcess.Id

Sorun Giderme

SSH bağlantısında sorun yaşadığınızda verbose modu çok işe yarıyor:

ssh -vvv [email protected]
  • -v: Temel debug bilgisi
  • -vv: Daha ayrıntılı
  • -vvv: En ayrıntılı, bağlantının her adımını gösterir

Sık karşılaşılan sorunlar ve çözümleri:

  • Permission denied (publickey): Genel anahtarın doğru konumda olup olmadığını, authorized_keys dosyasının izinlerini kontrol edin (Linux’ta 600 olmalı)
  • Connection refused: Hedef sunucuda SSH servisi çalışmıyor olabilir veya güvenlik duvarı 22. portu engelliyor olabilir
  • Host key verification failed: Sunucunun anahtarı değişmiş, known_hosts dosyasından eski kaydı silmeniz gerekiyor
  • WARNING: UNPROTECTED PRIVATE KEY FILE: Windows’ta anahtar dosyasının izinleri çok geniş, sadece kendi kullanıcınızın erişmesi gerekiyor

Anahtar dosyası izinlerini düzeltmek için:

# Ozel anahtar dosyasinin izinlerini duzelt
$AnahtarDosyasi = "$env:USERPROFILE.sshid_ed25519"
$Acl = Get-Acl $AnahtarDosyasi

# Miras alinan izinleri kaldir
$Acl.SetAccessRuleProtection($true, $false)

# Sadece mevcut kullaniciya tam erisim ver
$KullaniciKurali = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $env:USERNAME,
    "FullControl",
    "Allow"
)
$Acl.SetAccessRule($KullaniciKurali)
Set-Acl -Path $AnahtarDosyasi -AclObject $Acl

SSH Agent Kullanımı

Parolalı anahtar kullanıyorsanız her bağlantıda parola girmek zorunda kalırsınız. SSH Agent bu parolayı belleğe alır ve oturum süresince tekrar sormaz:

# SSH Agent servisini baslat
Start-Service ssh-agent
Set-Service ssh-agent -StartupType Automatic

# Anahtari agent'a ekle
ssh-add "$env:USERPROFILE.sshid_ed25519"

# Yuklü anahtarları listele
ssh-add -l

Artık o oturum boyunca SSH bağlantılarında parola sorulmayacak.

PowerShell Core ile Çapraz Platform Kullanım

PowerShell 7 (Core) Windows, Linux ve macOS üzerinde çalışıyor. Yani burada anlattığımız SSH scriptlerini Linux veya Mac üzerinde de aynı şekilde kullanabilirsiniz. Bu, hibrit ortamları yöneten sysadminler için büyük bir avantaj. Tek bir script hem Windows hem Linux yönetim makinelerinde çalışıyor.

Örneğin bir izleme scripti:

# Tüm platformlarda calisan basit saglik kontrolu
$Sunucular = @("web-01", "web-02", "db-01")
$SaglikDurumu = @()

foreach ($Sunucu in $Sunucular) {
    $Yuklenme = ssh admin@$Sunucu "cat /proc/loadavg | awk '{print $1}'"
    $DiskKullanim = ssh admin@$Sunucu "df -h / | awk 'NR==2{print $5}'"
    $RamKullanim = ssh admin@$Sunucu "free | awk '/Mem/{printf "%.0f%%", $3/$2*100}'"
    
    $SaglikDurumu += [PSCustomObject]@{
        Sunucu = $Sunucu
        Yuklenme = $Yuklenme
        Disk = $DiskKullanim
        RAM = $RamKullanim
        Zaman = Get-Date -Format "HH:mm:ss"
    }
}

$SaglikDurumu | Format-Table -AutoSize

Sonuç

PowerShell ile SSH kullanımı artık Windows dünyasında birinci sınıf bir deneyim sunuyor. PuTTY’yi sadece eski alışkanlıktan kullanıyorsanız, bir kez OpenSSH iş akışına geçtikten sonra geri dönmek istemeyeceksiniz. Anahtar tabanlı kimlik doğrulama, SSH config dosyaları ve komut satırı üzerinden çalışan scriptler, özellikle Linux/Windows karışık ortamları yöneten sysadminler için hayat kurtarıcı.

En önemli çıkarımları özetlemek gerekirse: Anahtar tabanlı kimlik doğrulamayı mutlaka kullanın, her ortam için ayrı anahtar çifti oluşturun, SSH config dosyasını iyi organize edin ve tekrarlayan işleri script haline getirin. Bu alışkanlıkları edindikten sonra onlarca sunucuyu yönetmek, tek bir sunucuyu yönetmek kadar kolay hale geliyor.

Yorum yapın