Her zamanki gibi ssh [email protected] yazdınız ve karşınıza şifre istemi yerine bir duvar dolusu ünlem işareti çıktı. Ekranda büyük harflerle "REMOTE HOST IDENTIFICATION HAS CHANGED", altında "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY" ve en sonunda soğuk bir "Host key verification failed" satırı var. Bağlantı kurulmadı.
İnternette bu hatayı arattığınızda ilk çıkan cevapların neredeyse tamamı aynı: ssh-keygen -R sunucu yaz, geç. Bu tavsiye teknik olarak doğrudur ama sıralaması yanlıştır. Çünkü o komut, SSH'ın size vermeye çalıştığı tek uyarıyı susturur. Uyarı %95 ihtimalle masumdur — sunucuyu yeniden kurmuşsunuzdur, IP başkasına geçmiştir. Ama kalan %5, bağlantınızın araya giren biri tarafından dinlendiği durumdur ve o durumda uyarıyı susturmak, saldırgana parolanızı elinizle vermek anlamına gelir.
Bu yazıda önce uyarının hangi mekanizmadan geldiğini anlayacağız, sonra "bu değişiklik meşru mu?" sorusunu cevaplayan bir kontrol listesi kuracağız. Parmak izini sunucu tarafından bant dışı bir kanaldan nasıl doğrulayacağınızı, known_hosts dosyasını nasıl temiz biçimde düzelteceğinizi ve bu sorunun bir daha yaşanmaması için hangi kalıcı yapıların kurulabileceğini ele alacağız.
SSH Sunucuyu Nasıl Tanıyor?#
SSH sunucusu kurulduğunda kendine bir dizi host key üretir. Bunlar /etc/ssh/ altında durur ve genellikle üç çift hâlinde bulunur:
ls -l /etc/ssh/ssh_host_*
# ssh_host_ecdsa_key ssh_host_ecdsa_key.pub
# ssh_host_ed25519_key ssh_host_ed25519_key.pub
# ssh_host_rsa_key ssh_host_rsa_key.pub
Bu anahtar çifti, sunucunun kimliğidir. Kullanıcı kimliğinizi kanıtlayan anahtarlarla karıştırmayın; bu, sunucunun size kendini kanıtladığı anahtardır. Kullanıcı tarafındaki anahtar yönetimi için SSH anahtarı nasıl oluşturulur yazısı ayrı bir konudur.
SSH'ın güven modeli "ilk kullanımda güven" (TOFU — Trust On First Use) olarak adlandırılır. Bir sunucuya ilk kez bağlandığınızda size parmak izini gösterir ve "bunu kabul ediyor musunuz?" diye sorar. Evet dediğinizde anahtar ~/.ssh/known_hosts dosyasına yazılır. Sonraki her bağlantıda istemciniz sunucunun sunduğu anahtarı bu kayıtla karşılaştırır.
Karşılaştırma tutmadığında iki şeyden biri olmuştur: ya sunucunun anahtarı gerçekten değişmiştir, ya da o adres arkasında artık başka bir makine vardır. SSH bu ikisini birbirinden ayıramaz, çünkü ayıramaz olması gerekir — ayırabilseydi zaten güvenlik değeri kalmazdı. Bu yüzden alarmı çalar ve kararı size bırakır.
Ekrandaki Mesajı Satır Satır Okumak#
Uyarı metni gereğinden fazla dramatik görünse de içinde işinize yarayacak somut bilgiler vardır. Tipik çıktı şöyledir:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:9k2LqWc4Xf1nPvR7bTyH0sMdAe6ZjQrK8uNgV3xIoBs.
Please contact your system administrator.
Add correct host key in /home/emre/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/emre/.ssh/known_hosts:14
Host key verification failed.
Bu çıktıda dört bilgi kritik:
| Satır | Ne söylüyor |
|---|---|
The fingerprint ... is SHA256:... | Sunucunun şu anda sunduğu anahtarın parmak izi |
ED25519 key sent by the remote host | Karşı tarafın hangi anahtar türünü sunduğu |
Offending ECDSA key in ...:14 | Sizde kayıtlı olan eski kaydın türü ve satır numarası |
Host key verification failed | Bağlantının hiç kurulmadığı |
İpucu: yeni anahtar ED25519, eski kayıt ECDSA ise bu genellikle sunucunun yeniden kurulduğunu veya istemcinizin tercih sırasının değiştiğini gösterir. Modern OpenSSH sürümleri Ed25519'u önceliklendirir; eski bir kayıt ECDSA olarak tutulmuş olabilir.
Not edin ki parmak izi ekranda yazıyor. Bir sonraki adımda ihtiyacınız olacak, kopyalayın.
Susturmadan Önce: Bu Değişiklik Meşru mu?#
Şimdi asıl soruya geliyoruz. Aşağıdaki senaryolardan hangisi sizin durumunuza uyuyor? Cevabı bilmeden ssh-keygen -R yazmayın.
1. Sunucuyu Yeniden Kurdunuz veya Format Attınız#
En yaygın sebep budur. İşletim sistemi yeniden kurulduğunda /etc/ssh/ssh_host_* dosyaları sıfırdan üretilir; makine aynı, IP aynı, ama kimlik yepyenidir. Sanal sunucunuzu panelden yeniden kurduysanız, snapshot'tan geri döndüyseniz veya sağlayıcı bir donanım arızası sonrası makineyi taşıdıysa bu uyarıyı beklemelisiniz. Bu durumda değişiklik meşrudur.
2. IP Adresi Başka Bir Makineye Geçti#
Bulut sağlayıcıları serbest bırakılan IP adreslerini havuza döndürür. Eski sunucunuzu sildiyseniz ve known_hosts dosyanızda o IP'ye ait kayıt kaldıysa, aynı IP'yi başka bir müşteri aldığında siz bağlanmaya çalıştığınızda bu uyarıyı alırsınız. DNS kaydınızı yeni bir sunucuya yönlendirdiyseniz de aynı şey olur: alan adı aynı, arkasındaki makine farklı.
3. Araya Bir Katman Girdi#
Bazen makine değişmemiştir, yol değişmiştir. Şu değişikliklerin hepsi anahtar uyuşmazlığı üretir:
- Bir jump host veya bastion üzerinden geçmeye başladınız
- Port yönlendirmesi kurdunuz ve
localhost:2222artık başka bir sunucuya gidiyor - Yük dengeleyici arkasında birden fazla SSH sunucusu var ve her biri farklı anahtara sahip
- Konteyner yeniden oluşturuldu ve içindeki SSH sunucusu yeni anahtar üretti
Bastion mimarisinin nasıl kurulduğunu merak ediyorsanız SSH jump host ve bastion sunucu yazısı konuyu ayrıntısıyla ele alıyor.
4. Gerçekten Şüphe Edilmesi Gereken Durumlar#
Aşağıdakilerden herhangi biri geçerliyse durun ve doğrulama yapmadan bağlanmayın:
- Sunucuda hiçbir değişiklik yapılmadı, kimse bir şey kurmadı, ama uyarı bugün ortaya çıktı
- Uyarıyı yalnızca belirli bir ağdan (otel, kafe, konferans Wi-Fi'ı, bir VPN çıkışı) alıyorsunuz; başka bir bağlantıdan sorun yok
- Aynı sunucuya farklı bir bilgisayardan sorunsuz bağlanabiliyorsunuz
- Parmak izi doğrulaması yaptınız ve sunucudaki değer ekrandakiyle uyuşmuyor
Bu tabloyu karar mekanizması olarak kullanabilirsiniz:
| Belirti | Muhtemel sebep | Aksiyon |
|---|---|---|
| Sunucuyu yeni kurdunuz | Yeni host key üretildi | Parmak izini doğrula, kaydı sil |
| IP'yi yeni aldınız / DNS taşındı | Adres başka makinede | Doğrula, kaydı sil |
| Yalnızca tek bir ağda oluyor | Araya giren cihaz olabilir | O ağdan bağlanma, güvenli ağdan dene |
| Hiçbir değişiklik yok, aniden çıktı | Ele geçirme veya dinleme | Doğrula, uymuyorsa olay müdahalesi |
| Başka makineden sorunsuz | İstemci veya ağ kaynaklı | Yerel ağı ve DNS'i incele |
Araya giren cihaz senaryosunun teknik ayrıntısı için MITM saldırısı nedir yazısı bu uyarının neden var olduğunu iyi açıklıyor.
Parmak İzini Sunucu Tarafından Doğrulama#
Karar vermenin tek doğru yolu, sunucudaki gerçek parmak izini SSH dışında bir kanaldan öğrenmektir. Buradaki "SSH dışında" ifadesi kritiktir: eğer ağınızda dinleyen biri varsa, o ağ üzerinden yaptığınız her sorgu de aynı kişinin kontrolündedir.
Güvenilir kanallar şunlardır: sağlayıcınızın panelindeki VNC/KVM konsolu, sunucunun fiziksel konsolu, sunucu kurulumu sırasında kaydettiğiniz not ya da otomasyon aracınızın (Ansible, Terraform) çıktısı.
Konsola girdikten sonra parmak izlerini şu komutla alın:
# Tek tek anahtarlar
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
# Hepsini birden
for k in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$k"; done
Çıktı şuna benzer:
256 SHA256:9k2LqWc4Xf1nPvR7bTyH0sMdAe6ZjQrK8uNgV3xIoBs root@web01 (ED25519)
Bu değeri, hata mesajındaki SHA256: satırıyla harfi harfine karşılaştırın. Eşleşiyorsa değişiklik meşrudur, rahatça devam edebilirsiniz. Eşleşmiyorsa o bağlantıyı kullanmayın; başka bir ağdan tekrar deneyin ve sunucuda yetkisiz erişim olup olmadığını araştırın. Ele geçirilmiş bir sistemde izlenecek adımlar için hacklenmiş site kurtarma yazısındaki müdahale sırası iyi bir başlangıçtır.
Bir uyarı: ssh-keyscan komutu cazip görünür ama bu doğrulama için işe yaramaz. Çünkü anahtarı yine aynı şüpheli ağ üzerinden sorar; araya giren biri varsa size kendi anahtarını gösterir ve "doğrulama" sahte bir güven üretir. Yalnızca ağın güvenli olduğundan eminken, örneğin toplu envanter çıkarmak için kullanın.
Eski dokümanlarda MD5 parmak izi görürseniz karşılaştırmayı aynı formatta yapabilirsiniz:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E md5
ssh -o FingerprintHash=md5 [email protected]
known_hosts Dosyasını Doğru Temizlemek#
Değişikliğin meşru olduğuna karar verdiyseniz artık eski kaydı silebilirsiniz. Doğru araç ssh-keygen -R:
# Alan adına göre
ssh-keygen -R sunucu.ornek.com
# IP adresine göre (ayrı bir kayıt olabilir)
ssh-keygen -R 203.0.113.45
# Standart dışı port kullanıyorsanız köşeli parantez şart
ssh-keygen -R "[sunucu.ornek.com]:2222"
Komut çalıştığında eski known_hosts dosyanızı known_hosts.old olarak yedekler; bir hata yaparsanız geri dönebilirsiniz.
Üç ayrıntı çok kişinin başını ağrıtır:
Hem alan adı hem IP kaydı olabilir. OpenSSH'ın eski sürümlerinde CheckHostIP varsayılan olarak açıktı ve her sunucu için iki kayıt yazılırdı. Alan adını sildiniz ama uyarı devam ediyorsa, IP'yi de silin.
Kayıtlar karma (hash) olarak tutulabilir. Birçok dağıtımda HashKnownHosts yes varsayılandır; dosyayı açtığınızda okunabilir sunucu adı yerine |1|xK3d... gibi satırlar görürsünüz. Bu durumda grep işe yaramaz, ama ssh-keygen bilir:
# İlgili kaydı bul (satır numarasıyla birlikte)
ssh-keygen -F sunucu.ornek.com
# Bulunan kaydı sil
ssh-keygen -R sunucu.ornek.com
Sistem geneli bir dosya olabilir. Kişisel ~/.ssh/known_hosts dışında /etc/ssh/ssh_known_hosts dosyası da devrededir ve genellikle yapılandırma yönetimi tarafından dağıtılır. Uyarı root dâhil bütün kullanıcılarda çıkıyorsa bakılacak yer burasıdır.
Hata mesajındaki satır numarasını kullanarak elle silmek de mümkündür ama önerilmez:
sed -i.yedek '14d' ~/.ssh/known_hosts
Bu yöntem, aynı dosyada birden fazla düzeltme yaparken satır numaraları kaydığı için yanlış kaydı silmeye çok müsaittir.
Sildikten sonra tekrar bağlanın. SSH size yeni parmak izini gösterip onay isteyecektir; gösterilen değerin sunucudan aldığınız değerle aynı olduğunu bir kez daha kontrol edip yes yazın.
Windows, PuTTY ve Otomasyon Tarafı#
Windows'un yerleşik OpenSSH istemcisi Linux ile aynı şekilde çalışır; dosya C:\Users\kullaniciadi\.ssh\known_hosts yolundadır ve ssh-keygen -R komutu PowerShell'de de geçerlidir. Windows'tan bağlantı kurmanın genel ayarları için Windows bilgisayardan sunucuya SSH bağlantısı yazısına bakabilirsiniz.
ssh-keygen -R sunucu.ornek.com
PuTTY farklı davranır: host key kayıtlarını dosyada değil kayıt defterinde tutar. Uyarı penceresi çıktığında "Kabul et" demeden önce gösterilen parmak izini yine doğrulayın. Kayıtları temizlemek isterseniz HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys altındaki ilgili değeri silin.
Otomasyon tarafında (CI boru hattı, Ansible, yedekleme betiği) bu uyarı bağlantıyı durdurur ve işi başarısız yapar. Burada en sık görülen çözüm de en kötüsüdür:
# YAPMAYIN
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null kullanici@sunucu
Bu iki seçenek birlikte, SSH'ın sunucu doğrulamasını tamamen devre dışı bırakır. Yedekleme betiğiniz artık her sunucuya, kimliği ne olursa olsun bağlanır ve içine parolanızı ya da veritabanı dökümünüzü teslim eder. Kabul edilebilir en yakın alternatif, yalnızca yeni anahtarları otomatik kabul eden moddur:
ssh -o StrictHostKeyChecking=accept-new kullanici@sunucu
Bu mod, ilk bağlantıda anahtarı sessizce ekler ama değişmiş bir anahtarda yine durur — yani uyarı mekanizmasını korur. Gerçek çözüm ise bir sonraki bölümde.
Bir Daha Yaşamamak İçin Kalıcı Önlemler#
Uyarıyı her seferinde elle temizlemek yerine, yeniden kurulumların ve makine değişikliklerinin bu sorunu hiç üretmemesini sağlayabilirsiniz.
1. Host key'leri yedekleyip geri yükleyin. Sunucuyu yeniden kuracaksanız eski anahtarları saklayın ve kurulumdan sonra geri koyun. Kimlik değişmez, hiçbir istemci uyarı almaz:
# Eski sunucudan al
tar czf host-keys.tar.gz /etc/ssh/ssh_host_*
# Yeni kurulumda geri yükle
tar xzf host-keys.tar.gz -C /
chmod 600 /etc/ssh/ssh_host_*_key
chmod 644 /etc/ssh/ssh_host_*_key.pub
chown root:root /etc/ssh/ssh_host_*
systemctl restart sshd
İzinler önemlidir: özel anahtar dosyaları fazla açık izinlere sahipse sshd başlamaz. Anahtar dosyası izinlerinin genel mantığı için private key güvenliği yazısı aynı prensipleri anlatır.
2. SSH sertifika otoritesi (CA) kurun. Onlarca sunucusu olan ortamlarda en temiz çözüm budur. Tek bir CA anahtarıyla her sunucunun host key'ini imzalarsınız; istemcilerde tek bir satır yeterli olur ve sunucu yeniden kurulduğunda yalnızca yeni sertifikayı imzalamanız gerekir, hiçbir istemci dosyası değişmez.
# CA ile sunucu anahtarını imzala (1 yıl geçerli)
ssh-keygen -s ca_key -I web01 -h -n web01.ornek.com,203.0.113.45 \
-V +52w /etc/ssh/ssh_host_ed25519_key.pub
Sunucu tarafında sshd_config içine HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub satırını ekleyin. İstemcilerin known_hosts dosyasına ise tek satır girer:
@cert-authority *.ornek.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
3. Anahtar dağıtımını yapılandırma yönetimine bırakın. Ansible, Puppet veya Salt kullanıyorsanız /etc/ssh/ssh_known_hosts dosyasını merkezden dağıtın. Böylece yeni bir sunucu envantere girdiğinde bütün ekibin istemcisi onu zaten tanır.
4. Parmak izlerini kayıt altına alın. Sunucu kurulum prosedürünüze "host key parmak izlerini şifre kasasına yaz" adımını ekleyin. Aylar sonra bir uyarı aldığınızda doğrulama yapacak referansınız olur.
SSH sunucusunun genel sıkılaştırma ayarları — port değişikliği, parola girişinin kapatılması, izin verilen kullanıcılar — için SSH bağlantısı ve güvenliği yazısı tamamlayıcı bir kaynaktır.
Yapılmaması Gerekenler#
Bu üç davranış, uyarıyı çözmez; yalnızca gizler.
known_hosts dosyasını tamamen silmek. rm ~/.ssh/known_hosts bir sunucunun sorununu çözerken bağlandığınız diğer bütün sunucuların güven kaydını da yok eder. Bir sonraki bağlantıda hepsini yeniden "ilk kez" kabul edersiniz ve o an araya giren biri varsa fark etmezsiniz.
StrictHostKeyChecking=no ayarını kalıcı hâle getirmek. ~/.ssh/config dosyasına Host * altında yazılan bu satır, bütün SSH kullanımınız boyunca sunucu doğrulamasını etkisiz kılar. accept-new her durumda daha iyi bir tercihtir.
Uyarıyı bir "hata" gibi görüp otomatik temizleyen alias yazmak. Bazı ekipler ssh-keygen -R çağıran bir sarmalayıcı betik kurar. O andan sonra sistem, gerçek bir dinleme girişimini de sessizce kabul eder — yani güvenlik özelliğini tamamen kaldırmış olursunuz.
Bağlantı sorunlarında yaşanan diğer yaygın hata olan kullanıcı anahtarı reddi ile bu uyarıyı da karıştırmayın; onun çözümü tamamen farklıdır ve SSH permission denied publickey hatası yazısında ele alınmıştır.
Sıkça Sorulan Sorular#
Bu uyarı her zaman saldırı anlamına mı geliyor?#
Hayır, vakaların büyük çoğunluğu masumdur. Sunucunun yeniden kurulması, snapshot'tan geri dönülmesi, IP adresinin başka bir makineye devredilmesi veya DNS kaydının yeni bir sunucuya yönlendirilmesi aynı uyarıyı üretir. SSH bu meşru durumlarla gerçek bir dinleme girişimini ayırt edemediği için ikisine de aynı alarmı verir. Kararı verecek olan sizsiniz; bu yüzden parmak izini sunucudan doğrulamak tek doğru yöntemdir.
ssh-keygen -R komutunu çalıştırmam güvenli mi?#
Değişikliğin neden olduğunu bildiğiniz veya parmak izini sunucudan doğruladığınız sürece güvenlidir; komut yalnızca eski kaydı siler ve dosyanın bir yedeğini known_hosts.old adıyla bırakır. Ancak sebebi bilmeden çalıştırırsanız, bağlantınızı dinleyen birinin anahtarını kalıcı olarak güvenilir listeye eklemiş olursunuz. Önce doğrulayın, sonra silin.
Parmak izini sunucuya bağlanmadan nasıl öğrenirim?#
Sağlayıcınızın panelindeki VNC veya KVM konsolunu kullanın; bu bağlantı SSH'tan tamamen bağımsız bir kanaldır. Konsolda ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub komutunu çalıştırıp çıkan SHA256 değerini hata mesajındakiyle karşılaştırın. Kurulum sırasında parmak izlerini not aldıysanız veya otomasyon aracınızın çıktısında saklıyorsanız o kayıtlar da geçerli bir referanstır.
Sunucuyu yeniden kurmadan önce ne yapmalıydım?#
/etc/ssh/ssh_host_* dosyalarını yedekleyip kurulumdan sonra aynı yere geri koymalıydınız. Böylece sunucunun kimliği değişmez ve hiçbir kullanıcı uyarı almaz. Geri yüklerken özel anahtarların izinlerini 600, sahipliğini root olarak ayarlamayı ve sshd servisini yeniden başlatmayı unutmayın; izinler fazla açık kalırsa SSH sunucusu hiç başlamaz.
known_hosts dosyamdaki satırlar okunamıyor, sunucu adını göremiyorum?#
HashKnownHosts yes ayarı etkin demektir; bu ayar sunucu adlarını karma hâlde saklar, böylece bilgisayarınız ele geçirilse bile saldırgan hangi sistemlere eriştiğinizi listeleyemez. Kayıt aramak için ssh-keygen -F sunucuadi, silmek için ssh-keygen -R sunucuadi komutlarını kullanın; her ikisi de karma kayıtları doğru şekilde bulur.
Otomasyon betiğimde bu uyarı işi durduruyor, nasıl çözerim?#
StrictHostKeyChecking=no ve UserKnownHostsFile=/dev/null ikilisini kullanmayın; bu, betiğinizin kimliği doğrulanmamış herhangi bir sunucuya kimlik bilgilerinizi teslim etmesine yol açar. Bunun yerine sunucu anahtarlarını önceden bilinen bir known_hosts dosyasına yazıp betiğe bu dosyayı gösterin, ya da SSH sertifika otoritesi kurun. Geçici çözüm gerekiyorsa StrictHostKeyChecking=accept-new kullanın: yeni sunucuları kabul eder ama değişmiş anahtarda yine durur.