SSH「Host key verification failed」エラーの原因と対処法|安全な解決方法
- 作成日 2026.06.18
- linux
リモートサーバーにSSH接続しようとして、突然以下のような警告が表示されて驚いた経験はありませんか?
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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:xxxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /home/user/.ssh/known_hosts:5
Host key verification failed.
「中間者攻撃の可能性があります」という赤い警告が出るため、ネット記事に書いてある通り ssh-keygen -R で削除して何も考えずに対処してしまう方が多いのではないでしょうか。
しかし、このエラーは本来SSHのセキュリティ機能の正常動作で、原因によっては実際にMITM攻撃を受けている可能性もあります。「警告が出たら言われた通り削除する」習慣は危険です。
- 警告が出たがどう対処すべきか分からない
- ssh-keygen -R で消すのは安全か不安
- Docker/Vagrant再起動のたびに警告が出る
- EC2で再起動したら接続できなくなった
- Git pushで突然このエラーが出る
- CI/CDパイプラインで自動接続が止まった
本記事では、「Host key verification failed」エラーのすべての原因と対処法を、セキュリティ視点と実用性の両面から整理します。仕組みの理解、安全な対処手順、Docker/Vagrant/クラウド環境別の対処、CI/CD対応、再発防止策まで完全網羅。この1本で「ホスト鍵検証エラー」と適切に付き合えるようになります。
- 1. 結論:今すぐ試すべき3ステップ
- 2. まず押さえる:ホスト鍵検証の仕組み
- 3. エラーが出る原因カテゴリ
- 4. 【原因①】サーバー再構築・再インストール
- 5. 【原因②】IPアドレスの再利用
- 6. 【原因③】Docker・Vagrant・VM環境
- 7. 【原因④】クラウドVMの再起動・IP変更
- 8. 【原因⑤】サーバー側のホスト鍵変更・アルゴリズム更新
- 9. 【原因⑥】実際のMITM攻撃の可能性(要注意)
- 10. known_hostsファイルを直接編集する
- 11. StrictHostKeyChecking 設定の使い分け
- 12. Windows環境での対処
- 13. Git経由のSSH接続でのエラー
- 14. CI/CD パイプラインでの対処
- 15. プログラム言語からのSSH接続
- 16. セキュリティベストプラクティス
- 17. トラブルシューティング・チェックリスト
- 18. よくある質問(FAQ)
- 18.1. Q1. 警告を毎回 ssh-keygen -R で消すのは安全ですか?
- 18.2. Q2. known_hosts ファイルを丸ごと削除しても大丈夫?
- 18.3. Q3. StrictHostKeyChecking=no を常用するのは危険ですか?
- 18.4. Q4. accept-new と no の違いは?
- 18.5. Q5. Docker再起動のたびにエラーが出るのを止めたいです
- 18.6. Q6. GitHubに突然繋がらなくなりました
- 18.7. Q7. WindowsとWSLでknown_hostsを共有したいです
- 18.8. Q8. ssh-keygen -R が動きません
- 18.9. Q9. CI/CDで毎回 known_hosts を作る運用は安全?
- 18.10. Q10. 同じIPに何度も別サーバーが割り当てられて困ります
- 18.11. Q11. PuTTY と OpenSSH で別々に管理されて面倒です
- 18.12. Q12. fingerprint の表示形式が違って比較できません
- 19. 参考リンク・関連資料
- 20. まとめ
結論:今すぐ試すべき3ステップ
時間がない方向けに、安全な手順を示します。
ステップ1:状況を確認(重要)
警告メッセージから以下を読み取ります:
- どのホストでエラーが出たか
- known_hosts の何行目が問題か
- 新しいホスト鍵のフィンガープリント
Offending ED25519 key in /home/user/.ssh/known_hosts:5
→ ~/.ssh/known_hosts の5行目が問題。
ステップ2:心当たりの確認
このサーバー、最近自分または管理者が以下のいずれかをしましたか?
- サーバー再構築・OS再インストール
- クラウドインスタンス再作成
- Dockerコンテナ削除→再起動
- IPアドレス変更・再割り当て
✅ 心当たりがある場合 → ステップ3へ ⚠️ 心当たりが全くない場合 → MITM攻撃の可能性。サーバー管理者に連絡し、別経路でフィンガープリントを確認してから対処
ステップ3:古いホスト鍵を削除
# ホスト名指定で削除
ssh-keygen -R hostname.example.com
# IPアドレス指定で削除
ssh-keygen -R 192.168.1.100
# ポート指定の場合
ssh-keygen -R '[hostname.example.com]:2222'
これでknown_hostsから該当エントリが削除され、次回SSH接続時に新しいホスト鍵を登録できます。
まず押さえる:ホスト鍵検証の仕組み
このエラーを理解するには、SSHのホスト鍵検証の仕組みを知る必要があります。
SSH接続の流れ
- クライアントがサーバーに接続要求
- サーバーが自身のホスト公開鍵を送信
- クライアントが
~/.ssh/known_hostsから該当ホストの鍵を検索 - 記録された鍵と一致 → 接続を継続
- 未登録ホスト → ユーザーに確認後、known_hostsに追加
- 登録された鍵と異なる → 「Host key verification failed」を出してブロック
なぜホスト鍵検証が必要か
中間者(MITM)攻撃を防ぐためです。
[クライアント] ←→ [攻撃者がなりすまし] ←→ [本物のサーバー]
↑
通信を盗聴・改ざんできる
攻撃者が「サーバー」を装ってクライアントと通信した場合、攻撃者のホスト鍵が送られてきます。これを「初回登録時の鍵」と照合することで、なりすましを検出できます。
つまり、「Host key verification failed」は SSHが正しく仕事をしている証でもあります。
エラーが出る原因カテゴリ
| カテゴリ | 例 | 頻度 | 危険度 |
|---|---|---|---|
| サーバー再構築系 | OS再インストール、Docker再作成 | 多 | 低(自分の操作なら安全) |
| IP/ホスト名再利用系 | 同じIPに別サーバー、DHCPで他人のIP割当 | 中 | 中 |
| 開発環境特有系 | Vagrant、Docker、VirtualBox | 多 | 低 |
| クラウド特有系 | EC2インスタンス停止→起動でIP変動 | 多 | 低 |
| アルゴリズム変更系 | サーバー設定変更、OpenSSHバージョンアップ | 少 | 低 |
| MITM攻撃系 | 実際の攻撃 | 稀 | 極高 |
順番に切り分けます。
【原因①】サーバー再構築・再インストール
最も多いケースです。
発生パターン
- 同じホスト名・IPでOS再インストール
- VPSで OS 入れ替え
- Dockerコンテナを
docker rmしてからdocker runで再作成 - Vagrantで
vagrant destroy → vagrant up - AMI更新でEC2再構築
サーバー側のホスト鍵は再構築時に新しく生成されるため、古いknown_hostsの記録と一致しなくなります。
対処
自分が再構築したなら安全なので、古いエントリを削除します。
# ホスト名で削除
ssh-keygen -R hostname.example.com
# IPアドレスで削除
ssh-keygen -R 192.168.1.100
# 削除確認(known_hostsを表示)
cat ~/.ssh/known_hosts | grep hostname
削除後、再度SSH接続すると新しいホスト鍵の登録確認が出ます:
The authenticity of host 'hostname.example.com (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
yes を入力すると新しい鍵が登録されます。
【原因②】IPアドレスの再利用
「前は別のサーバーに割り当てられていたIPが、別のサーバーに再割り当て」されたケースです。
発生パターン
- DHCPで割り当てられたIPが、別マシンに割り当て直された
- クラウドの動的IPプール
- 社内ネットワークの端末入れ替え
- 公衆Wi-Fiで他人と同じIPを使用
対処
新しいサーバーが信頼できるなら、原因①と同じく削除して再登録:
ssh-keygen -R 192.168.1.100
ssh-keygen -R hostname.example.com # ホスト名も登録されていれば
⚠️ ただし、同じホスト名で予期せず別のマシンに繋がっている場合、業務上の重要データを誤って別マシンに送るリスクがあります。心当たりがない場合は、ホスト名・IP・到達先を確認してから対処してください。
【原因③】Docker・Vagrant・VM環境
開発環境で最頻発するパターンです。
Dockerでの典型ケース
# コンテナ初回起動
docker run -d -p 2222:22 --name myssh ssh-server-image
# SSH接続OK
ssh -p 2222 user@localhost
# コンテナ削除→再作成
docker rm -f myssh
docker run -d -p 2222:22 --name myssh ssh-server-image
# SSH接続するとエラー!
ssh -p 2222 user@localhost
# → Host key verification failed
新コンテナは別のホスト鍵を生成するため、警告が出ます。
対処:ポート番号込みで削除
ssh-keygen -R '[localhost]:2222'
⚠️ ポート指定の場合、ホスト名は [hostname]:port のように角括弧付き形式です。
Docker環境の根本対処
毎回エラーが出るのを避けるには、SSH設定で警告を抑制:
# ~/.ssh/config
Host docker-dev
HostName localhost
Port 2222
User root
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR
これでssh docker-dev接続時に警告が出ず、known_hostsにも記録されません。
⚠️ 本番サーバーには絶対に設定しないこと。開発環境(localhost、Docker、VM)限定で使ってください。
Vagrantでの対処
Vagrantはvagrant sshコマンドが内部でホスト鍵検証を回避する設定を生成するため、Vagrant経由なら問題ありません。直接sshで繋ぐ場合は上記のSSH config設定を行ってください。
【原因④】クラウドVMの再起動・IP変更
AWS EC2やGCEで頻発します。
EC2でのよくあるパターン
- インスタンスを停止 → 起動でパブリックIPが変動
- 同じパブリックIPが他インスタンスに再割り当て
対処
ssh-keygen -R ec2-xx-xx-xx-xx.compute.amazonaws.com
ssh-keygen -R xx.xx.xx.xx
根本対処:Elastic IP / 静的IP の利用
クラウドの固定IP機能を使うと、再起動でIPが変わらず、ホスト鍵問題も発生しにくくなります。
- AWS: Elastic IP
- GCP: Static external IP
- Azure: Static Public IP
ただし固定IPでも、インスタンス再構築時にはホスト鍵が変わるので注意。
EC2のホスト鍵をコンソールから確認
EC2の場合、システムログにホスト鍵フィンガープリントが出力されます:
aws ec2 get-console-output --instance-id i-xxxxxxxxx | grep -A 5 "BEGIN SSH HOST KEY"
または管理コンソールから「アクション → モニタリングおよびトラブルシューティング → システムログを取得」。
ここで表示されるフィンガープリントと、SSH接続時に表示される値が一致すれば、なりすましではなく正しいサーバーに繋がっていることを確認できます。
【原因⑤】サーバー側のホスト鍵変更・アルゴリズム更新
たまにあるケースです。
発生例
- 古いホスト鍵(RSA 1024bit等)がセキュリティ要件で更新された
- 管理者がホスト鍵を手動で再生成
- OpenSSH のバージョンアップで使用アルゴリズムが変更
対処
サーバー管理者から「ホスト鍵を更新した」連絡があれば、新しいフィンガープリントを確認した上で削除・再登録:
ssh-keygen -R hostname.example.com
ssh hostname.example.com
# 接続時、新しいフィンガープリントが管理者から伝えられた値と一致することを確認
【原因⑥】実際のMITM攻撃の可能性(要注意)
最後に、本当に攻撃を受けているケースもあり得ます。確率は低いですが、無視できない可能性です。
注意すべきシナリオ
- 公衆Wi-Fi・カフェ・空港等の信頼できないネットワーク
- 管理者から再構築の連絡が無いのにエラーが出る
- 同じネットワークの別端末では問題なく接続できる
- フィンガープリントが毎回違う値になる
安全に判別する方法
1. 別経路でフィンガープリントを確認
サーバー管理者にSSH以外の手段(電話、社内チャット、メール等)で:
「現在のホスト鍵フィンガープリントを教えてください」
と問い合わせ、それと一致することを確認。
2. サーバーに直接ログインして確認
別の経路(コンソール、別の信頼できるネットワーク)でログインし、ホスト鍵フィンガープリントを取得:
# サーバー上で全ホスト鍵のフィンガープリント表示
for key in /etc/ssh/ssh_host_*_key.pub; do
ssh-keygen -lf "$key"
done
これで表示される値と、エラーで提示された値が一致するか確認。
3. クラウドのコンソールログから確認
AWS EC2、GCP等は、インスタンス起動時にホスト鍵をシステムログに出力します。別経由でログを取得して確認。
一致しない場合
実際の攻撃の可能性があります。対応:
- 当該ネットワークでの作業を中止
- セキュリティチーム・管理者にエスカレート
- パスワード等の機密情報を入力していないか確認・変更
known_hostsファイルを直接編集する
ssh-keygen -R以外の方法として、~/.ssh/known_hostsを直接編集することもできます。
ファイルの場所
# Linux/Mac
~/.ssh/known_hosts
# Windows (OpenSSH)
%USERPROFILE%\.ssh\known_hosts
ファイル内容の例
hostname.example.com,192.168.1.100 ssh-rsa AAAAB3NzaC1yc2EAAAAB...
[localhost]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlz...
|1|xxxxx|yyyyy ssh-ed25519 AAAAC3NzaC1lZDI1NTE5...
最後の|1|xxxxx|yyyyyはホスト名がハッシュ化されたエントリです(後述のHashKnownHosts機能)。
特定行を削除する例
# 5行目を削除(警告メッセージの:5 から特定)
sed -i.bak '5d' ~/.ssh/known_hosts
# Macの場合
sed -i '' '5d' ~/.ssh/known_hosts
全エントリ確認
# 平文ホスト名のエントリを確認
cat ~/.ssh/known_hosts | awk '{print $1}'
# ハッシュ化エントリが含まれる場合
ssh-keygen -H -f ~/.ssh/known_hosts # 既存をハッシュ化
ssh-keygen -F hostname # 検索(ハッシュ化エントリも見つかる)
バックアップを忘れずに
cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak
編集ミスでファイルが壊れると、全SSH接続で再登録が必要になります。
StrictHostKeyChecking 設定の使い分け
SSH の動作を細かく制御できる設定です。
設定値と挙動
| 値 | 動作 |
|---|---|
yes | 既知ホストのみ接続。未知ホストは拒否 |
accept-new | 未知ホストは自動登録、既知ホストの変更は拒否(推奨) |
no または false | 警告を表示するが接続は続行(既知ホストの変更も) |
off または ask(デフォルト) | 未知ホストは確認、変更は拒否 |
コマンドラインでの一時指定
# 一時的に警告を無視(信頼できる開発環境のみ)
ssh -o StrictHostKeyChecking=no user@host
# known_hostsを書き換えない
ssh -o UserKnownHostsFile=/dev/null user@host
# 両方を組み合わせて完全に無視
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@host
~/.ssh/config での恒久設定
# 全体的なデフォルト
Host *
StrictHostKeyChecking accept-new
# 開発環境のみ無効化
Host dev-* docker-* vagrant-*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR
# 本番サーバーは厳格に
Host *.production.example.com
StrictHostKeyChecking yes
accept-new が推奨される理由
OpenSSH 7.6(2017年)で導入された値です:
- 初回接続時: 自動的に登録(プロンプト不要)
- 2回目以降: 鍵が変わっていれば拒否
「初回登録の手間を減らしつつ、変更検知は確実に行う」というバランスの良い設定です。
Windows環境での対処
Windows標準のOpenSSH(Win10 1809以降)
Windows 10/11には標準でOpenSSHクライアントが入っています。
ssh user@host
対処は基本的にLinux/Macと同じ:
ssh-keygen -R hostname
known_hostsの場所: C:\Users\<username>\.ssh\known_hosts
PowerShellでの操作
# known_hosts内容確認
Get-Content ~/.ssh/known_hosts
# 特定ホストの削除
ssh-keygen -R hostname
# known_hosts丸ごとリセット
Remove-Item ~/.ssh/known_hosts
WSL/WSL2のSSH
WSLはLinux環境なのでLinuxと同じ手順:
ssh-keygen -R hostname
注意点として、WindowsホストのknownとWSL内のknownは別ファイルです。両方で問題が起きていないか確認してください。
PuTTY
PuTTYはOpenSSHと別のキャッシュを使います:
- レジストリエディタで以下を開く:
HKEY_CURRENT_USER\SOFTWARE\SimonTatham\PuTTY\SshHostKeys - 該当エントリを削除
- または、PuTTYで接続を試みた時に表示される「鍵の更新」確認に応答
Git for Windows
Git付属のbashも独自のknown_hostsを持つことがあります:
# Git Bash内で
ls ~/.ssh/
# 標準OpenSSHと同じ場所
Git経由のSSH接続でのエラー
GitHubやGitLabへのGit操作時に発生するケースです。
典型的なエラー
$ git push
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
...
Host key verification failed.
fatal: Could not read from remote repository.
GitHubの場合
GitHubは2023年3月にRSAホスト鍵をローテーションしました。古いknown_hostsのまま新規接続するとこのエラーが出る場合があります。
# 古い鍵を削除
ssh-keygen -R github.com
# 公式の新ホスト鍵を確認・追加
# 公式ドキュメント: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints
ssh-keyscan github.com >> ~/.ssh/known_hosts
# 接続テスト
ssh -T git@github.com
ssh-keyscan の利用
ホスト鍵を自動取得する便利なコマンド:
# 単一ホスト
ssh-keyscan github.com >> ~/.ssh/known_hosts
# 複数ホスト
ssh-keyscan github.com gitlab.com bitbucket.org >> ~/.ssh/known_hosts
# 特定鍵タイプのみ
ssh-keyscan -t ed25519,rsa github.com >> ~/.ssh/known_hosts
⚠️ ssh-keyscanはネットワーク経由で鍵を取得するため、MITM下で実行するとブロックされた鍵が記録されてしまいます。公式ドキュメントのフィンガープリントと照合してから使うのが安全です。
GitHubの公式フィンガープリント
GitHubは公式に以下のフィンガープリント値を公開しています:
- ED25519:
SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU - RSA:
SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s - ECDSA:
SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM
接続時に表示される値と一致するか確認してください。
CI/CD パイプラインでの対処
自動化された環境では対話的な確認ができないため、特別な工夫が必要です。
GitHub Actions
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# ホスト鍵を事前登録
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
- name: Deploy
run: ssh user@${{ secrets.SSH_HOST }} 'deploy-command.sh'
GitLab CI
deploy:
before_script:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
script:
- ssh user@$SSH_HOST 'deploy-command.sh'
Jenkins
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sshagent(credentials: ['ssh-key']) {
sh '''
mkdir -p ~/.ssh
ssh-keyscan -H ${SSH_HOST} >> ~/.ssh/known_hosts
ssh user@${SSH_HOST} 'deploy-command.sh'
'''
}
}
}
}
}
CI/CDでのセキュリティ考慮
ssh-keyscanは便利だが、MITM対策にはならない- 理想は信頼できるホスト鍵を事前登録し、
StrictHostKeyChecking=yesで運用 - Secretsに期待されるホスト鍵フィンガープリントを保存し、起動時に検証
# 期待される鍵と一致するか検証
EXPECTED_KEY="ssh-ed25519 AAAA..."
ACTUAL_KEY=$(ssh-keyscan -t ed25519 $SSH_HOST 2>/dev/null | awk '{$1=""; print $0}' | xargs)
if [ "$ACTUAL_KEY" != "$EXPECTED_KEY" ]; then
echo "Host key mismatch!"
exit 1
fi
プログラム言語からのSSH接続
ライブラリ経由でも同様の問題が発生します。
Python(paramiko)
import paramiko
# ❌ 危険:全ホスト鍵を無条件で受け入れる
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('hostname', username='user')
# ✅ 推奨:システムのknown_hostsを利用
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.RejectPolicy()) # 未知ホストは拒否
client.connect('hostname', username='user')
Python(fabric)
from fabric import Connection
# known_hostsを使う標準的な方法
conn = Connection('user@hostname')
conn.run('uname -a')
# 開発環境用:known_hosts無視
conn = Connection('user@hostname', connect_kwargs={
'host_key_policy': 'AutoAddPolicy' # 注意:本番非推奨
})
Node.js(ssh2)
const { Client } = require('ssh2');
const conn = new Client();
conn.connect({
host: 'hostname',
username: 'user',
privateKey: require('fs').readFileSync('/path/to/key'),
// ホスト鍵検証コールバック
hostVerifier: (hashedKey, callback) => {
const expectedKey = 'SHA256:xxxxxxx'; // 事前登録した値
callback(hashedKey === expectedKey);
}
});
Go(golang.org/x/crypto/ssh)
package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/knownhosts"
)
func main() {
// known_hostsを利用
hostKeyCallback, err := knownhosts.New(os.ExpandEnv("$HOME/.ssh/known_hosts"))
if err != nil { panic(err) }
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
ssh.Password("password"),
},
HostKeyCallback: hostKeyCallback,
}
client, err := ssh.Dial("tcp", "hostname:22", config)
if err != nil { panic(err) }
defer client.Close()
fmt.Println("Connected!")
}
セキュリティベストプラクティス
ホスト鍵運用のお勧め設定を整理します。
1. StrictHostKeyChecking=accept-new を採用
Host *
StrictHostKeyChecking accept-new
未知ホストは自動登録、既知ホストの変更は拒否。バランスの良い設定です。
2. HashKnownHosts で記録をハッシュ化
Host *
HashKnownHosts yes
known_hosts内のホスト名がハッシュ化され、ファイル流出時のリスク軽減になります。
3. 警告を真剣に扱う
何度警告が出ても「とりあえず削除」する習慣を改めましょう。原因の心当たりを毎回確認するクセを付けると、本物のMITM検出につながります。
4. 重要サーバーのフィンガープリントを記録
業務で頻繁に接続するサーバーは、初回接続時にフィンガープリントを別途記録しておきます。Slack/Notion等のチームナレッジに残すと共有しやすいです。
5. SSHFP DNSレコードの活用(上級)
DNSにホスト鍵を登録する仕組みです。設定済みなら自動的にホスト鍵を検証できます:
ssh -o VerifyHostKeyDNS=yes user@host
DNSSEC との併用が前提となります。
6. Certificate Authority(CA)方式
大規模環境では、ホスト鍵にCA署名を使う方式が推奨されます。CAの公開鍵さえあれば、新規ホストの鍵を毎回登録する必要がなくなります。
# CA公開鍵を信頼する
echo '@cert-authority *.example.com ssh-ed25519 AAAA...' >> ~/.ssh/known_hosts
トラブルシューティング・チェックリスト
エラーが出た時の手順整理:
- エラー全文を読む: ホスト名・known_hostsの行番号を確認
- 心当たりを確認: 自分または管理者がサーバー変更したか
- 心当たりがある場合:
ssh-keygen -Rで削除→再接続 - 心当たりがない場合: 別経路でフィンガープリント確認
- 公衆Wi-Fi等: 接続停止、信頼できるネットワークで再試行
- Docker/Vagrant: SSH config で StrictHostKeyChecking=no(開発のみ)
- CI/CD: ssh-keyscanで事前登録、もしくは固定値検証
- GitHub/GitLab: 公式フィンガープリントと照合
- 再発防止: accept-new 設定への移行
- 本物の攻撃の可能性: セキュリティチームへ報告
よくある質問(FAQ)
Q1. 警告を毎回 ssh-keygen -R で消すのは安全ですか?
サーバーの再構築や Docker/Vagrant 等、自分が変更した心当たりがあれば安全です。心当たりが全くない時は、MITM攻撃の可能性も考慮し、別経路で確認してから対処してください。
Q2. known_hosts ファイルを丸ごと削除しても大丈夫?
技術的には可能ですが、全SSH接続で初回登録ダイアログが出るため不便です。問題のあるエントリだけssh-keygen -Rで削除する方が現実的です。
# 不便を承知でリセット
mv ~/.ssh/known_hosts ~/.ssh/known_hosts.bak
Q3. StrictHostKeyChecking=no を常用するのは危険ですか?
本番接続では危険です。MITM攻撃を完全に無視することになります。開発環境(localhost、Docker、Vagrant等)に限定して使用してください。
Q4. accept-new と no の違いは?
| 設定 | 既知ホストの鍵変更時 | 未知ホスト |
|---|---|---|
no | 警告のみ・接続続行 | 確認なしで接続 |
accept-new | エラーで拒否 | 自動登録 |
accept-new は変更検知をきちんと行うため、セキュリティ的に大幅に優れています。
Q5. Docker再起動のたびにエラーが出るのを止めたいです
~/.ssh/config で開発環境を分離:
Host docker-* localhost-*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR
ホスト名規約(docker-myapp等)を決めて運用します。
Q6. GitHubに突然繋がらなくなりました
2023年3月のGitHubホスト鍵ローテーションが原因の可能性。古いエントリを削除して再登録:
ssh-keygen -R github.com
ssh-keyscan github.com >> ~/.ssh/known_hosts
ssh -T git@github.com
接続時のフィンガープリントがGitHub公式値と一致するか必ず確認。
Q7. WindowsとWSLでknown_hostsを共有したいです
WSL内からシンボリックリンクを作成:
# WSL内で
rm -rf ~/.ssh
ln -s /mnt/c/Users/<username>/.ssh ~/.ssh
ただしパーミッション周りで問題が出ることがあるので慎重に。
Q8. ssh-keygen -R が動きません
考えられる原因:
- known_hosts ファイルがない
- 削除対象のホスト名が間違っている(ポート指定形式を含む)
- ハッシュ化されたエントリで通常のホスト名指定では見つからない
# ハッシュ化エントリも検索
ssh-keygen -F hostname
ssh-keygen -R hostname # ハッシュ化エントリも削除される
Q9. CI/CDで毎回 known_hosts を作る運用は安全?
ssh-keyscan単独ではMITM対策にならないため、理想的には:
- 期待される鍵フィンガープリントをCIシークレットに保存
ssh-keyscan取得結果と比較- 一致しなければ即座にビルド失敗
これで自動化と安全性を両立できます。
Q10. 同じIPに何度も別サーバーが割り当てられて困ります
クラウドならElastic IP / Static IPを使うのが基本。動的IPプール環境では、ホスト名ベースで接続するように工夫:
# ホスト名を使う(known_hostsエントリも別になる)
ssh user@server-prod.example.com # 別ホストと混同しにくい
Q11. PuTTY と OpenSSH で別々に管理されて面倒です
両ツールはホスト鍵ストアが別物です。完全統一は難しいですが、PuTTYからOpenSSH形式にエクスポートしてからインポートする方法があります。または PuTTY をやめて Windows標準のOpenSSHに統一するのもひとつの解。
Q12. fingerprint の表示形式が違って比較できません
OpenSSH では SHA256(Base64)が標準ですが、古い形式(MD5、16進)の場合もあります:
# SHA256形式で表示
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
# MD5形式で表示(古い形式)
ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub
接続時の表示形式と合わせて確認してください。
参考リンク・関連資料
SSH公式・標準
- OpenSSH 公式サイト – OpenSSHプロジェクト
- ssh(1) manページ – ssh コマンド公式
- ssh-keygen(1) manページ – ssh-keygen 公式
- sshd_config(5) manページ – SSHサーバー設定
- ssh_config(5) manページ – SSHクライアント設定
Git ホスティング
Windows関連
クラウド関連
セキュリティ基礎
関連記事(本サイト)
- 「Address already in use」エラーの対処法 – ポート競合エラー
- UbuntuでIPアドレスを確認する全方法 – ネットワーク確認
- wget と curl の違いを徹底比較 – HTTP通信ツール
- ORA-12541: TNS no listener エラー対処 – リスナー接続エラー
まとめ
「Host key verification failed」はSSHのセキュリティ機能の正常動作ですが、原因によって対処の安全性が大きく変わります。要点を再整理します。
- エラーの本質: ホスト鍵が
known_hostsの記録と一致しない → MITM攻撃の可能性を警告 - 3ステップ判断: 状況確認 → 心当たり確認 → 削除・再登録
- 心当たりがある場合:
ssh-keygen -Rで削除して安全に対処 - 心当たりがない場合: 別経路でフィンガープリント確認、攻撃の可能性も考慮
- Docker/Vagrant: 開発環境専用にSSH config で警告抑制
- クラウド: 静的IP・コンソールログでのフィンガープリント確認を活用
- CI/CD:
ssh-keyscan+フィンガープリント検証で安全に自動化 - ベストプラクティス:
StrictHostKeyChecking=accept-newへの移行を推奨
これらの知識は、リモート開発・サーバー運用・CI/CD構築などのあらゆる場面で必須です。本記事をブックマークしておけば、SSH警告が出た時に安全かつ迅速に対応できるようになります。
本記事は2026年6月時点の情報をもとに、OpenSSH 9.x、Ubuntu 22.04/24.04、macOS Sonoma/Sequoia、Windows 11 での動作確認に基づき作成しています。OS・バージョンによって挙動が異なる場合があるため、ご利用の環境に応じてご確認ください。
-
前の記事
Docker「no space left on device」エラーの原因と対処法|容量不足を解消 2026.06.17
-
次の記事
【完全リファレンス】Linux grepコマンドのオプション一覧と使い方|実用例80超で徹底解説 2026.06.18
コメントを書く