Debian Sunucularda SSH Güvenliği Sertleştirme Rehberi

SSH, uzak sunucu yönetiminin bel kemiği. Ama varsayılan kurulumda gelen ayarlarla SSH’ı açık bırakmak, evinizin kapısını sadece “lütfen girme” yazan bir kağıt asarak kapatmaya benziyor. Özellikle Debian sunucularında, fresh kurulumdan sonra SSH servisini hemen internete açan sistem yöneticilerinin başı çok kısa sürede dertte oluyor. Bu yazıda, Debian üzerinde SSH güvenliğini gerçek anlamda sertleştirmek için adım adım ne yapmanız gerektiğini anlatacağım.

Neden SSH Sertleştirmesi Şart?

Geçen ay bir müşterimin sunucusunu devrettim. Yeni kurulmuş, temiz bir Debian 12 sistemi, root girişi açık, port 22’de dinliyor, parola doğrulaması aktif. Sunucunun loglarına baktığımda ne gördüm? Kurulumdan sadece 4 saat sonra başlamış brute force denemeleri. Çin’den, Rusya’dan, Hollanda’dan… Her dakika onlarca giriş denemesi.

Bu gerçek bir senaryo ve her gün binlerce Debian sunucusunda yaşanıyor. Shodan’da port 22 üzerinden yapılan taramalar düşünüldüğünde, sunucunuz internete çıktığı andan itibaren hedef haline geliyor. Peki bunu nasıl önlüyoruz?

Başlamadan Önce: Mevcut Durumu Anlamak

Sertleştirmeye geçmeden önce neyle uğraştığımızı anlamalıyız. SSH versiyonunu ve mevcut konfigürasyonu kontrol edelim:

# SSH versiyon kontrolü
ssh -V

# Çalışan SSH servis durumu
systemctl status ssh

# Aktif bağlantıları görüntüle
ss -tnlp | grep :22

# Mevcut konfigürasyonu listele
sshd -T | grep -E "permitrootlogin|passwordauthentication|port|protocol"

Bu komutlardan çıkan çıktıyı bir yere not edin. Değişiklik yaptıktan sonra karşılaştırma yapmanız gerekebilir.

Kritik uyarı: SSH sertleştirmesi yaparken her zaman mevcut bağlantınızı açık tutun ve yeni bir terminal sekmesinde test edin. Kendinizi sunucudan kilitlemek, özellikle fiziksel erişiminiz yoksa ciddi bir sorun haline gelir. Konsol erişiminiz (VNC, IPMI, KVM) varsa bu riski biraz azaltır ama yine de dikkatli olun.

SSH Yapılandırma Dosyası: Temel Sertleştirme

Ana yapılandırma dosyası /etc/ssh/sshd_config üzerinde çalışacağız. Önce yedeğini alalım:

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

Şimdi sertleştirme parametrelerini tek tek inceleyelim. Dosyayı düzenlemek için:

nano /etc/ssh/sshd_config

Port Değiştirme

Varsayılan port 22’yi değiştirmek, “security through obscurity” olarak eleştirilse de brute force saldırılarının ezici çoğunluğunu engeller. Otomatik botlar önce 22’yi tarar. Portu değiştirmek bu gürültüyü dramatik biçimde düşürür.

# /etc/ssh/sshd_config içinde
Port 2222

Tabii 2222 de yaygın bir alternatif, bu yüzden 49152-65535 arasındaki yüksek portlar daha iyi tercih. Örneğin 57843 gibi rastgele bir şey. Firewall’da da bu portu açmayı unutmayın:

ufw allow 57843/tcp
ufw reload

Root Girişini Kapatmak

Bu tartışmasız yapılması gereken en önemli adım:

PermitRootLogin no

Eğer root erişimine gerçekten ihtiyaç duyuyorsanız, sudo kullanın. Normal bir kullanıcıyla giriş yapıp ardından sudo su veya doğrudan sudo komutu çok daha güvenli.

Parola Doğrulamasını Kapatmak

SSH key-based authentication kullanıyorsanız (ve kullanmalısınız), parola girişini tamamen kapatın:

PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

Bu adımı yapmadan önce SSH anahtarlarınızı mutlaka kurmuş olun. Aksi takdirde kendinizi kilitlersiniz.

Diğer Kritik Parametreler

# Boş parola ile girişi engelle
PermitEmptyPasswords no

# X11 forwarding genelde gerekmez, kapat
X11Forwarding no

# Maksimum kimlik doğrulama denemesi
MaxAuthTries 3

# Oturum limiti
MaxSessions 10

# İzin verilen kimlik doğrulama yöntemleri
AuthenticationMethods publickey

# TCP keepalive
ClientAliveInterval 300
ClientAliveCountMax 2

# DNS lookup'ı kapat (bağlantı hızını artırır)
UseDNS no

# Banner göster (opsiyonel ama güzel)
Banner /etc/ssh/banner.txt

