SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

SSHの「Too many authentication failures」を解決する方法

SSHの「Too many authentication failures」は、正しい鍵の前に上限6回へ達するエラーです。ssh -vで提示順を確認し、ssh-agentの鍵を1つに絞って解決します。

「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) のマニュアルページには、次の制限が記載されています。「1 接続あたりに許可する認証試行の最大回数を指定します。失敗回数がこの値の半分に達すると、以降の失敗がログに記録されます。デフォルト値は 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を指定すると、設定した identity だけが ssh から提示され、agent が追加で提示する鍵は無視されます。これを 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 つの鍵」にはなりません。IdentityFile の行がない場合、デフォルトの identity ファイルも設定済みの identity として扱われるため、ssh は ~/.ssh/id_ed25519、~/.ssh/id_rsa、その他に見つかったデフォルトのファイルも試します。IdentityFile の行も必要です。これを 1 つ指定すると、ssh はデフォルトの identity を追加しなくなります。
  • 署名を行うのは引き続き agent です。IdentitiesOnly は提示する鍵を制御するものであり、署名を行う主体を指定するものではありません。IdentityFile で指定した秘密鍵が agent に読み込まれていれば、署名は agent が生成するため、パスフレーズは要求されません。IdentityFile に対応する .pub ファイルを指定することもできます。これは、秘密鍵が agent または hardware token にしか存在しない場合に使います。

~/.ssh/config にある 1 つの設定が、この修正を気付かないうちに無効にします。多くのキーワードは最初に見つかった値を使うため、具体的な Host ブロックは Host * より前に置きます。IdentityFile はこの規則に従いません。マニュアルには、「設定ファイルで複数の identity file を指定でき、それらすべての 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 need

ssh-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.10

ssh はディスク上の秘密鍵を読み込み、パスフレーズが設定されていればその入力を求めます。

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.git

2 段目の hop でエラーが表示される理由

ForwardAgent yes を使うと、接続先のサーバーで agent socket が利用可能になります。そのサーバーで実行した ssh コマンドは、転送された socket を介して、すべての鍵を持つローカルの agent を使います。そのため、最初の hop は正常でも、jump host から最終サーバーへの hop でエラーが表示されることがあります。中間マシンで echo $SSH_AUTH_SOCK を実行してください。出力が空なら、到達可能な agent はありません。socket のパスが表示される場合は agent が存在しますが、それが自分の agent とは限りません。そのマシンで起動した agent が同じ変数を設定している可能性があるためです。そこでも ssh-add -l を実行してください。自分のマシンの鍵が一覧に表示されるなら、forwarding は有効です。

Agent forwarding には、もう 1 つのリスクがあります。中間マシンの root は、そのマシンでセッションが開いている間、あなたの agent を使ってあなたになりすまし、認証できます。ProxyJump を使うと、両方の問題を回避できます。

ssh -J deploy@jump.example.com deploy@10.0.0.5

ProxyJump は jump host を経由して接続を開き、最終サーバーへの認証を自分のマシンから行います。そのため、ローカルの ~/.ssh/config が IdentitiesOnly を含むすべての hop に適用されます。VPS で SSH を強化する場合、ForwardAgent を無効にするのは標準的な手順です。

サーバーで MaxAuthTries を増やすべきか

通常は増やしません。まず現在の値を確認します。

sudo sshd -T | grep -i maxauthtries

sshd -T はデフォルトを含む有効な設定を出力します。そのため、sshd_config に値が記載されていなくても実際の値を確認できます。Match ブロックを使用している場合は -C user=deploy,host=example.com,addr=203.0.113.10 も追加します。これらのブロックは接続ごとに評価され、指定しないと対象外になるためです。

上限を増やせば、限定的な意味では効果があります。値を大きくすると、動作不良のクライアントが試行できる余地が増えるためです。

MaxAuthTries 20

ファイルを検証してサービスを reload します。その際は、2 つ目のセッションを開いたままにしてください。

sudo sshd -t
sudo systemctl reload ssh      # Debian and Ubuntu
sudo systemctl reload sshd     # RHEL family

Ubuntu 24.04 で systemctl is-enabled ssh.socket が enabled を返す場合、sshd は socket activation で起動されています。Ubuntu の ssh.socket は接続ごとに新しい daemon を起動しません。最初の接続が到着したときに ssh.service を起動し、そのサービスが実行を続けて以降の接続を処理します。上記の reload で変更が適用されます。ssh.service がまだ active でなければ reload の対象はありません。次の接続時に、新しいファイルを使用して起動します。

