"Host key verification failed" in SSH, negli script e in CI

SSH non ha potuto confermare l'identità del server e si è fermato. Di solito il server non è ancora in known_hosts e nessuno può rispondere alla domanda sì o no, cosa che succede con BatchMode=yes, in cron e in CI. Aggiungi la chiave vera del server a known_hosts dell'utente che esegue il comando. Se vedi anche REMOTE HOST IDENTIFICATION HAS CHANGED, la chiave è diversa da quella salvata: capisci il motivo prima di togliere la vecchia.

Aggiornata il . Riprodotto con OpenSSH 10.3 su macOS contro un server OpenSSH 10.0 su Linux, usando un file known_hosts temporaneo.

Cosa vedi

In uno script con BatchMode=yes, o senza un terminale su cui chiedere, c'è una sola riga:

Host key verification failed.

Con StrictHostKeyChecking=yes sopra c'è anche il motivo:

No ED25519 host key is known for server and you have requested strict checking.
Host key verification failed.

Git aggiunge righe sue, che non vogliono dire che il repository manca:

Host key verification failed.
fatal: Could not read from remote repository.

Capire in quale caso sei

Esegui questo con lo stesso utente che esegue il comando che fallisce:

ssh-keygen -F server

Per un server su un'altra porta, la voce è salvata con le parentesi quadre:

ssh-keygen -F '[server]:2222'
  • Nessun output: l'host è sconosciuto a questo utente. Vedi causa 1 e causa 2.
  • Viene stampata una riga e l'errore mostra il grande avviso REMOTE HOST IDENTIFICATION HAS CHANGED: vedi causa 3.

Causa 1: il server non è in known_hosts

In un terminale, SSH ti chiederebbe di confermare l'impronta. BatchMode=yes vieta le domande, e un job senza terminale non ha nessuno a cui chiedere, quindi SSH fallisce. Aggiungi la chiave in anticipo.

Raccogli la chiave e confrontala con quella sul server prima di fidarti:

ssh-keyscan -t ed25519 server > server.hostkey
ssh-keygen -lf server.hostkey

Sul server stesso, o da una console del tuo provider:

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

Se le due impronte coincidono, installa la chiave:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
cat server.hostkey >> ~/.ssh/known_hosts

Per una porta diversa dalla 22, usa ssh-keyscan -p 2222 -t ed25519 server. ssh-keyscan da solo non prova nulla, perché accetta qualunque cosa risponda a quell'indirizzo. È il confronto a renderlo sicuro. I servizi di hosting pubblicano le loro impronte, per esempio GitHub nella pagina indicata nelle fonti.

In CI

Salva la riga verificata come variabile di CI e scrivila all'inizio del job, invece di fare la scansione a ogni esecuzione:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$KNOWN_HOSTS" >> ~/.ssh/known_hosts

accept-new e no

StrictHostKeyChecking=accept-new salva una chiave mai vista prima e rifiuta comunque una chiave cambiata. Si fida della prima connessione senza verificarla, un compromesso accettabile per una macchina usa e getta su una rete di cui ti fidi. Evita StrictHostKeyChecking=no: lascia proseguire la connessione anche quando la chiave è cambiata, cioè proprio la situazione per cui esiste questo controllo.

Cosa contiene ogni riga del file: known_hosts spiegato.

Causa 2: un altro utente o un altro HOME

known_hosts appartiene a un utente. Funziona nel tuo terminale e fallisce nel job quando il job gira come qualcun altro: sudo ssh usa il file di root, e cron, le build Docker e i runner di CI hanno una loro cartella home, spesso vuota a ogni esecuzione.

whoami
echo "$HOME"
ssh -G server | grep -iE '^(userknownhostsfile|stricthostkeychecking) '

L'ultimo comando stampa quali file SSH leggerà per quell'host, senza connettersi. Installa la chiave per quell'utente, oppure indica al job un file che controlli tu:

ssh -o UserKnownHostsFile=/path/to/known_hosts -o BatchMode=yes user@server true

Causa 3: la chiave salvata è diversa

L'output inizia allora con questo avviso, e le ultime due righe sono:

Host key for server has changed and you have requested strict checking.
Host key verification failed.

Una reinstallazione o un nuovo server allo stesso indirizzo è il motivo più comune, ma è anche l'aspetto di un'intercettazione. accept-new non la supera. Confronta le impronte come mostrato sopra e solo dopo rimuovi la vecchia voce:

ssh-keygen -R server

Con github.com succede spesso: GitHub ha sostituito la sua chiave host RSA a marzo 2023, quindi una vecchia riga salvata ora fallisce. Rimuovila con ssh-keygen -R github.com, poi aggiungi le chiavi che GitHub pubblica, dalla pagina nelle fonti.

Altro su questo caso in REMOTE HOST IDENTIFICATION HAS CHANGED.

Domande

Cosa significa Host key verification failed?

SSH non ha potuto confermare l'identità del server e si è fermato. O il server non è in known_hosts e nessuno poteva rispondere alla domanda, o la sua chiave è diversa da quella salvata.

StrictHostKeyChecking=no è una soluzione sicura in CI?

No. Accetta anche una chiave cambiata. Installa la chiave verificata in known_hosts, oppure usa accept-new su macchine usa e getta in una rete di cui ti fidi.

Perché funziona nel mio terminale ma fallisce in cron?

known_hosts appartiene a un utente. Cron, sudo e i runner di CI usano un altro utente o un'altra home, dove la voce salvata non c'è.

Perché git dice Host key verification failed con GitHub?

O github.com non è in known_hosts per l'utente che esegue git, o c'è ancora una riga RSA salvata prima di marzo 2023. Rimuovila con ssh-keygen -R github.com e aggiungi le chiavi dalla pagina dei fingerprint di GitHub.

Fonti

Altro in Messaggi di errore

Tutte le guide