ClientAliveInterval 300 ve ClientAliveCountMax 2 ayarları, 10 dakika boyunca yanıt vermeyen bağlantıları otomatik olarak kapatır. Zombi oturumlarla uğraşmak zorunda kalmazsınız.

SSH Key Yönetimi: Doğru Yapıldığında

SSH anahtarı oluşturmak basit ama doğru algoritma seçimi önemli. 2024 itibarıyla Ed25519 kullanın. RSA 2048 artık yetersiz, RSA 4096 kabul edilebilir ama Ed25519 hem daha güvenli hem de daha hızlı.

İstemci tarafında (kendi bilgisayarınızda):

# Ed25519 anahtar oluştur
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/debian_server

# Güçlü parola ile koruyun, boş bırakmayın
# Anahtarı sunucuya kopyala
ssh-copy-id -i ~/.ssh/debian_server.pub -p 57843 kullanici@sunucu_ip

Sunucu tarafında izinleri kontrol edin:

# .ssh dizini ve authorized_keys dosyası izinleri kritik
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh

Bu izinler yanlışsa SSH anahtarları çalışmaz ve insanlar saatler harcayabilir nedenini bulmak için.

Allowed Users ile Erişim Kontrolü

Hangi kullanıcıların SSH ile giriş yapabileceğini sınırlayın:

# /etc/ssh/sshd_config
AllowUsers deploy admin monitoring

# Belirli grupları da kullanabilirsiniz
AllowGroups sshusers sudo

Bu şekilde, sisteminizde başka kullanıcı hesapları olsa bile SSH üzerinden giriş yapabilecekler yalnızca belirttiğiniz kişiler olur.

İki Faktörlü Kimlik Doğrulama (2FA)

SSH key’in yanına bir de 2FA eklemek istiyorsanız, Google Authenticator PAM modülü kullanabilirsiniz:

apt update
apt install libpam-google-authenticator

Kullanıcı olarak (root değil) TOTP kurulumunu yapın:

google-authenticator

Gelen sorulara:

  • Time-based tokens? y
  • Update .google_authenticator? y
  • Disallow multiple uses? y
  • Extend window? n
  • Enable rate limiting? y

PAM konfigürasyonunu güncelleyin:

# /etc/pam.d/sshd dosyasının en üstüne ekle
auth required pam_google_authenticator.so

SSH konfigürasyonunu da güncelleyin:

# /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Artık hem SSH anahtarı hem de telefondaki kod gerekecek. Bu kombinasyon anahtar çalınsa bile hesabı koruyor.

Fail2Ban ile Brute Force Koruması

Parola doğrulamasını kapatsanız bile, hâlâ log dosyalarını kalabalıklaştıran ve kaynak tüketen saldırılar gelmeye devam eder. Fail2ban bu trafiği keser:

apt install fail2ban

SSH için özel bir jail konfigürasyonu oluşturalım:

nano /etc/fail2ban/jail.d/sshd.conf
[sshd]
enabled = true
port = 57843
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 192.168.1.0/24

maxretry 3: 10 dakika içinde 3 başarısız deneme. bantime 3600: 1 saat yasak. ignoreip: Kendi ağınızı beyaz listeye alın, yoksa kendinizi kilitleyebilirsiniz.

Fail2ban’ı başlatın:

systemctl enable fail2ban
systemctl start fail2ban

# Durumu kontrol et
fail2ban-client status sshd

# Yasaklı IP'leri listele
fail2ban-client status sshd | grep "Banned IP"

Geçici olarak kendinizi kilitlediyseniz:

fail2ban-client set sshd unbanip 1.2.3.4

Firewall ile Kaynak IP Kısıtlaması

Eğer sabit IP adresinizden yönetim yapıyorsanız, SSH erişimini yalnızca o IP’ye kısıtlayın. Bu, dünyanın geri kalanını tamamen dışarıda bırakır:

# Sadece belirli IP'den SSH erişimi
ufw allow from 85.x.x.x to any port 57843

# Ya da bir subnet için
ufw allow from 192.168.100.0/24 to any port 57843

# Genel erişimi reddet
ufw deny 57843

Dinamik IP kullanıyorsanız bu yaklaşım pratik değil. Bu durumda VPN üzerinden SSH erişimi kombinasyonu düşünebilirsiniz. Wireguard kurup sadece VPN IP aralığına SSH açmak, hem güvenli hem de esnek bir çözüm.

SSH Log İzleme

Ne kadar sertleştirme yaparsanız yapın, log izleme şart. Günlük olarak SSH loglarını gözden geçirin:

# Başarısız giriş denemeleri
grep "Failed password" /var/log/auth.log | tail -20

# Başarılı girişler
grep "Accepted" /var/log/auth.log | tail -20

# Belirli bir IP'den gelen denemeler
grep "Failed" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -10

# Journald ile
journalctl -u ssh --since "1 hour ago"

Bunları otomatik hale getirmek için basit bir script yazabilirsiniz:

#!/bin/bash
# /usr/local/bin/ssh-report.sh