次に、この変更の結果を確認します。このクライアントは、サーバーが受け入れることのない鍵を提示しています。上限を増やすと、接続するすべてのクライアントと、インターネット上でパスワードを推測するすべての接続元に対して、サーバーは接続ごとに 6 個ではなく 20 個の拒否される鍵を順に処理することになります。各鍵の提示で、サーバーは authorized_keys の検索を実行します。正しい鍵が最後に並んでいるため、自分の login も遅いままです。agent に 13 個目の鍵を追加すると、元の状態に戻り、再びより大きな値を指定する必要が生じます。

正当なクライアントが複数の identity を実際に提示する必要がある場合に限り、値を増やしてください。それ以外の場合は、クライアント側を修正します。すべての user が設定済みの鍵で login できるようになった後は、値を下げることも妥当な hardening です。値を小さくすると、推測を試みる接続元が接続ごとに試せる回数を減らせるためです。

これで fail2ban に自分のアドレスを ban される理由

sshd は、拒否された鍵をすべてログに記録するわけではありません。デフォルトの LogLevel INFO では、実在するアカウントに対する拒否された鍵は、接続の失敗回数が MaxAuthTries の半分に達した時点で初めてログに記録されます。これは、マニュアルにある「失敗回数がこの値の半分に達すると、追加の失敗が記録される」という説明に該当します。デフォルト値は 6 なので、最初の 3 回の拒否された鍵の提示はログに記録されません。最後の 3 回は、次のような行として表示され、その後に maximum authentication attempts exceeded の行が続きます。

Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...

これらの行は大量の失敗のように見えますが、fail2ban の sshd filter はこれらを複数の失敗として数えません。提供されているデフォルトの publickey = nofail は、有効なユーザーに対する Failed publickey の行からアドレスとユーザー名だけを取得します。カウント対象になるのは maximum authentication attempts exceeded です。そのため、制限に達した 1 接続で追加される失敗は 1 件であり、複数件ではありません。findtime の中に maxretry 件の失敗が入ると、jail は送信元アドレスを ban します。fail2ban 自体の jail.conf では、これらが 5 分と 10 分に設定されています。10 分間に約 5 回の接続失敗があれば、自分のアドレスを ban するには十分です。ループで再試行するスクリプトやツールを使うと、すぐにこの状態になります。

その後、症状が変わります。ここが混乱しやすい点です。「Too many authentication failures」が表示されなくなり、何も表示されなくなります。ファイアウォールがパケットに応答せず、drop しているため、接続がハングして最終的にタイムアウトします。以前はエラーメッセージが表示されていた箇所でタイムアウトする場合は、その違いが手がかりです。この違いについては SSH 接続拒否と 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 に達する可能性があります。-o IdentitiesOnly=yes は、ssh が指定した identity だけを使うように制限するオプションです。-i と -o IdentitiesOnly=yes を併用するか、1 回の接続で agent を完全に無視するには -o IdentityAgent=none を使用します。

この問題を解決するために、サーバーの MaxAuthTries を増やすべきですか?

通常は増やしません。ほぼすべての場合、クライアントが、このサーバーでは受け入れられない鍵を送信しています。上限を増やすと、サーバーは接続ごとに、さらに多くの拒否対象の提示を評価することになります。対象にはすべてのクライアントと、サーバーに到達するすべてのブルートフォース試行が含まれます。また、agent に鍵が 1 つ増えただけで再び問題が発生します。確認したい場合は sudo sshd -T | grep -i maxauthtries で実効値を確認し、IdentitiesOnly でクライアント側を修正します。

先月まで正常に動作していたサーバーで、なぜこの問題が発生したのですか?

agent に読み込まれた鍵が増えたためです。AddKeysToAgent yes は、~/.ssh/config にある使用する各鍵を読み込んだ状態に保ちます。また、デスクトップの keyring agent はログイン時に自動的に鍵を読み込みます。読み込まれた鍵の数がサーバーの MaxAuthTries を超えると、提示順で後ろにある鍵を使うサーバーで問題が発生し始めます。ssh-add -l を実行し、サーバー側の上限と数を比較します。

fail2ban によって IP アドレスが ban されることはありますか?

はい。ただし、サーバーのログから受ける印象よりも時間がかかります。デフォルトの fail2ban sshd filter は、正しいユーザーに対する Failed publickey 行を数えません。maximum authentication attempts exceeded 行を数えるため、上限に達した接続は 1 回の失敗として扱われます。maxretry = 5 と findtime = 10m が出荷時のデフォルト値の場合、10 分間にこの接続が約 5 回あるとアドレスが ban されます。判断の手掛かりは、エラーがハング状態に変わり、その後 timeout になることです。応答が返されるのではなく、パケットが破棄されているためです。コンソールから sudo fail2ban-client set sshd unbanip <your address> で解除し、再接続する前にクライアントを修正します。

#ssh#ssh-agent#openssh#ssh-config#troubleshooting