SSH Bağlantısı Neden Yavaş: Gecikme Sorunlarını Giderme
Yıllar içinde kaç tane “SSH neden bu kadar yavaş açılıyor?” sorusu aldım bilmiyorum. Özellikle yeni bir sunucuya geçiş yapıldıktan sonra ya da network altyapısı değiştiğinde bu soru kaçınılmaz olarak geliyor. Bağlantı sonunda açılıyor ama o 10-30 saniyelik bekleme insanı çıldırtıyor. Bu yazıda sorunu gerçekten adım adım izole edip çözmeyi anlatacağım, teorik değil, sahada işe yarayan yöntemlerle.
Önce Gecikmenin Nerede Olduğunu Anlayın
SSH bağlantısı yavaşladığında çoğu insan hemen sshd_config’e dalıyor. Ama önce gecikmenin hangi aşamada olduğunu tespit etmek şart. Bunun için en basit araç -vvv flag’i:
ssh -vvv kullanici@sunucu_ip 2>&1 | head -50
Bu çıktıyı dikkatlice okuyun. Gecikme şu noktalarda yaşanıyor olabilir:
- TCP bağlantısı kurulurken (network katmanı)
- Anahtar alışverişi sırasında (kriptografik işlemler)
- Kimlik doğrulama aşamasında (DNS, PAM, LDAP)
- Oturum açıldıktan sonra (MOTD, shell başlatma)
Verbose çıktıda hangi satırdan sonra duraksıyor? debug1: SSH2_MSG_SERVICE_ACCEPT received satırından önce mi sonra mı? Bu sorunun cevabı sizi doğrudan doğru yöne götürür.
Bir de şunu yapın: Bağlantı süresini ölçün.
time ssh kullanici@sunucu_ip 'echo baglanti_ok'
Eğer bağlantı 15-20 saniye sürüyorsa ve verbose çıktıda debug1: Trying to reverse map address ya da benzeri bir şey görüyorsanız, cevap büyük ihtimalle DNS’te.
En Yaygın Neden: Ters DNS Çözümleme
SSH daemon’ı varsayılan olarak bağlanan istemcinin IP adresini ters DNS ile çözmeye çalışır. Eğer DNS sunucunuz yavaşsa veya ters kayıt yoksa bu işlem timeout’a kadar bekler. Özellikle iç ağda kurulu DNS olmayan ortamlarda bu çok sık karşılaşılan bir durum.
/etc/ssh/sshd_config dosyasında şu satırı kontrol edin:
grep -i "usedns|GSSAPIAuthentication" /etc/ssh/sshd_config
Eğer UseDNS yes yazıyorsa veya hiç yoksa (varsayılan eski sistemlerde yes), bunu değiştirin:
# /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no
GSSAPIDelegateCredentials no
Değişikliği uygulayın:
sudo systemctl restart sshd
# veya eski sistemlerde:
sudo service ssh restart
GSSAPIAuthentication konusunda biraz daha durmak istiyorum çünkü bu da ciddi gecikme yaratıyor. Kerberos tabanlı kimlik doğrulama kullanmıyorsanız, GSSAPI denemesi yaparken sunucu Kerberos ticket kontrolü için bekliyor. Bu hem sunucu tarafında hem istemci tarafında kapatılması gereken bir şey.
İstemci tarafında:
# ~/.ssh/config veya /etc/ssh/ssh_config
Host *
GSSAPIAuthentication no
GSSAPIDelegateCredentials no
DNS Sorununu Daha Derinlemesine İncelemek
Sunucunun DNS çözümlemesinin ne kadar sürdüğünü ölçmek için:
# Sunucu tarafında çalıştırın
time host 192.168.1.100
# veya
time nslookup 192.168.1.100
Eğer bu komutlar 5-10 saniye bekliyorsa sorun kesinlikle DNS. /etc/resolv.conf dosyanıza bakın:
cat /etc/resolv.conf
Birden fazla nameserver varsa ve birincisi cevap vermiyorsa ikinciye geçmesi zaman alıyor. Yavaş veya erişilemeyen nameserver’ları kaldırın. Ayrıca timeout ve attempts parametrelerini düşürebilirsiniz:
# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
options timeout:2 attempts:2
/etc/nsswitch.conf dosyasında hosts satırını da kontrol edin. Bazı sistemlerde mdns4 veya başka servisler DNS zincirinde gereksiz yere yer alıyor olabilir.
PAM ve Login Gecikmeleri
DNS’i kapattınız ama hala yavaş mı? Sıra PAM’de. Özellikle Ubuntu ve Debian sistemlerde pam_motd ve diğer PAM modülleri gecikme yaratabilir. Daha da önemlisi, bazı sistemlerde pam_systemd veya pam_exec modülleri timeout’a düşen harici scriptler çalıştırıyor olabilir.
PAM loglarını kontrol etmek için:
sudo tail -f /var/log/auth.log | grep -i "pam|sshd"
Paralelde SSH bağlantısı kurun ve loglara bakın. Hangi PAM modülünde takılıyor?
/etc/pam.d/sshd dosyasını inceleyin:
cat /etc/pam.d/sshd
Özellikle şunu arayın: pam_nologin, pam_env, ya da pam_exec satırları. Gereksiz modüller varsa yorum satırına alın (dikkatli olun, PAM konfigürasyonunu yanlış yapmak sisteme girişi tamamen kesebilir).
lastlog kontrolü de gecikme yaratabilir. Büyük sistemlerde /var/log/lastlog dosyası çok büyüyebilir ve her login’de bu dosyaya yazma işlemi yavaşlıyor olabilir:
ls -lh /var/log/lastlog
Eğer bu dosya gigabyte mertebesindeyse, pam_lastlog modülünü sshd için devre dışı bırakabilirsiniz.
SSH İstemci Tarafı Optimizasyonları
Sunucu tarafında her şey yolunda görünüyorsa istemci konfigürasyonuna bakın. ~/.ssh/config dosyası SSH bağlantılarını dramatik şekilde hızlandırabilir.
# ~/.ssh/config
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
ConnectTimeout 10
GSSAPIAuthentication no
Host production-servers
HostName 10.0.1.0/24
User deployer
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist 10m
ControlMaster ve ControlPersist özelliği özellikle dikkat çekici. İlk bağlantıyı açtıktan sonra aynı host’a yapılan sonraki bağlantılar mevcut TCP bağlantısını yeniden kullanıyor, yani yeni handshake, yeni kimlik doğrulama yok. Özellikle Ansible veya sık sık SSH açıp kapattığınız durumlarda bu büyük fark yaratıyor.
Socket dizinini oluşturmayı unutmayın:
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets
Şifreleme Algoritması Seçimi
Eski sunucularda veya düşük CPU’lu cihazlarda (Raspberry Pi, bazı VM’ler, eski bare metal) kriptografik işlemler gecikme yaratabilir. Hangi şifreleme algoritmalarının desteklendiğini görmek için:
ssh -Q cipher
ssh -Q kex
ssh -Q mac
Daha hızlı algoritmalar kullanmak için hem istemci hem sunucu tarafında yapılandırma yapabilirsiniz. Modern sistemlerde chacha20-poly1305 veya [email protected] genellikle en iyi performansı veriyor:
# ~/.ssh/config (istemci)
Host *
Ciphers [email protected],[email protected],[email protected]
KexAlgorithms curve25519-sha256,[email protected]
MACs [email protected],[email protected]
Gerçekten düşük kapasiteli bir cihazda SSH performansını test etmek için:
# Şifreleme hızını test et
openssl speed aes-128-cbc aes-256-cbc
# veya SSH bağlantısında transfer hızını ölç
time ssh user@host 'dd if=/dev/zero bs=1M count=100 2>/dev/null' | wc -c
Network Katmanı: MTU ve TCP Sorunları
Bazen gecikme network katmanında oluyor. Özellikle VPN üzerinden SSH açarken MTU uyuşmazlıkları ciddi sorun yaratabilir. Paket fragmentasyonu olduğunda TCP bağlantısı kurulabiliyor ama data transferi yavaşlıyor ya da takılıyor.
MTU sorununu test etmek için:
# Farklı paket boyutları ile ping at, DF (Don't Fragment) bit'i set
ping -M do -s 1472 sunucu_ip
ping -M do -s 1400 sunucu_ip
# VPN üzerinde genellikle 1400 veya daha düşük MTU gerekir
Eğer büyük paketler gitmiyorsa ama küçükler gidiyorsa MTU sorunudur. SSH’ın IPQoS ayarını devre dışı bırakmak da bazen yardımcı oluyor:
# ~/.ssh/config
Host *
IPQoS none
TCP keepalive değerlerini de kontrol edin. Uzun süre idle kalan SSH bağlantıları ortadaki firewall veya NAT cihazları tarafından koparılıyor olabilir:
# Sunucu tarafı sshd_config
ClientAliveInterval 30
ClientAliveCountMax 6
TCPKeepAlive yes
MOTD ve Shell Başlatma Yavaşlığı
Bağlantı kurulduktan sonra shell açılırken yaşanan gecikme farklı bir kategori. Bu genellikle .bashrc, .bash_profile, ya da /etc/profile.d/ altındaki scriptlerden kaynaklanıyor.
Bunu izole etmek için şunu deneyin:
# Shell başlatma scriptleri çalıştırmadan bağlan
ssh -t kullanici@sunucu 'bash --norc --noprofile'
Eğer bu hızlı açılıyorsa sorun shell konfigürasyon dosyalarında. /etc/profile.d/ altındaki tüm scriptleri inceleyin:
ls -la /etc/profile.d/
# Her birini zamanlayarak test et
time bash -c 'source /etc/profile.d/sorunlu_script.sh'
MOTD konusunda da bir not düşeyim: /etc/update-motd.d/ altındaki dinamik MOTD scriptleri her login’de çalışıyor. Özellikle 50-landscape-sysinfo veya 90-updates-available gibi scriptler network çağrısı yapabiliyor veya disk I/O yoğun işlemler yapabiliyor.
# Hangi MOTD scriptleri var ve ne kadar sürüyor?
ls -la /etc/update-motd.d/
time run-parts /etc/update-motd.d/
Yavaş olanları devre dışı bırakın:
sudo chmod -x /etc/update-motd.d/50-landscape-sysinfo
sudo chmod -x /etc/update-motd.d/90-updates-available
Systemd-Resolved ve Modern Dağıtımlar
Ubuntu 18.04 ve sonrasında, CentOS 8, RHEL 8 gibi modern dağıtımlarda DNS çözümleme artık systemd-resolved üzerinden geçiyor. Bu servisin kendi cache mekanizması var ama bazen de sorun çıkarabiliyor.
# systemd-resolved durumu
systemctl status systemd-resolved
# DNS sorgularını debug et
resolvectl query 8.8.8.8
resolvectl statistics
# Cache'i temizle
sudo resolvectl flush-caches
Eğer systemd-resolved servisinde sorun varsa geçici olarak direkt /etc/resolv.conf‘a yazabilirsiniz ama dikkatli olun, bu dosya symlink olabilir:
ls -la /etc/resolv.conf
# Eğer symlink ise önce kaldırın, sonra dosya oluşturun
sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
Gerçek Dünya Senaryosu: Staging Ortamında 25 Saniyelik Gecikme
Bir keresinde şirketin staging ortamında her SSH bağlantısı 25 saniye gecikiyordu. Prod’da sorun yoktu. İlginç bir durum.
-vvv ile bakıldığında debug1: pledge: network satırından sonra uzun süre bekliyordu. DNS değildi çünkü UseDNS no zaten vardı. GSSAPI de kapalıydı.
Sonunda şu komutu çalıştırdım:
sudo strace -p $(pgrep -f "sshd.*notty" | head -1) -e trace=network,file 2>&1 | head -100
Ve gördüm ki sshd, her bağlantıda /etc/security/access.conf dosyasını okumaya çalışıyor ve pam_access modülü hostname çözümlemesi yapıyordu. PAM konfigürasyonunda pam_access modülü vardı ve bu modül bağlanan IP’nin hostname’ini çözmeye çalışıyordu. Staging ortamında iç DNS yoktu, timeout bekleniyor, sonra bağlantı devam ediyordu.
Çözüm:
# /etc/pam.d/sshd içinde
# account required pam_access.so <-- bu satırı yorum yaptık
# veya access.conf'ta nodefgroup kullandık
Bu tür problemleri strace olmadan bulmak çok zordu.
Toplu Kontrol Scripti
Birden fazla sunucuyu yönetiyorsanız SSH yavaşlığını otomatik kontrol eden küçük bir script işinize yarayabilir:
#!/bin/bash
SUNUCU="$1"
KULLANICI="${2:-root}"
echo "=== SSH Gecikme Tanılama ==="
echo "Hedef: $KULLANICI@$SUNUCU"
echo ""
# Bağlantı süresini ölç
echo "[1] Bağlantı süresi ölçülüyor..."
BASLANGIC=$(date +%s%N)
ssh -o ConnectTimeout=30 -o GSSAPIAuthentication=no "$KULLANICI@$SUNUCU" 'echo OK' > /dev/null 2>&1
BITIS=$(date +%s%N)
SURE=$(( (BITIS - BASLANGIC) / 1000000 ))
echo " Toplam sure: ${SURE}ms"
# DNS çözümleme süresi
echo "[2] DNS çözümleme süresi..."
time host "$SUNUCU" > /dev/null 2>&1
# Verbose çıktıdan gecikme noktasını bul
echo "[3] Verbose SSH çıktısı (ilk 30 satır)..."
ssh -vvv -o ConnectTimeout=15 -o GSSAPIAuthentication=no "$KULLANICI@$SUNUCU" 'echo OK' 2>&1 | grep -E "debug1: (Connecting|Authentication|pledge|SSH2_MSG)" | head -20
Özet: Kontrol Listesi
Gecikme giderme sürecini sistematik hale getirmek için şu sırayı takip edin:
- İlk adım:
ssh -vvvile gecikmenin hangi aşamada olduğunu tespit edin - UseDNS no: Sunucu tarafında sshd_config’e ekleyin, çoğu sorunu çözer
- GSSAPIAuthentication no: Hem sunucu hem istemci tarafında kapatın
- PAM logları:
/var/log/auth.log‘u real-time izleyin, hangi modülde takılıyor? - MOTD scriptleri:
/etc/update-motd.d/altındakileri zamanlayın, yavaş olanları devre dışı bırakın - Shell profil dosyaları:
.bashrc,.bash_profileve/etc/profile.d/altındaki scriptler - ControlMaster: Sık bağlantı açıyorsanız kesinlikle aktive edin
- MTU sorunları: VPN kullanıyorsanız ping ile MTU’yu test edin
- systemd-resolved: Modern dağıtımlarda DNS cache sorunlarını kontrol edin
- strace: Son çare ama bazen hayat kurtarıyor
Sonuç
SSH gecikmesi genellikle iki ana kategoride: DNS/hostname çözümleme ve PAM kimlik doğrulama zinciri. Bu ikisini çözdüğünüzde sorunun yüzde doksanı gidiyor. Kalan yüzde on ise genellikle MTU uyuşmazlığı, yavaş MOTD scriptleri veya shell konfigürasyon dosyalarından geliyor.
En önemli tavsiye: Körü körüne değişiklik yapmayın. -vvv çıktısını okuyun, loglara bakın, strace kullanmaktan çekinmeyin. Sistemin size söylediği şeyleri dinleyin. SSH son derece verbose bir protokol, sorun nerede olursa olsun size bırakmaz.
Ve şunu da ekleyeyim: Eğer bir sunucuya düzenli olarak bağlanıyorsanız ControlMaster konfigürasyonu yapmak hem gecikmeyi ortadan kaldırıyor hem de günlük iş akışınızı inanılmaz hızlandırıyor. İlk bağlantı ne kadar sürerse sürsün, sonraki bağlantılar milisaniyeler içinde açılıyor. Bunu henüz denemediyseniz, bu yazıdan alacağınız en değerli şey bu olabilir.
