SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor

SSH: risolvere "Too many authentication failures"

L'errore SSH appare quando il client offre troppe chiavi prima di quella corretta. Usa ssh -v e limita l'agent: MaxAuthTries predefinito è 6.

Cosa significa "Too many authentication failures"

"Too many authentication failures" significa che il client SSH ha offerto al server più chiavi di quante fosse disposto a verificare. Il server ha quindi chiuso la connessione prima di provare la chiave corretta. Quasi sempre il problema è nel client. La chiave si trova sul disco, il server la contiene in authorized_keys, ma nessuno dei due fatti è sufficiente perché la connessione è terminata troppo presto.

Il flusso è questo. ssh-agent contiene tutte le chiavi private caricate. Il client offre queste chiavi al server una alla volta, perché non può sapere quale chiave sia accettata dall'account. Il server rifiuta ogni chiave che non è presente in authorized_keys e conta ogni rifiuto come un tentativo di autenticazione non riuscito. MaxAuthTries in sshd_config limita il numero di tentativi non riusciti consentiti per una singola connessione. Il valore predefinito è 6. Se l'agent contiene dieci chiavi e quella corretta è l'ottava, il server chiude la connessione prima di arrivare a provarla.

La soluzione consiste quindi nel fare in modo che il client offra una sola chiave: quella corretta.

Cosa conta il server e come interviene MaxAuthTries

L'autenticazione con chiave pubblica inizia come un gioco di tentativi. Il client invia una chiave pubblica e chiede al server se accetterebbe una firma generata con quella chiave. Il server risponde sì o no. Un "no" è un tentativo non riuscito, esattamente come una password errata.

La pagina man di sshd_config(5) descrive il limite: "Specifica il numero massimo di tentativi di autenticazione consentiti per connessione. Quando il numero di errori raggiunge la metà di questo valore, gli errori aggiuntivi vengono registrati nei log. Il valore predefinito è 6."

Sei tentativi sono sufficienti per una persona che digita una password. Non sono molti per un agente che dispone di dieci chiavi. Quando il conteggio degli errori raggiunge il limite, sshd disconnette il client e scrive una riga simile nel log di sistema:

error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2

Il client visualizza l'altra metà dello stesso evento:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22

Si tratta di un errore diverso da l'errore SSH permission denied (publickey). In quel caso, il server ha esaminato tutto ciò che gli hai offerto e non ha accettato nulla. Qui il server ha smesso di esaminare le chiavi. Confondere i due casi porta a perdere tempo ricopiando una chiave che era già corretta.

Perché la stessa chiave funziona dal portatile del tuo collega

La chiave e il server sono identici. Il suo agent contiene due chiavi, mentre il tuo ne contiene dodici. La chiave che per lui viene offerta per prima arriva per te al nono tentativo; a quel punto la connessione è già terminata.

Il numero di chiavi aumenta senza che te ne accorga. AddKeysToAgent yes in ~/.ssh/config aggiunge all'agent ogni chiave utilizzata e la lascia memorizzata. Gli agent dei portachiavi desktop, come GNOME Keyring su Linux o il portachiavi di accesso su macOS, caricano le chiavi all'accesso senza chiedere conferma. Se nell'arco di un anno aggiungi una chiave client, una chiave per un host Git e una chiave per un server di laboratorio, un giorno un server che ha sempre funzionato inizia a rifiutare la connessione. Sul server non è cambiato nulla. È aumentato il numero di chiavi nell'agent.

Come vedere le chiavi offerte con ssh -v

Esegui la connessione che fallisce con -v e leggi il trace.

ssh -v deploy@203.0.113.10

Sono importanti due tipi di riga. Will attempt key: elenca le identità raccolte dal client, nell’ordine in cui verranno utilizzate. Offering public key: compare una volta per ogni chiave effettivamente inviata al 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... agent

I percorsi, i tipi di chiave e le impronte digitali saranno diversi. Devi contare il numero di righe Offering public key: prima della disconnessione. Se le offerte continuano a susseguirsi e la sessione termina senza che compaia mai la chiave prevista, la diagnosi è chiara. La parola agent alla fine di una riga indica che l’identità proviene da ssh-agent. La parola explicit indica che proviene da una riga IdentityFile o da -i nella riga di comando.

Poi chiedi all’agent quali chiavi contiene:

ssh-add -l

Ogni riga dell’output corrisponde a una chiave caricata. Se viene visualizzato The agent has no identities., l’agent non è la causa del problema e devi esaminare le righe IdentityFile in ~/.ssh/config. Se viene visualizzato Could not open a connection to your authentication agent., non è in esecuzione alcun agent e le offerte provengono dai file di chiave predefiniti.

