Fix SSH Too Many Authentication Failures
Too many authentication failures means your SSH agent offered every key it holds and the server cut you off. Diagnose it with ssh -v and fix it for good.
What "Too many authentication failures" means
"Too many authentication failures" means your SSH client offered the server more keys than it was willing to check, and the server closed the connection before your correct key was ever tried. This is almost always a client problem. The key is on your disk, the server has it in authorized_keys, and neither of those facts helps, because the connection ended too early.
Here is the chain. ssh-agent holds every private key you have loaded into it. Your client offers those keys to the server one at a time, because it has no way to know which one the account accepts. The server rejects each key that is not in authorized_keys, and it counts each rejection as a failed authentication attempt. MaxAuthTries in sshd_config limits how many failures one connection is allowed. The default is 6. If your agent holds ten keys and the right one is eighth in line, the server hangs up before it gets there.
So the fix is to make the client offer one key: the right one.
What the server counts, and where MaxAuthTries comes in
Public key authentication starts as a guessing game. The client sends a public key and asks whether the server would accept a signature made with it. The server answers yes or no. A "no" is a failed attempt, exactly like a wrong password.
The sshd_config(5) manual page describes the limit: "Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6."
Six attempts is plenty for a person typing a password. It is not much for an agent holding ten keys. Once the failure count passes the limit, sshd disconnects and writes a line like this to the system log:
error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2Your client prints the other half of the same event:
Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22This is a different failure from the SSH permission denied (publickey) error. There, the server looked at everything you offered and accepted none of it. Here the server stopped looking. Treating one as the other is how people spend an afternoon re-copying a key that was already correct.
Why the same key works from your colleague's laptop
Nothing is different about the key or about the server. Their agent holds two keys and yours holds twelve. The offer that arrives first for them arrives ninth for you, and by then the connection is over.
The count grows quietly. AddKeysToAgent yes in ~/.ssh/config adds each key you use to the agent and leaves it there. Desktop keyring agents, such as GNOME Keyring on Linux or the login keychain on macOS, load keys at login without asking. Add a client key, a git host key and a lab box key over a year, and one day a server that always worked starts refusing you. Nothing changed on the server. Your agent got fuller.
How to see the offers with ssh -v
Run the failing connection with -v and read the trace.
ssh -v deploy@203.0.113.10Two kinds of line matter. Will attempt key: lists the identities the client assembled, in the order it will use them. Offering public key: appears once for each key actually sent to the server.
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... agentYour paths, key types and fingerprints will differ. What you are counting is the number of Offering public key: lines before the disconnect. If the offers march past and the session ends without your intended key ever appearing, the diagnosis is settled. The word agent at the end of a line means that identity came from ssh-agent. The word explicit means it came from an IdentityFile line or from -i on the command line.
Then ask the agent what it is holding:
ssh-add -lEach line of output is one loaded key. If it prints The agent has no identities. then the agent is not your problem, and you should look at the IdentityFile lines in ~/.ssh/config instead. If it prints Could not open a connection to your authentication agent. then no agent is running, and the offers are coming from your default key files.
Fix 1: IdentitiesOnly with one key per host
IdentitiesOnly yes tells ssh to offer only the identities you configured and to ignore the extra ones the agent volunteers. Pair it with an IdentityFile line and the client sends a single offer.
Host vps
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_vps
IdentitiesOnly yesSave that in ~/.ssh/config, then run chmod 600 ~/.ssh/config. A group-writable or world-writable file makes ssh refuse to run, with Bad owner or permissions on /home/you/.ssh/config. Now ssh vps offers one key, and ssh -v vps should show exactly one Offering public key: line.
Two details surprise people here.
IdentitiesOnly yeson its own does not mean "one key". The default identity files count as configured identities, so ssh still tries~/.ssh/id_ed25519,~/.ssh/id_rsaand the other defaults it finds. You need theIdentityFileline as well.- The agent still does the signing.
IdentitiesOnlycontrols which keys are offered, not who signs them. If the private key named byIdentityFileis loaded in the agent, the agent produces the signature and you are never asked for a passphrase. You can even pointIdentityFileat the matching.pubfile, which is what you do when the private key lives only in the agent or on a hardware token.
One trap in ~/.ssh/config undoes this fix silently. Most keywords take the first value found, which is why specific Host blocks belong above Host *. IdentityFile does not follow that rule. The manual says: "It is possible to have multiple identity files specified in configuration files; all these identities will be tried in sequence." An IdentityFile under Host * is added to your per-host one, not replaced by it, so a forgotten global line puts an extra offer back into every connection.
If you want a global safety net, set only the flag, at the bottom of the file:
Host *
IdentitiesOnly yesEvery host then needs its own IdentityFile, which is the outcome you want anyway. Naming one key per server is also what makes it possible to revoke a single machine's access later without reissuing everything, and that habit is worth building early: see how to manage SSH keys per machine.
Fix 2: prune or restart the agent
If you cannot edit the config yet, empty the agent and load only what you need.
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 needIf the connection works right after ssh-add -D, the agent was the cause. Treat that as a test rather than a repair. A desktop keyring agent reloads its keys at your next login, so the problem comes back tomorrow. An IdentitiesOnly line in ~/.ssh/config survives a reboot. An empty agent does not.
You can also give a key a lifetime so the agent clears it for you:
ssh-add -t 1800 ~/.ssh/id_ed25519_vpsThe key is dropped 1800 seconds after it is added. Restarting the agent works too, and how you do it depends on what started it. An ssh-agent you launched yourself stops with ssh-agent -k. If you run it from a systemd user unit you wrote, restart that unit with systemctl --user restart <unit>. A keyring agent restarts with your desktop session.
Fix 3: the one off command for a server you touch once
For a host you will not add to your config, put the same settings on the command line:
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10-i on its own is the most common wrong fix. -i adds a key to the list of identities. It does not remove the agent's keys from that list, so all the other offers still go out ahead of yours and the connection still dies at the limit. Run ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 without IdentitiesOnly and you will watch the agent keys get offered first. -i needs -o IdentitiesOnly=yes beside it.
To take the agent out of the picture completely for one connection:
ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10ssh then reads the private key from disk and asks for its passphrase if it has one.
The tools built on ssh accept the same option:
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.gitWhy the error shows up on the second hop
With ForwardAgent yes, the agent socket is made available on the server you connect to. An ssh command run on that server uses your local agent, with all of your keys, over the forwarded socket. That is why the error can appear on the hop from a jump host to the final server while the first hop worked fine. Run echo $SSH_AUTH_SOCK on the middle machine: a socket path means a forwarded agent is in reach, and empty output means there is none.
Agent forwarding carries a second cost. Anyone with root on that middle machine can use your agent to authenticate as you, for as long as your session is open. ProxyJump avoids both problems:
ssh -J deploy@jump.example.com deploy@10.0.0.5ProxyJump opens a connection through the jump host and authenticates to the final server from your own machine, so your local ~/.ssh/config applies at every hop, IdentitiesOnly included. Turning ForwardAgent off is a standard step when hardening SSH on a VPS.
Should you raise MaxAuthTries on the server?
Usually not. Check the current value first:
sudo sshd -T | grep -i maxauthtriessshd -T prints the effective configuration, defaults included, so it reports the real value even when sshd_config says nothing about it. Add -C user=deploy,host=example.com,addr=203.0.113.10 if you use Match blocks, because those are evaluated per connection and are otherwise skipped.
Raising the limit does work, in the narrow sense that a larger number gives a misbehaving client more room:
MaxAuthTries 20Validate the file and reload the service, and keep a second session open while you do it:
sudo sshd -t
sudo systemctl reload ssh # Debian and Ubuntu
sudo systemctl reload sshd # RHEL familyIf systemctl is-enabled ssh.socket reports enabled on Ubuntu 24.04, sshd is socket activated: a fresh process starts per connection and reads sshd_config again, so new connections pick up the change on their own.
Now look at what that change did. The client is offering keys this server will never accept. Raising the ceiling tells the server to work through twenty rejected offers per connection instead of six, for every client that connects and for every password guesser on the internet. Each offer costs the server a lookup in authorized_keys. Your own login stays slow, because the right key is still last in line. Add a thirteenth key to your agent and you are back where you started, asking for a bigger number again.
Raise it only when a legitimate client really does need to present several identities. Fix the client in every other case. Lowering it is reasonable hardening once every user logs in with a configured key, since a smaller number gives a guesser fewer tries per connection.
Why fail2ban can ban you for this
At its default log level, sshd records each rejected public key:
Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...One connection from a full agent produces several of those lines from one address within a second or two. The fail2ban sshd jail counts sshd failure lines and bans the source address once maxretry is reached inside findtime. Those windows are small by default, so two retries of a broken connection can be enough to ban your own address.
The symptom then changes, and this is the part that confuses people. You stop seeing "Too many authentication failures" and start seeing nothing at all: the connection hangs and eventually times out, because the firewall is now dropping your packets instead of answering them. A timeout where you used to get an error message is the signal, and that distinction is covered in SSH connection refused versus connection timed out.
From your provider's console, or from a different address, check the jail and lift the ban:
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10Put your own address in ignoreip in jail.local while you sort out the client, then take it back out when you are done. The jail itself is set up in the fail2ban guide for Ubuntu 24.04.
What to do once, so this stops coming back
Give every server its own Host block in ~/.ssh/config, with HostName, User, IdentityFile and IdentitiesOnly yes. After that, ssh vps is short to type, it offers exactly one key, and it cannot trip MaxAuthTries however full your agent becomes. It also keeps ssh -v output short enough to read on the day something else breaks.
FAQ
How do I fix "Too many authentication failures" right now?
Offer one key instead of all of them. For an immediate connection, run ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host. For a permanent fix, add a block to ~/.ssh/config with HostName, User, IdentityFile pointing at that key, and IdentitiesOnly yes, then chmod 600 ~/.ssh/config. Confirm it with ssh -v: you should see one Offering public key: line for that host.
Why does ssh -i still offer my other keys?
Because -i adds an identity to the list, it does not restrict the list. The keys loaded in ssh-agent remain in the list and are still offered, often before yours, so the server can still hit MaxAuthTries before your key is reached. -o IdentitiesOnly=yes is the option that limits ssh to the identities you named. Use -i and -o IdentitiesOnly=yes together, or -o IdentityAgent=none to ignore the agent entirely for that one connection.
Should I increase MaxAuthTries on the server to fix this?
No, in nearly every case. The client is sending keys this server will never accept, and a larger limit only makes the server evaluate more rejected offers per connection, for every client and every brute force attempt that reaches it. It also breaks again as soon as one more key lands in your agent. Check the effective value with sudo sshd -T | grep -i maxauthtries if you are curious, then fix the client with IdentitiesOnly.
Why did this start on a server that worked fine last month?
Your agent got bigger. AddKeysToAgent yes in ~/.ssh/config keeps each key you use loaded, and desktop keyring agents load keys at login on their own. Once the number of loaded keys passes the server's MaxAuthTries, any server whose key sits late in the offer order starts failing. Run ssh-add -l and compare the count against the limit on the server.
Can this get my IP address banned by fail2ban?
Yes. Each rejected key produces a Failed publickey for ... line in the server log, so one connection can generate several failures from your address in seconds, and the fail2ban sshd jail bans the address once maxretry is reached within findtime. The give away is that the error changes into a hang and then a timeout, because packets are being dropped rather than answered. Clear it from the console with sudo fail2ban-client set sshd unbanip <your address>, and fix the client before you reconnect.