SSHのToo many authentication failuresを解決する方法
SSHの「Too many authentication failures」は、ssh-agentの鍵をすべて提示してMaxAuthTriesの既定値6回を超えるエラーです。ssh -vで原因を確認し、正しい鍵だけを使う設定を紹介します。
「Too many authentication failures」の意味
「Too many authentication failures」は、SSH クライアントがサーバーの確認可能な上限を超える数の鍵を提示したため、正しい鍵が試される前にサーバーが接続を切断したことを意味します。これはほぼ常にクライアント側の問題です。鍵がディスク上にあり、サーバーがその鍵を authorized_keys に登録していても、接続が早すぎる段階で終了するため、それだけでは解決しません。
流れは次のとおりです。ssh-agent には、読み込まれているすべての秘密鍵が保存されています。クライアントは、アカウントがどの鍵を受け入れるか判断できないため、それらの鍵を1つずつサーバーに提示します。サーバーは authorized_keys にない鍵を拒否し、拒否するたびに認証失敗として数えます。sshd_config の MaxAuthTries は、1つの接続で許可される失敗回数を制限します。デフォルトは 6 です。agent に 10 個の鍵があり、正しい鍵が8番目の場合、そこまで到達する前にサーバーが接続を切断します。
したがって、クライアントが1つの鍵、つまり正しい鍵だけを提示するようにします。
サーバーが数えるものと、MaxAuthTries が関係する箇所
公開鍵認証は、推測を繰り返す処理として始まります。クライアントは公開鍵を送信し、その鍵で作成した署名をサーバーが受け入れるかどうかを確認します。サーバーは yes または no で応答します。no は、誤ったパスワードと同じく、失敗した試行として扱われます。
sshd_config(5) のマニュアルページでは、次のように上限を説明しています。「接続ごとに許可する認証試行の最大回数を指定します。失敗回数がこの値の半分に達すると、以降の失敗がログに記録されます。既定値は 6 です。」
パスワードを入力する人にとって、6 回の試行は十分です。しかし、10 個の鍵を保持するエージェントにとっては、それほど多くありません。失敗回数が上限を超えると、sshd は接続を切断し、システムログに次のような行を書き込みます。
error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2クライアント側では、同じイベントの別の部分が表示されます。
Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22これは、SSH の permission denied (publickey) エラーとは異なる失敗です。後者では、サーバーは提示されたすべての鍵を確認し、そのどれも受け入れませんでした。今回は、サーバーが確認を途中で停止しています。この2つを同じものとして扱うと、正しい鍵をすでに再コピーした後も、原因のない作業を続けることになります。
同じ鍵が同僚のノート PC では使える理由
鍵にもサーバーにも違いはありません。同僚の agent には2個の鍵があり、あなたの agent には12個あります。同僚には最初に送られる鍵が、あなたには9番目に送られます。その時点で接続は終了しています。
鍵の数は気付かないうちに増えます。AddKeysToAgent yes を ~/.ssh/config で実行すると、使用した各鍵が agent に追加され、そのまま残ります。Linux の GNOME Keyring や macOS のログインキーチェーンなど、デスクトップの keyring agent はログイン時に鍵を自動的に読み込みます。1年の間にクライアント鍵、git ホスト鍵、検証環境のサーバー鍵を追加すると、ある日、常に接続できていたサーバーが接続を拒否し始めます。サーバー側は何も変わっていません。agent に保持される鍵が増えただけです。
ssh -v で送信される鍵を確認する方法
失敗する接続を -v 付きで実行し、トレースを確認します。
ssh -v deploy@203.0.113.10重要なのは、2 種類の行です。Will attempt key: には、クライアントが組み立てた認証情報が、使用する順序で表示されます。Offering public key: は、実際にサーバーへ送信された鍵ごとに 1 回表示されます。
debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Will attempt key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agentパス、鍵の種類、フィンガープリントは環境によって異なります。数えるのは、切断されるまでに表示された Offering public key: 行の数です。鍵の送信が続いた後、意図した鍵が一度も表示されないままセッションが終了する場合、原因は確定します。行末の agent という語は、その認証情報が ssh-agent から読み込まれたことを示します。explicit という語は、IdentityFile 行またはコマンドラインの -i から読み込まれたことを示します。
次に、agent が保持している鍵を確認します。
ssh-add -l出力の各行は、読み込まれている鍵を 1 つ示します。The agent has no identities. と表示された場合、問題は agent にはないため、代わりに ~/.ssh/config 内の IdentityFile 行を確認します。Could not open a connection to your authentication agent. と表示された場合、agent は実行されておらず、送信されている鍵はデフォルトの鍵ファイルから読み込まれています。
修正 1: ホストごとに 1 つの鍵を使用する IdentitiesOnly
IdentitiesOnly yes は、設定した認証情報だけを ssh が提示し、エージェントが追加で提示する認証情報を無視するように指定します。これを IdentityFile 行と組み合わせると、クライアントは 1 つだけ提示します。
Host vps
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_vps
IdentitiesOnly yesこれを ~/.ssh/config に保存し、chmod 600 ~/.ssh/config を実行します。グループ書き込み可能または全員書き込み可能なファイルがあると、ssh は Bad owner or permissions on /home/you/.ssh/config とともに実行を拒否します。これで ssh vps は 1 つの鍵だけを提示し、ssh -v vps には Offering public key: 行が正確に 1 行だけ表示されるはずです。
ここでは、2 つの点が意外に思われることがあります。
IdentitiesOnly yesだけでは「1 つの鍵」を意味しません。デフォルトの identity ファイルも設定済みの認証情報として数えられるため、ssh は~/.ssh/id_ed25519、~/.ssh/id_rsa、その他に見つかったデフォルトも試します。IdentityFile行も必要です。- 署名を行うのは引き続きエージェントです。
IdentitiesOnlyは提示する鍵を制御するものであり、署名者を指定するものではありません。IdentityFileで指定した秘密鍵がエージェントに読み込まれていれば、エージェントが署名を生成するため、パスフレーズは要求されません。IdentityFileに対応する.pubファイルを指定することもできます。これは、秘密鍵がエージェントまたはハードウェアトークンにしか存在しない場合に使用します。
~/.ssh/config にある 1 つの落とし穴によって、この修正が気付かないうちに無効になることがあります。多くのキーワードは最初に見つかった値が使われるため、特定の Host ブロックは Host * より上に置きます。IdentityFile はこの規則に従いません。マニュアルには、「設定ファイルで複数の identity ファイルを指定できます。これらの認証情報はすべて順番に試行されます」と記載されています。Host * 内の IdentityFile はホストごとの設定で置き換えられず、それに追加されます。そのため、忘れたグローバル設定によって、すべての接続で追加の鍵提示が再び行われます。
グローバルな安全策が必要な場合は、ファイルの末尾でフラグだけを設定します。
Host *
IdentitiesOnly yesその後は、すべてのホストに固有の IdentityFile が必要になります。これは、いずれにしても望ましい構成です。サーバーごとに鍵を 1 つ指定しておけば、後から 1 台のマシンのアクセスだけを失効させ、すべての鍵を再発行せずに済みます。この習慣は早い段階で身につける価値があります。マシンごとの SSH 鍵の管理方法も参照してください。
修正 2: agent のキーを削除するか再起動する
まだ設定を編集できない場合は、agent を空にして、必要なものだけを読み込みます。
ssh-add -l # list what is loaded
ssh-add -d ~/.ssh/id_rsa # remove one key
ssh-add -D # remove every key
ssh-add ~/.ssh/id_ed25519_vps # load the one you needssh-add -Dの直後に接続できる場合は、agent が原因です。これは修復ではなく、テストとして扱ってください。デスクトップの keyring agent は次回のログイン時にキーを再読み込みするため、問題は翌日に再発します。~/.ssh/config内のIdentitiesOnly行は再起動後も残ります。空にした agent の状態は残りません。
キーに有効期間を設定して、agent に自動削除させることもできます。
ssh-add -t 1800 ~/.ssh/id_ed25519_vpsキーは追加されてから 1800 秒後に削除されます。agent を再起動する方法もありますが、起動方法によって手順が異なります。自分で起動したssh-agentは、ssh-agent -kで停止します。自分で作成した systemd user unit から実行している場合は、systemctl --user restart <unit>でその unit を再起動します。keyring agent はデスクトップセッションの再起動時に再起動します。
修正 3: 1 回だけ接続するサーバー向けの一時的なコマンド
設定ファイルに追加しないホストでは、同じ設定をコマンドラインで指定します。
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10-i だけを指定するのが、最もよくある誤った修正です。-i は鍵を認証情報の一覧に追加するだけです。その一覧から agent の鍵を削除しないため、他の鍵が先にすべて提示され、接続は引き続き上限に達して失敗します。IdentitiesOnly なしで ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 を実行すると、agent の鍵が先に提示されることを確認できます。-i には -o IdentitiesOnly=yes も必要です。
1 回の接続で agent の影響を完全に除外するには、次のようにします。
ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10ssh はディスク上の秘密鍵を読み込み、パスフレーズが設定されていればその入力を求めます。
ssh を基盤として使用するツールも、同じオプションを受け付けます。
scp -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps report.tar.gz deploy@203.0.113.10:/tmp/
rsync -av -e "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" ./site/ deploy@203.0.113.10:/srv/site/
GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" git clone git@example.com:team/repo.git2 番目のホップでエラーが発生する理由
ForwardAgent yes を使用すると、接続先のサーバーで agent socket が利用可能になります。そのサーバー上で実行する ssh コマンドは、転送された socket を介して、すべての鍵を含むローカルの agent を使用します。そのため、最初のホップは正常でも、jump host から最終サーバーへのホップでエラーが発生することがあります。中間マシンで echo $SSH_AUTH_SOCK を実行します。socket のパスが表示される場合は、転送された agent に到達できます。出力が空の場合は、転送された agent がありません。
agent forwarding には、もう 1 つのリスクがあります。中間マシンの root があれば、セッションを開いている間、あなたの agent を使用して、あなたになりすまして認証できます。ProxyJump を使用すると、両方の問題を回避できます。
ssh -J deploy@jump.example.com deploy@10.0.0.5ProxyJump は jump host 経由で接続し、最終サーバーへの認証を自分のマシンから行います。そのため、ローカルの ~/.ssh/config が IdentitiesOnly を含むすべてのホップで適用されます。ForwardAgent を無効にすることは、VPS 上の SSH を強化する際の標準的な手順です。
サーバーの MaxAuthTries を増やすべきか
通常は増やしません。まず現在の値を確認します。
sudo sshd -T | grep -i maxauthtriessshd -T はデフォルト値を含む有効な設定を出力します。そのため、sshd_config に何も記載されていなくても実際の値を確認できます。Match ブロックを使用している場合は -C user=deploy,host=example.com,addr=203.0.113.10 も追加してください。これらのブロックは接続ごとに評価されるため、指定しないと確認対象から除外されます。
上限を増やせば、限定的な意味では効果があります。値を大きくすると、問題のあるクライアントが試行できる余地が増えるためです。
MaxAuthTries 20ファイルを検証してサービスを reload します。その際は、別のセッションを開いたままにしてください。
sudo sshd -t
sudo systemctl reload ssh # Debian and Ubuntu
sudo systemctl reload sshd # RHEL familyUbuntu 24.04 で systemctl is-enabled ssh.socket が enabled を出力する場合、sshd は socket activation で起動されています。接続ごとに新しいプロセスが起動し、その都度 sshd_config を読み込むため、新しい接続では変更が自動的に反映されます。
次に、その変更で何が起きたかを確認します。クライアントは、このサーバーが受け付けることのない鍵を提示しています。上限を増やすと、接続するすべてのクライアントとインターネット上のすべてのパスワード推測者について、サーバーは接続ごとに、拒否する鍵の提示を 6 回ではなく 20 回処理することになります。各提示では、サーバーが authorized_keys を検索します。正しい鍵が依然として最後にあるため、自分のログインも遅いままです。agent に 13 個目の鍵を追加すると、また同じ状態に戻り、再びより大きな値を設定することになります。
正当なクライアントが実際に複数の identity を提示する必要がある場合に限り、上限を増やしてください。それ以外の場合はクライアントを修正します。すべてのユーザーが設定済みの鍵でログインできるようになった後は、上限を下げることも適切な hardening です。値を小さくすると、推測者が接続ごとに試せる回数が減るためです。
fail2ban によってこのように ban される理由
デフォルトのログレベルでは、sshd は拒否した公開鍵認証を毎回記録します。
Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...full agent からの 1 回の接続で、同じアドレスから数行が 1~2 秒以内に出力されることがあります。fail2ban の sshd jail は sshd の失敗行を数え、findtime 内に maxretry に達すると送信元アドレスを ban します。これらの期間はデフォルトで短いため、壊れた接続を 2 回再試行するだけで、自分のアドレスが ban されることがあります。
その後、症状が変わります。ここが混乱しやすい点です。「Too many authentication failures」が表示されなくなり、何も表示されなくなります。接続がハングし、最終的にタイムアウトします。ファイアウォールが応答する代わりにパケットを破棄しているためです。以前はエラーメッセージが表示されていた箇所でタイムアウトすることが、その兆候です。この違いについては SSH 接続が拒否される場合とタイムアウトする場合 で説明しています。
プロバイダーのコンソールから、または別のアドレスから jail を確認し、ban を解除します。
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10クライアントを修正する間は、jail.local の ignoreip に自分のアドレスを追加してください。作業が終わったら、そのアドレスを削除します。jail 自体の設定については、Ubuntu 24.04 向け fail2ban ガイド を参照してください。
再発を防ぐために一度だけ行うこと
各サーバーに ~/.ssh/config 内の専用 Host ブロックを作成し、HostName、User、IdentityFile、IdentitiesOnly yes を指定します。その後は ssh vps の入力が短くなり、提示される鍵は必ず 1 つだけになります。agent に鍵がいくつ読み込まれていても、MaxAuthTries を発生させることはありません。また、別の障害が発生したときにも ssh -v の出力を読みやすい長さに保てます。
FAQ
「Too many authentication failures」をすぐに解決するにはどうすればよいですか?
すべての鍵ではなく、1 つの鍵だけを使用します。すぐに接続するには ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host を実行します。恒久的に修正するには、~/.ssh/config に HostName、User、IdentityFile でその鍵を指定し、IdentitiesOnly yes を含むブロックを追加してから、chmod 600 ~/.ssh/config を実行します。ssh -v で確認します。そのホストについて Offering public key: の行が 1 行だけ表示されるはずです。
ssh -i を指定しているのに、他の鍵も提示されるのはなぜですか?
-i は identity をリストに追加するだけで、リストを制限しないためです。ssh-agent に読み込まれた鍵はリストに残り、引き続き提示されます。多くの場合、指定した鍵より先に提示されるため、サーバーは指定した鍵に到達する前に MaxAuthTries に達することがあります。ssh が使用する identity を制限するオプションは -o IdentitiesOnly=yes です。-i と -o IdentitiesOnly=yes を併用するか、その接続だけ agent を完全に無視するには -o IdentityAgent=none を使用します。
これを解決するために、サーバーの MaxAuthTries を増やすべきですか?
いいえ。ほとんどの場合、増やすべきではありません。クライアントが、このサーバーでは受け入れられない鍵を送信しています。上限を増やしても、サーバーは接続ごとに拒否される提示をより多く評価するだけです。これは、接続してくるすべてのクライアントと総当たり攻撃に適用されます。また、agent に鍵が 1 つ増えると、再び問題が発生します。確認したい場合は sudo sshd -T | grep -i maxauthtries で実効値を確認し、IdentitiesOnly でクライアント側を修正します。
先月まで正常に動作していたサーバーで、なぜこの問題が発生したのですか?
agent に読み込まれた鍵が増えたためです。~/.ssh/config の AddKeysToAgent yes は、使用する各鍵を読み込んだままにします。デスクトップ環境の keyring agent も、ログイン時に独自に鍵を読み込みます。読み込まれた鍵の数がサーバーの MaxAuthTries を超えると、提示順が後ろの鍵を使用するサーバーで失敗し始めます。ssh-add -l を実行し、サーバー側の上限と数を比較します。
fail2ban によって IP アドレスが禁止されることはありますか?
はい。拒否された鍵ごとに、サーバーのログへ Failed publickey for ... 行が出力されます。そのため、1 回の接続で数秒以内に、送信元アドレスから複数の失敗が発生することがあります。findtime の間に maxretry に達すると、fail2ban の sshd jail がそのアドレスを禁止します。見分けるポイントは、エラーがハングアップに変わり、その後タイムアウトすることです。応答が返っているのではなく、パケットが破棄されているためです。sudo fail2ban-client set sshd unbanip <your address> でコンソールから解除し、再接続する前にクライアントを修正します。