echo "=== SSH Güvenlik Raporu - $(date) ==="
echo ""
echo "Son 24 saatte başarısız girişler:"
grep "Failed" /var/log/auth.log | grep "$(date --date='yesterday' '+%b %e')|$(date '+%b %e')" | wc -l

echo ""
echo "En çok deneme yapan IP'ler:"
grep "Failed" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -5

echo ""
echo "Başarılı girişler:"
grep "Accepted" /var/log/auth.log | grep "$(date '+%b %e')" | tail -10

echo ""
echo "Mevcut fail2ban yasakları:"
fail2ban-client status sshd 2>/dev/null | grep "Banned IP"

Bunu cron’a ekleyip her sabah mail olarak alabilirsiniz.

SSH Sertifika Tabanlı Kimlik Doğrulama

Büyük ortamlarda düzinelerce sunucu ve kullanıcı varken, her sunucuya her kullanıcının public key’ini dağıtmak kabus haline gelir. SSH CA (Certificate Authority) kullanmak bu sorunu çözer.

Temel mantık şu: Kendi CA anahtarınızı oluşturuyorsunuz, kullanıcıların public key’lerini bu CA ile imzalıyorsunuz, sunucular yalnızca CA’nıza güveniyor. Yeni bir sunucu eklediğinizde sadece CA’nızın public key’ini kopyalamanız yeterli.

# CA anahtarı oluştur (güvenli bir makinede)
ssh-keygen -t ed25519 -f /etc/ssh/ca_key -C "SSH CA - sirket.com"

# Kullanıcı public key'ini imzala
ssh-keygen -s /etc/ssh/ca_key 
  -I "[email protected]" 
  -n admin 
  -V +52w 
  ~/.ssh/id_ed25519.pub

Sunucuda CA’ya güven ekleyin:

# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub

-V +52w ile sertifika 1 yıl için geçerli oluyor. Bu, ayrılmış çalışanların anahtarlarını tek tek silmek yerine, sertifikalarının süresinin dolmasını bekleyebileceğiniz anlamına geliyor.

Konfigürasyon Testi ve Servisi Yeniden Başlatma

Her değişiklik sonrası sshd konfigürasyonunu test edin:

# Konfigürasyon syntax kontrolü
sshd -t

# Daha detaylı test
sshd -T | grep -E "port|permitrootlogin|passwordauth|pubkeyauth|maxauthtries"

Hata yoksa servisi yeniden yükleyin:

# Reload (mevcut bağlantıları kesmez)
systemctl reload ssh

# Ya da restart
systemctl restart ssh

Altın kural: Yeni terminal sekmesinde bağlantıyı test etmeden mevcut bağlantınızı kapatmayın. Her zaman test önce.

Tüm Değişikliklerin Özeti

Yapılan sertleştirmeleri doğrulayan bir kontrol scripti:

#!/bin/bash
echo "=== SSH Sertleştirme Kontrol Listesi ==="

check_param() {
    local param=$1
    local expected=$2
    local actual=$(sshd -T 2>/dev/null | grep -i "^$param " | awk '{print $2}')
    
    if [ "$actual" = "$expected" ]; then
        echo "[OK] $param: $actual"
    else
        echo "[UYARI] $param: $actual (beklenen: $expected)"
    fi
}

check_param "permitrootlogin" "no"
check_param "passwordauthentication" "no"
check_param "permitemptypasswords" "no"
check_param "x11forwarding" "no"
check_param "maxauthtries" "3"
check_param "pubkeyauthentication" "yes"

echo ""
echo "Port:"
sshd -T 2>/dev/null | grep "^port "

echo ""
echo "Fail2ban durumu:"
systemctl is-active fail2ban

echo ""
echo "UFW durumu:"
ufw status | grep -E "ssh|22|5784"

Sonuç

SSH sertleştirmesi bir kere yapıp unutulacak bir iş değil. Sistemin dinamiklerine göre periyodik olarak gözden geçirilmesi gerekiyor. Yeni bir kullanıcı eklediğinizde AllowUsers listesini güncelleyin. Ayrılan bir çalışanın anahtarını hemen silin. Log raporlarını düzenli okuyun.

Bu yazıda anlattıklarımı özetleyecek olursam: Portu değiştirin, root girişini kapatın, parola doğrulamasını devre dışı bırakın, güçlü algoritmalarla SSH anahtarı kullanın, fail2ban kurun, firewall kurallarını sıkılaştırın ve logları izleyin. Bu adımları uygulayan bir Debian sunucusu, internetteki botların ezici çoğunluğu için gerçekten değmez hale gelir.

Sıfırdan Debian kurarken bu adımları baştan uygulamak, sonradan düzeltmeye çalışmaktan her zaman daha kolay. Deployment pipeline’ınıza bir SSH sertleştirme aşaması ekleyin, Ansible veya başka bir configuration management aracı kullanıyorsanız bu ayarları idempotent hale getirin. Güvenlik, sonradan akılda kalan bir şey değil, baştan planlanan bir mimari olmalı.

Yorum yapın