Correzione 1: IdentitiesOnly con una chiave per host

IdentitiesOnly yes indica a ssh di offrire soltanto le identità configurate e di ignorare quelle aggiuntive che l’agent propone automaticamente. Insieme a una direttiva IdentityFile, il client invia una sola offerta.

Host vps
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519_vps
  IdentitiesOnly yes

Salva la configurazione in ~/.ssh/config, quindi esegui chmod 600 ~/.ssh/config. Se il file è scrivibile dal gruppo o da chiunque, ssh rifiuta di essere eseguito e visualizza Bad owner or permissions on /home/you/.ssh/config. Ora ssh vps offre una sola chiave e ssh -v vps dovrebbe mostrare esattamente una riga Offering public key:.

Due dettagli sorprendono spesso gli utenti.

  • IdentitiesOnly yes da solo non significa “una sola chiave”. Se manca una direttiva IdentityFile, i file di identità predefiniti vengono considerati identità configurate. ssh prova quindi comunque ~/.ssh/id_ed25519, ~/.ssh/id_rsa e gli altri file predefiniti disponibili. Serve anche la direttiva IdentityFile: quando viene impostata, ssh smette di aggiungere i file predefiniti.
  • La firma continua a essere eseguita dall’agent. IdentitiesOnly controlla quali chiavi vengono offerte, non chi esegue la firma. Se la chiave privata indicata da IdentityFile è caricata nell’agent, l’agent produce la firma e non viene mai richiesta una passphrase. Puoi anche impostare IdentityFile sul file .pub corrispondente. È la configurazione da usare quando la chiave privata esiste soltanto nell’agent o su un token hardware.

Un’impostazione in ~/.ssh/config può annullare silenziosamente questa correzione. Per la maggior parte delle parole chiave viene usato il primo valore trovato. Per questo i blocchi Host specifici devono precedere Host *. IdentityFile non segue questa regola. Il manuale specifica: “È possibile indicare più file di identità nei file di configurazione; tutte queste identità verranno provate in sequenza.” Una direttiva IdentityFile all’interno di Host * viene aggiunta a quella specifica dell’host, invece di sostituirla. Una direttiva globale dimenticata reintroduce quindi un’offerta aggiuntiva in ogni connessione.

Se vuoi una misura di sicurezza globale, imposta soltanto il flag alla fine del file:

Host *
  IdentitiesOnly yes

Ogni host dovrà quindi avere una propria direttiva IdentityFile, che è comunque il risultato desiderato. Assegnare una chiave a ogni server consente inoltre di revocare in seguito l’accesso a una singola macchina senza dover rigenerare tutto. È una pratica utile da adottare fin dall’inizio: vedi come gestire le chiavi SSH per macchina.

Correzione 2: svuotare o riavviare l'agent

Se non puoi ancora modificare la configurazione, svuota l'agent e carica soltanto ciò che ti serve.

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

Se la connessione funziona subito dopo ssh-add -D, la causa era l'agent. Consideralo un test, non una correzione. Un agent del portachiavi del desktop ricarica le chiavi al login successivo, quindi il problema si ripresenterà domani. Una riga IdentitiesOnly in ~/.ssh/config persiste dopo un riavvio. Un agent vuoto no.

Puoi anche impostare una durata per una chiave, in modo che sia l'agent a rimuoverla:

ssh-add -t 1800 ~/.ssh/id_ed25519_vps

La chiave viene rimossa 1800 secondi dopo essere stata aggiunta. Anche riavviare l'agent è una soluzione, ma la procedura dipende da ciò che lo ha avviato. Un ssh-agent avviato manualmente si arresta con ssh-agent -k. Se lo esegui tramite una user unit di systemd che hai creato, riavvia l'unità con systemctl --user restart <unit>. Un agent del portachiavi viene riavviato insieme alla sessione desktop.

Correzione 3: il comando una tantum per un server che utilizzi una sola volta

Per un host che non aggiungerai alla configurazione, specifica le stesse impostazioni nella riga di comando:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

-i da solo è la correzione errata più comune. -i aggiunge una chiave all’elenco delle identità. Non rimuove le chiavi dell’agent da quell’elenco, quindi tutte le altre chiavi vengono comunque offerte prima della tua e la connessione continua a interrompersi quando raggiunge il limite. Esegui ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 senza IdentitiesOnly per vedere che le chiavi dell’agent vengono offerte per prime. -i deve essere accompagnato da -o IdentitiesOnly=yes.

Per escludere completamente l’agent da una connessione:

ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

ssh legge quindi la chiave privata dal disco e ne richiede la passphrase, se impostata.

