できない.dev

SSH で「Host key verification failed」が出て接続できない

接続先が提示したホスト鍵が known_hosts の記録と一致しないか、記録自体が無いときに出る。
サーバーを作り直したのか中間者攻撃なのかを鍵指紋で確かめてから、古い記録を消して入れ直す。

公開: 更新:

実行例あり(2026-09-27 に実環境で検証)

要約

Host key verification failed. は、接続先が示したホスト鍵が ~/.ssh/known_hosts の記録と食い違ったときに出る。ssh(1)(新しいタブで開く) が説明するとおり、SSH は初回接続で相手の公開鍵を記録し、2 回目以降は毎回それと照合する。
食い違いは「相手が入れ替わった」という警告なので、鍵を消す前に理由を確かめる。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Offending ECDSA key in /home/me/.ssh/known_hosts:12
Host key verification failed.

多くの場合はサーバーの作り直しが理由である。
ただし「多くの場合」で片付けると中間者攻撃を見逃すため、指紋の照合を挟む。

実行例

alpine:3 のコンテナに sshd を立て、ホスト鍵を known_hosts に記録して一度つないだあとで鍵を作り直すと、同じ ssh -p 2222 deploy@127.0.0.1 whoami が REMOTE HOST IDENTIFICATION HAS CHANGED! の警告と Host key verification failed.(終了コード 255)で止まった。ssh-keyscan で取った指紋とサーバー側の ssh_host_ed25519_key.pub の指紋が一致するのを確かめ、ssh-keygen -R で古い行を消してから StrictHostKeyChecking=accept-new で受け入れると deploy が返り、known_hosts に入った指紋も同じ値になっている。

$ ssh-keyscan -p 2222 -t ed25519 127.0.0.1 >> ~/.ssh/known_hosts
$ ssh -p 2222 deploy@127.0.0.1 whoami
deploy
$ echo $?
0
$ ssh -p 2222 deploy@127.0.0.1 whoami
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    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:SHMOBdzubZ1quVkQRwzE2NxGQLAOfMCQGEL1iCs/Nq0.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /root/.ssh/known_hosts:2
Host key for [127.0.0.1]:2222 has changed and you have requested strict checking.
Host key verification failed.
$ echo $?
255
$ ssh-keyscan -p 2222 -t ed25519 127.0.0.1 | ssh-keygen -lf -
256 SHA256:SHMOBdzubZ1quVkQRwzE2NxGQLAOfMCQGEL1iCs/Nq0 [127.0.0.1]:2222 (ED25519)
$ ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:SHMOBdzubZ1quVkQRwzE2NxGQLAOfMCQGEL1iCs/Nq0 root@27fdc441f0a7 (ED25519)
$ ssh-keygen -R '[127.0.0.1]:2222'
# Host [127.0.0.1]:2222 found: line 2
/root/.ssh/known_hosts updated.
Original contents retained as /root/.ssh/known_hosts.old
$ ssh -o StrictHostKeyChecking=accept-new -p 2222 deploy@127.0.0.1 whoami
Warning: Permanently added '[127.0.0.1]:2222' (ED25519) to the list of known hosts.
deploy
$ echo $?
0
$ ssh-keygen -lf ~/.ssh/known_hosts
256 SHA256:SHMOBdzubZ1quVkQRwzE2NxGQLAOfMCQGEL1iCs/Nq0 [127.0.0.1]:2222 (ED25519)

— 2026-09-27 時点の出力

検証環境

検証日
実行環境
alpine:3 Alpine Linux v3.24

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. サーバーを作り直した: OS の再インストールや、クラウドのインスタンス再作成でホスト鍵が生成し直されている。
    移行時に /etc/ssh/ssh_host_* を引き継がなければ必ず変わる。
  2. IP が再利用された: known_hosts はホスト名だけでなく IP でも記録される。
    クラウドでは同じ IP が別の利用者に回るため、名前は違っても IP の行が衝突する。
  3. 接続先が実は別のホスト: 踏み台やポートフォワードの設定を変えると、localhost:2222 のような同じ宛先で違うサーバーに繋がる。
  4. 記録が無いまま非対話で実行: CI では確認プロンプトに答えられない。StrictHostKeyChecking が yes 相当なら、未知のホストというだけで失敗する。
  5. known_hosts の破損: 手で編集して行が折り返された、あるいはファイルが読み取り専用になっている場合も一致に失敗する。

解決策

1. 相手の指紋を先に確認する

ssh-keyscan -t ed25519 example.com | ssh-keygen -lf -

サーバー側にログインできるなら、そこで同じ値を出して突き合わせる。

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

一致すれば正当な変更である。
一致しない、あるいは確認手段が無いなら、その接続は行わない。

2. 古い記録を削除する

ssh-keygen -R example.com
ssh-keygen -R 203.0.113.10

ssh-keygen(1)(新しいタブで開く) の -R はホスト名がハッシュ化されていても該当行を消せる。
ホスト名と IP の両方を消しておくと再発しにくい。
削除後にもう一度接続し、表示された指紋が手順 1 の値と同じことを確認してから受け入れる。

3. CI では事前に登録する

mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keyscan -t ed25519 github.com >> ~/.ssh/known_hosts

ssh-keyscan の結果をそのまま信用するのは初回だけなので、GitHub のように指紋が公開されているサービスでは、取得した値を提供元のドキュメントと照合してから固定する。
以後は取得ではなくリポジトリに保存した値を使う。

4. 一時回避は範囲を限定する

ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@example.com

このオプションは照合そのものを捨てるため、恒久的な設定ファイルには書かない。
使い捨ての検証環境に限る。

この記事は役立ちましたか?