みなさんはsshコマンドを使ってサーバに接続しようとした際にssh_exchange_identification: connection closed by remote hostというエラーが表示された経験はないでしょうか。
今回はそのエラーが発生する大まかな原因とそれ毎の対処方法について述べていきたいと思います。
以下、接続元となるPCないしはサーバをローカル、sshで接続したい先のサーバのことをリモートと呼びます。
ssh_exchange_identificationとは何か
接続先が存在しない、またはセキュリティ違反によってリモートに接続できない場合に発生するエラーです。このエラーが発生しうる原因と対処について述べていきたいと思います。
ssh_exchange_identification: connection closed by remote hostの原因
リモートの情報が変更されてしまった場合
以下の様なメッセージが表示されている場合、リモートの情報とローカルに記録されたknown_hostsファイルの情報が異なっている可能性があります
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
known_hostsファイルとは何か
known_hostsファイルにはfingerprintと呼ばれる情報が記録されており、過去接続したことのあるサーバのIPアドレス、公開鍵、鍵の暗号方式が記録されています。
sshの際には単にリモートのホスト名だけではなく、これらの情報と合わせて識別を行っており、名前の通り指紋の役割として働いています。
何らかの理由により、fingerprintが異なる場合 REMOTE HOST IDENTIFICATION HAS CHANGED! というエラーが出るというわけです。
fingerprintが古い場合の対処
known_hostsに記録されたfingerprintが変わってしまう原因としては、サーバが再起動したことによってDHCPによりIPアドレスが変わったり、OS再インストールによって公開鍵が変わったりと様々です。
リモートの情報が変更された理由に心当たりがある場合は以下の2つの方法で対処が可能です。
原因に心当たりがない場合はなりすましの可能性があるので注意が必要です。
known_hostsに記録されたfingerprintを削除する
リモートが更新された原因に心当たりがあるなら直接fingerprintを削除してしまって問題ありません。
vim ~/.ssh/known_hosts
以下のsedコマンドを使って削除することも可能です
sed -i '/リモートのホスト名/d' ~/.ssh/known_hosts
警告を無視する
-o 'StrictHostKeyChecking no'オプションをつけることで無視することができます。shellやpythonなどのスクリプトから接続している際にはかなり有用ではありますが、万が一なりすましの場合セキュリティ上のリスクはあるので注意が必要です。
ssh -o 'StrictHostKeyChecking no' リモートのホスト名
リモートからアクセスが禁止されている場合
以上fingerprintが変更されている場合について説明いたしました。そのほかにもsshd(ローカルからのssh接続を受け持つデーモン)やdenyHostsというセキュリティツールで禁止されている可能性もあります。
接続先の/etc/hosts.denyにローカルのIPアドレスがないか確認が必要です。
vim /etc/hosts.deny # denyhostsの場合
systemctl restart denyhosts # sshdの場合
systemctl restart sshd
まとめ
今回はssh_exchange_identification: connection closed by remote hostのエラーとその原因・対処について紹介いたしました。
エラーの原因と対処
- リモートのfingerprintが変わったため:fingerprintを削除する
- リモートから拒絶されているため:リモートサーバの接続設定を見直す