Gli strumenti basati su ssh accettano la stessa opzione:

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

Perché l’errore compare al secondo hop

Con ForwardAgent yes, il socket dell’agent viene reso disponibile sul server a cui ci si connette. Un comando ssh eseguito su quel server usa il proprio agent locale, con tutte le chiavi, tramite il socket inoltrato. Per questo l’errore può comparire nell’hop da un jump host al server finale, mentre il primo hop funziona correttamente. Eseguire echo $SSH_AUTH_SOCK sulla macchina intermedia: un output vuoto significa che non è raggiungibile alcun agent. Un percorso del socket indica che è presente un agent, ma non necessariamente il proprio, perché un agent avviato su quella macchina imposta la stessa variabile. Eseguire anche ssh-add -l: se elenca le chiavi della propria macchina, l’inoltro è attivo.

L’inoltro dell’agent comporta anche un secondo rischio. Chiunque disponga dell’accesso root alla macchina intermedia può usare il proprio agent per autenticarsi come l’utente, finché la sessione resta aperta. ProxyJump evita entrambi i problemi:

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

ProxyJump apre una connessione tramite il jump host e si autentica al server finale dalla propria macchina, quindi il ~/.ssh/config locale si applica a ogni hop, incluso IdentitiesOnly. Disattivare ForwardAgent è una procedura standard per rafforzare la sicurezza di SSH su un VPS.

Aumentare MaxAuthTries sul server?

Di solito no. Controllare prima il valore attuale:

sudo sshd -T | grep -i maxauthtries

sshd -T stampa la configurazione effettiva, inclusi i valori predefiniti, quindi restituisce il valore reale anche quando sshd_config non contiene alcuna impostazione al riguardo. Aggiungere -C user=deploy,host=example.com,addr=203.0.113.10 se si usano blocchi Match, perché vengono valutati per ogni connessione e altrimenti vengono ignorati.

Aumentare il limite funziona, in senso stretto, perché un valore più alto concede a un client che si comporta in modo anomalo più tentativi:

MaxAuthTries 20

Convalidare il file e ricaricare il servizio. Durante l'operazione, mantenere aperta una seconda sessione:

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

Se systemctl is-enabled ssh.socket restituisce enabled su Ubuntu 24.04, sshd è attivato tramite socket. Il ssh.socket di Ubuntu non avvia un nuovo demone per ogni connessione: avvia ssh.service quando arriva la prima connessione, quindi il servizio continua a funzionare e gestisce le connessioni successive. Il reload precedente è comunque l'operazione che applica la modifica. Se ssh.service non è ancora attivo, non c'è nulla da ricaricare e la connessione successiva lo avvia usando il nuovo file.

A questo punto verificare l'effetto della modifica. Il client sta proponendo chiavi che questo server non accetterà mai. Aumentare il limite dice al server di elaborare venti chiavi rifiutate per connessione invece di sei, per ogni client che si connette e per ogni tentativo di indovinare la password proveniente da Internet. Ogni proposta richiede al server una ricerca in authorized_keys. Il proprio accesso resta lento, perché la chiave corretta si trova comunque in fondo all'elenco. Aggiungere una tredicesima chiave all'agent riporta alla situazione iniziale e richiede di nuovo un valore più alto.

Aumentare il limite solo quando un client legittimo deve davvero presentare diverse identità. In tutti gli altri casi, correggere il client. Ridurlo è una misura di hardening ragionevole quando ogni utente accede con una chiave configurata, perché un valore più basso concede a chi tenta di indovinare la password meno tentativi per connessione.

Perché fail2ban può bloccare il tuo indirizzo in questo caso

sshd non registra ogni chiave rifiutata. Con il valore predefinito di LogLevel INFO, una chiave rifiutata per un account esistente viene scritta nel log solo quando il conteggio dei tentativi della connessione raggiunge la metà di MaxAuthTries, come indicato nel manuale: "Once the number of failures reaches half this value, additional failures are logged." Con il valore predefinito 6, le prime tre chiavi rifiutate non vengono scritte nel log. Le ultime tre vengono registrate con righe come questa, seguite dalla riga maximum authentication attempts exceeded:

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

Queste righe sembrano indicare molti tentativi falliti, ma il filtro sshd di fail2ban non le conta. Il valore predefinito fornito dal programma, publickey = nofail, legge una riga Failed publickey relativa a un utente valido soltanto per recuperare l'indirizzo e il nome utente. La riga che viene conteggiata è maximum authentication attempts exceeded, quindi una connessione che raggiunge il limite aggiunge un solo errore, non diversi. Il jail blocca l'indirizzo sorgente quando si verificano maxretry errori entro findtime. La configurazione predefinita di fail2ban, jail.conf, imposta questi valori rispettivamente su 5 e 10 minuti. Sono sufficienti circa cinque connessioni fallite in dieci minuti per bloccare il proprio indirizzo. Uno script o uno strumento che riprova in ciclo raggiunge rapidamente questo limite.

