SSH のエラーメッセージは意図的にそっけなく作られています。プロトコルは、見知らぬ相手に、なぜ 締め出したのかを教えません。それはセキュリティとしては良く、使い勝手としては悪いことです。目にするメッセージは、実際の問題から 2 段階ほど離れていることがよくあります。これは、実際に出会う 13 のエラーについての現場ガイドです。それぞれが本当は何を意味するのか、そして最短の直し方を扱います。
始める前に 1 つの道具を。ssh -v user@host です(-vvv まで増やせます。その出力の読み方(英語))。以下のほぼすべての謎は、ハンドシェイクのどの段階で死んでいるかが見えた瞬間に、謎でなくなります。
エラー早見表
| エラー | 意味 | まず試すこと |
|---|---|---|
Connection refused | ホストは応答した。そのポートで何も待ち受けていない | sshd が動いているか、呼んだポートで待ち受けているかを確認 |
Connection timed out | 経路上でパケットが消えた | クラウドのファイアウォール/セキュリティグループを確認 |
Permission denied (publickey) | 提示した鍵がどれも受け入れられなかった | ユーザー、次に鍵、次に authorized_keys を確認 |
Permission denied(プロンプトなし) | パスワード認証が無効。鍵でなければ通らない | 鍵を使うか、プロバイダーのコンソールから入る |
Host key verification failed | 信頼して以降、サーバーの鍵が変わった | 別経路で確認し、次に ssh-keygen -R |
Too many authentication failures | エージェントが鍵を提示しすぎた | -i と併せて -o IdentitiesOnly=yes |
UNPROTECTED PRIVATE KEY FILE | 鍵ファイルが他者から読める | 秘密鍵を chmod 600 |
Broken pipe | アイドル状態の接続が切られた | ServerAliveInterval を追加 |
no matching key exchange method | レガシーなサーバーと現代的なクライアント | そのホストだけ、アルゴリズムを 1 つ再有効化 |
Connection reset by peer | SSH の挨拶より前に TCP が閉じられた | fail2ban/MaxStartups を確認 |
Bad configuration option | 設定の 1 行に対してクライアントが古すぎる | ssh を更新するか、その行をガードする |
did not receive identification string | 何かが接続したがバナーを送らなかった | たいていはスキャナー。サーバー側では無視 |
Unspecified GSS failure | Kerberos の試行が失敗し、フォールバックした | ログインが成功しているなら無視 |
1. Connection refused
マシンには到達できていますが、あなたがノックしたポートで何も待ち受けていません。これは、ほぼあなたのせいではありません。
- sshd が動いていない。コンソールから
systemctl status sshd(VPS プロバイダーには、まさにこういうときのためのウェブコンソールがあります)。 - 非標準のポートで待ち受けている。
ssh -p 2222を試すか、/etc/ssh/sshd_configのPortを確認。 - ファイアウォールが、そのポートを(ドロップではなく)能動的に拒否している。
サーバーを たった今 作り直したなら、原因はファイアウォールです。昨日まで動いていたなら、sshd がクラッシュしたか、ポートが変わったのです。
完全な解決策: connection refused と timed out の読み解き。
2. Connection timed out
refused とは違い、パケットが消えています。ホストが落ちている、IP が間違っている、あるいは、クラウドのマシンでは最も多いことですが、セキュリティグループやネットワーク ACL が 22 番ポートを黙ってドロップしています。まずプロバイダーのファイアウォールのルールを確認し、次に、送信 22 番をブロックするネットワークにいないかを確認します(ホテルやオフィスのゲスト Wi-Fi はこれが大好きです。ポート 443 ベースのアクセスや別のネットワークを試して確かめましょう)。
完全な解決策: 同じ refused と timed out のウォークスルーに、timed-out の分岐が手順ごとに載っています。
3. Permission denied (publickey)
不動のチャンピオンです。サーバーは鍵認証しか受け付けず、あなたが提示したどの鍵も受け入れませんでした。可能性の高い順に。
- ユーザーが違う。 Ubuntu イメージなら
ubuntu、Amazon Linux ならec2-user、素の VPS の多くはroot。同じ鍵でもユーザー名が違えば、まさにこのエラーが出ます。クラウドのイメージはそれぞれ独自のログインユーザーを採用しており、これは初めての EC2/VPS ログイン(英語)の半分を占める話です。 - 鍵が提示されなかった。
ssh -vは試したすべての鍵を表示します。あなたの鍵が一覧になければ、明示的に指定します。ssh -i ~/.ssh/id_ed25519 user@host。 - 鍵がサーバー上にない。 公開鍵側が
~user/.ssh/authorized_keysに 1 行として入っている必要があります。root ではなく、その ユーザーのものに、です。 - サーバー側のパーミッション。 ホームディレクトリ、
~/.ssh(700)、あるいはファイル自体(600)がグループ書き込み可能だと、sshd はauthorized_keysを尊重しません。これは「鍵をコピーしたのに、まだ動かない」の定番です。
完全な解決策: Permission denied (publickey) を素早く体系的に直す(英語)が、すべての原因を順番に片付けます。
4. パスワードのプロンプトを期待したのに Permission denied
パスワード認証を使いたいのに一度も尋ねられなかったなら、サーバーは PasswordAuthentication no になっています。クラウドのイメージはたいていそう出荷され、それが正しい既定です。パスワードを再び有効に戻すのではなく、プロバイダーのコンソールか既存の鍵で入り、新しい鍵をきちんと追加しましょう。
5. Host key verification failed / REMOTE HOST IDENTIFICATION HAS CHANGED
ASCII のドクロのような迫力がある、おっかないバナーです。サーバーが、以前あなたが信頼したのとは別の鍵を提示しました。説明は 2 つです。マシンが正当に作り直された/再インストールされた(圧倒的によくあるケース)か、あなたとサーバーの間の何かがなりすましている(この警告が存在する理由のケース)かです。
サーバーが作り直されたと分かっている場合に限り、ssh-keygen -R hostname が古いエントリを削除し、次の接続で再び信頼します。その削除を、やみくもにワークフローへ組み込まないでください。警告が本物であるただ一度のとき、それが唯一の警告なのですから。
完全な解決策: Host key verification failed と、その正しい直し方(英語)。
6. Too many authentication failures
エージェントが張り切って 6 本の鍵を提示し、サーバーの MaxAuthTries が「もう十分」と言ったのです。意図した鍵だけを提示するよう、クライアントに伝えます。
ssh -o IdentitiesOnly=yes -i ~/.ssh/the_right_key user@host
……あるいは ~/.ssh/config にホストごとで恒久的に設定します。多くの鍵を持ち歩いているなら、Host * の下の IdentitiesOnly yes が、このエラーから永遠にあなたを救います。
7. WARNING: UNPROTECTED PRIVATE KEY FILE
あなたの 秘密 鍵が他者から読める状態で、クライアントがそれを使うのを拒んでいます。chmod 600 ~/.ssh/id_ed25519 です。Windows では、マシン間やクラウドドライブから鍵をコピーした後に出ます。ファイルのセキュリティのプロパティから直すか、鍵を同期フォルダーの外に置いておきましょう。
8. client_loop: send disconnect: Broken pipe(目を離すと死ぬセッション)
あなたとサーバーの間の NAT ルーターや攻撃的なファイアウォールが、アイドル状態の接続を切っています。キープアライブがクライアント側で解決します。
Host *
ServerAliveInterval 30
ServerAliveCountMax 4
2 分間の沈黙までは許容し、30 秒ごとにパケットを送るので、NAT のテーブルがあなたを忘れることはありません。アイドルではなく 負荷のかかった状態で セッションが死ぬなら、それは別物です。キープアライブではなく MTU(特に VPN)を見てください。
9. no matching key exchange method found / no matching cipher
あなたは何か古いもの、つまりレガシーな暗号から抜け出せないルーター、スイッチ、アプライアンスと話しています。現代の OpenSSH は、相応の理由があってそれらのアルゴリズムを削除しました。グローバルにではなく、そのホスト 1 台だけ で再有効化します。
Host ancient-switch
KexAlgorithms +diffie-hellman-group14-sha1
Ciphers +aes256-cbc
エラーメッセージは、サーバーが提示したアルゴリズムの名前を挙げます。その一覧の中で、いちばんマシなものを追加してください。
10. ssh_exchange_identification: read: Connection reset by peer
TCP 接続が開いた直後、SSH が挨拶すらする前に、勢いよく閉じられました。容疑者の定番は、fail2ban か DenyHosts があなたの IP を禁止している(コンソールから /etc/hosts.deny と fail2ban の jail を確認)、sshd が過負荷(ポートを叩き続けるスキャナーに MaxStartups を使い切られた)、あるいはロードバランサーのヘルスチェックが接続を食べている、です。原因が fail2ban で、しかも自分のサーバーなら、直し方はコンソールからログインして fail2ban-client unban <your-ip>。そのうえで、SSH をスキャナーのレーダーから外すか、jail を締めて、来週の巻き添えにならないようにしましょう。
11. Bad configuration option: pubkeyacceptedalgorithms
サーバーの問題ではありません。ローカルの ssh が設定ファイルに対して古すぎるのです。PubkeyAcceptedAlgorithms は OpenSSH 8.5 で登場しました(PubkeyAcceptedKeyTypes を置き換えたもの)。その行を古いクライアント(ある年代の macOS 標準 ssh、古いディストロ、最小構成のコンテナーイメージ)に食べさせると、ファイルの解析自体を拒みます。抜け道は 3 つ。クライアントを更新する(ssh -V で現状が分かります)。新しいバージョンがいまもエイリアスとして受け入れる、古い綴り PubkeyAcceptedKeyTypes を使う。あるいは、能力のあるクライアントだけが読むよう、その行をガードする。
Match all
# only OpenSSH >= 8.5 gets here via Include ordering
実際には、最もシンプルなガードは、バージョンに敏感なオプションを Include で取り込む別ファイルに分けておくことです。そうすれば、同じ dotfiles を使う古いクライアントは、それを読み飛ばすだけです。同じ形のエラー(Bad configuration option: <something>)は、いつも同じことを意味します。その 単語 が このバイナリ にとって未知だ、ということです。まずオプションの綴りを、次にバイナリのバージョンを確認してください。
12. did not receive identification string / invalid ssh identification string
どちらも SSH の最初の段階、つまり暗号処理より前のバナー交換で起きます。did not receive identification string from <ip> は、何かが 22 番ポートへ TCP 接続を開いたものの SSH-2.0-... の行を一度も送らなかったときに、sshd が サーバー側 で記録します。ポートスキャナー、ロードバランサーのヘルスチェック、監視のプローブ、あるいは諦めたクライアントなどです。サーバーのログでは、これはほぼ常に背景のノイズであって不具合ではありません。ただし、接続に失敗しているのが あなたの クライアントなら話は別で、その場合は経路上の何か(プロキシ、TCP ラッパー、IDS)がバナーを食べています。
kex_exchange_identification: ... invalid ssh identification string はその裏返しです。何かが 応答した のですが、SSH ではないデータでした。よくある原因を順に。ssh を間違ったポートに向けている(HTTP サーバー、データベース、HTML を返すキャプティブポータルなど)。経路上のミドルボックスが接続を横取りし、サーバーの代わりに応答している。あるいは ProxyCommand/ProxyJump の設定ミスが、SSH ストリームでない何かをクライアントへ流し込んでいる(バナーがあるべき場所に、プロキシのエラーページが届く)。本当に sshd と話しているかを確かめましょう。nc <host> 22 は、すぐに SSH-2.0-OpenSSH... のバナーを表示するはずです。HTML が出たり何も出なかったりするなら、問題は鍵ではなく、ポート(あるいはホスト、あるいはプロキシの経由先)です。
13. Unspecified GSS failure / debug1: unspecified GSS failure. Minor code may provide more information
Kerberos のノイズです。OpenSSH は既定で、あなたの鍵より先に GSSAPI(Kerberos)認証を試みます。Kerberos のレルムにいない場合(ほとんどの人がそうです)、これは失敗してデバッグレベルでこの行を記録し、その後、鍵認証にフォールバックして問題なく接続します。最終的に接続が成功しているなら、この行は無害です。無視してください。 これが問題になるのは、実際に Kerberos の SSO に依存していて、認証が失敗している場合だけで、そのときは本物のチケット/レルムの問題です(klist、時刻のずれ、DNS 上のホストの SPN を確認)。Kerberos を使わない構成でノイズを止めるには、設定に GSSAPIAuthentication no を追加します。
直した状態を定着させる
これらの半分は一度きりの修正です。残りの半分は、二度と戻ってこないよう ~/.ssh/config に 1 行を割く価値があります。キープアライブ、IdentitiesOnly、ホストごとのポートと鍵、などです。設定は記憶に勝ります。
記憶に勝るもう 1 つは、あなたの代わりに状態を保持してくれるクライアントです。Termalin は、ホストごとの設定(ポート、ユーザー、鍵、キープアライブ)をホスト自体とともに保存し、初回接続時にサーバーを検証し、フィンガープリントが変わると大きく警告します。ステータスバーにはマシンのバイタルがライブで表示されるので、「そもそもマシンは起きているのか?」が診断の一手順でなくなります。Free プランはホスト数の制限がありません。入手して、これらのエラーのいくつかを永久に引退させましょう。