A questo punto il sintomo cambia. È questo l'aspetto che spesso crea confusione. Non viene più visualizzato "Too many authentication failures" e non viene visualizzato più nulla: la connessione resta in attesa e alla fine va in timeout, perché il firewall ora scarta i pacchetti invece di rispondere. Un timeout al posto del precedente messaggio di errore è il segnale da osservare. La differenza è descritta in Connessione SSH rifiutata o connessione SSH scaduta per timeout.

Dalla console del provider, oppure da un indirizzo diverso, controlla il jail e rimuovi il blocco:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10

Inserisci il tuo indirizzo in ignoreip all'interno di jail.local mentre risolvi il problema del client. Rimuovilo al termine. La configurazione del jail è descritta in la guida a fail2ban per Ubuntu 24.04.

Cosa fare una volta sola per evitare che il problema si ripresenti

Assegna a ogni server un proprio blocco Host in ~/.ssh/config, con HostName, User, IdentityFile e IdentitiesOnly yes. In questo modo, ssh vps è breve da digitare, offre esattamente una chiave e non può attivare MaxAuthTries, anche quando il tuo agent contiene molte chiavi. Inoltre mantiene breve l'output di ssh -v, così resta leggibile quando si verifica un altro problema.

FAQ

Come posso correggere subito l'errore "Too many authentication failures"?

Offri una sola chiave invece di tutte. Per una connessione immediata, esegui ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host. Per una correzione permanente, aggiungi un blocco a ~/.ssh/config con HostName, User e IdentityFile impostati sulla chiave in questione, quindi IdentitiesOnly yes e poi chmod 600 ~/.ssh/config. Verifica con ssh -v: per quell'host dovresti vedere una sola riga Offering public key:.

Perché ssh -i continua a offrire le altre chiavi?

Perché -i aggiunge un'identità all'elenco, ma non limita l'elenco. Le chiavi caricate in ssh-agent restano nell'elenco e continuano a essere offerte, spesso prima della tua. Il server può quindi raggiungere MaxAuthTries prima di arrivare alla tua chiave. -o IdentitiesOnly=yes è l'opzione che limita ssh alle identità specificate. Usa insieme -i e -o IdentitiesOnly=yes, oppure -o IdentityAgent=none per ignorare completamente l'agent in quella singola connessione.

Devo aumentare MaxAuthTries sul server per risolvere il problema?

No, nella quasi totalità dei casi. Il client invia chiavi che il server non accetterà mai. Un limite più alto fa soltanto valutare al server un numero maggiore di offerte rifiutate per connessione, per ogni client e per ogni tentativo di brute force che lo raggiunge. Il problema si ripresenta anche non appena nell'agent viene caricata un'altra chiave. Se vuoi verificare il valore effettivo, controllalo con sudo sshd -T | grep -i maxauthtries, quindi correggi il client con IdentitiesOnly.

Perché il problema è comparso su un server che il mese scorso funzionava correttamente?

L'agent contiene più chiavi. AddKeysToAgent yes in ~/.ssh/config mantiene caricata ogni chiave utilizzata, mentre gli agent dei portachiavi dei desktop caricano autonomamente le chiavi al login. Quando il numero di chiavi caricate supera MaxAuthTries del server, qualsiasi server la cui chiave si trova in una posizione avanzata nell'ordine delle offerte inizia a rifiutare la connessione. Esegui ssh-add -l e confronta il numero con il limite configurato sul server.

Questo può far bloccare il mio indirizzo IP da fail2ban?

Sì, anche se più lentamente di quanto suggeriscano i log del server. Il filtro sshd predefinito di fail2ban non conta le righe Failed publickey relative a un utente valido. Conta la riga maximum authentication attempts exceeded, quindi ogni connessione che raggiunge il limite equivale a un errore. Con i valori predefiniti distribuiti, maxretry = 5 e findtime = 10m, bastano circa cinque connessioni di questo tipo in dieci minuti per bloccare il tuo indirizzo. Il segnale è che l'errore si trasforma in un'attesa prolungata e poi in un timeout, perché i pacchetti vengono scartati invece di ricevere una risposta. Rimuovi il blocco dalla console con sudo fail2ban-client set sshd unbanip <your address> e correggi il client prima di riconnetterti.

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