com.jcraft.jsch.JSchException: UnknownHostKey


179

Sto cercando di utilizzare Jsch per stabilire una connessione SSH in Java. Il mio codice produce la seguente eccezione:

com.jcraft.jsch.JSchException: UnknownHostKey: mywebsite.com. 
RSA key fingerprint is 22:fb:ee:fe:18:cd:aa:9a:9c:78:89:9f:b4:78:75:b4

Non riesco a trovare come verificare la chiave host nella documentazione di Jsch. Ho incluso il mio codice qui sotto.

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class ssh {
    public static void main(String[] arg) {

        try {
            JSch jsch = new JSch();

            //create SSH connection
            String host = "mywebsite.com";
            String user = "username";
            String password = "123456";

            Session session = jsch.getSession(user, host, 22);
            session.setPassword(password);
            session.connect();

        } catch(Exception e) {
            System.out.println(e);
        } 
    }
}

Prova a chiudere sshd sul tuo host * nix e avvia un singolo thread in primo piano: / usr / sbin / sshd -d Questo ti darà molte informazioni di debug dal lato sshd.

@AmmSokun tutti sono stati in grado di risolvere questo problema. Vedi le risposte
bmargulies,

Risposte:


226

Vorrei:

  1. Provate sshdalla riga di comando e accettate la chiave pubblica (l'host verrà aggiunto ~/.ssh/known_hostse tutto dovrebbe funzionare correttamente da Jsch) -OPPURE-
  2. Configurare JSch in modo che non utilizzi "StrictHostKeyChecking" (questo introduce insicurezze e dovrebbe essere usato solo a scopo di test), usando il seguente codice:

    java.util.Properties config = new java.util.Properties(); 
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);

L'opzione n. 1 (aggiunta dell'host al ~/.ssh/known_hostsfile) ha le mie preferenze.


37
JSch#setConfig("StrictHostKeyChecking", "no")farà lo stesso lavoro, ma in una sola riga
yegor256

2
Nota a margine: ho usato questo feedback per configurare il mio ~/.ssh/configfile per correggere l'errore sopra quando non avevo accesso a modificare il codice sorgente
Adam Rofer

Cosa hai fatto al tuo .ssh / config? Sto riscontrando lo stesso errore.
Bernard Igiri,

19
Questo è insicuro e in realtà non avrebbe dovuto essere selezionato come la risposta giusta su quel principio. Le opzioni setKnownHosts () e setFingerPrint () sono il modo per farlo senza ignorare un aspetto importante del processo ssh. Modifica: nella mia esperienza, # 1 non funziona all'interno di alcuni ambienti IDE come Eclipse.
Rondo,

1
Ha fatto il lavoro per me all'interno di Eclipse ... proprio quello di cui avevo bisogno in un ambiente di test ....
ProfVersaggi

46

Mentre alla domanda è stata data una risposta in generale, mi sono trovato che esiste un caso in cui anche la voce known_hosts esistente non aiuta. Questo accade quando un server SSH invia l'impronta digitale ECDSA e, di conseguenza, avrai una voce come questa:

|1|+HASH=|HASH= ecdsa-sha2-nistp256 FINGERPRINT=

Il problema è che JSch preferisce SHA_RSA e durante la connessione proverà a confrontare l'impronta digitale SHA-RSA, che si tradurrà in un errore su "host sconosciuto".

Per risolvere questo problema, esegui semplicemente:

$ ssh-keyscan -H -t rsa example.org >> known_hosts

o lamentarsi con Jcraft per preferire SHA_RSA invece di utilizzare l' impostazione HostKeyAlgorithms locale , anche se non sembrano troppo desiderosi di correggere i loro bug .


1
Siamo in un caso simile, con ecdsa-sha2-nistp384, e la tua soluzione funziona molto bene. In accordo con il manuale di openssh-keyscan e le nostre necessità, corriamo ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
taringamberini

1
Ho avuto un tale problema, ma l'eccezione era JSchException: rifiutare HostKey: invece di JSchException: UnknownHostKey (questo potrebbe aiutare alcuni altri utenti)
bdulac

Ho dovuto aggiungere anche il file setKnownHosts come proposto da @krishnakumarp
Wolfgang Fahl

34

È un rischio per la sicurezza evitare il controllo della chiave host.

JSch utilizza l'interfaccia HostKeyRepository e la sua classe KnownHosts di implementazione predefinita per gestirlo. È possibile fornire un'implementazione alternativa che consenta chiavi specifiche implementando HostKeyRepository. In alternativa, è possibile conservare le chiavi che si desidera consentire in un file nel formato known_hosts e chiamare

jsch.setKnownHosts(knownHostsFileName);

O con una chiave pubblica String come di seguito.

String knownHostPublicKey = "mysite.com ecdsa-sha2-nistp256 AAAAE............/3vplY";
jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));

vedi Javadoc per maggiori dettagli.

Questa sarebbe una soluzione più sicura.

Jsch è open source e puoi scaricare la fonte da qui . Nella cartella degli esempi, cerca KnownHosts.java per conoscere maggiori dettagli.


16

A seconda del programma utilizzato per ssh, il modo di ottenere la chiave corretta potrebbe variare. Putty (popolare con Windows) usa il proprio formato per i tasti ssh. Con la maggior parte delle varianti di Linux e BSD che ho visto, devi solo dare un'occhiata ~/.ssh/known_hosts. Di solito ssh da una macchina Linux e quindi copio questo file su una macchina Windows. Quindi uso qualcosa di simile a

jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts");

Supponendo di aver inserito il file C:\Users\cabbottsul mio computer Windows. Se non si ha accesso a una macchina Linux, provare http://www.cygwin.com/

Forse qualcun altro può suggerire un'altra alternativa a Windows. Trovo che il modo di putty di gestire le chiavi SSH memorizzandole nel registro in un formato non standard sia fastidioso da estrarre.


Su windows usando h ssh in cygwin(devi scaricare il opensslpacchetto e le dipendenze) sono stato in grado di scaricare ~/.ssh/known_hosts. Grazie a @CharityAbbott.
Taringamberini,

10

Fornire la chiave rsa pubblica dell'host: -

String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/";

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));

1
Non ha funzionato per me con la versione 0.1.50 di jsch (sempre ottenuto un NPE in jsch) ma con la versione 0.1.53 più recente funziona.
Udo,

questo (String.getBytes ()) fornirà un array di byte di caratteri codificati unicode, quando il codice Jsch (Util.byte2str ()) prevede la codifica UTF-8?
ricco p

7

Puoi anche semplicemente fare

session.setConfig("StrictHostKeyChecking", "no");

Non è sicuro ed è una soluzione alternativa non adatta all'ambiente live poiché disabiliterà il controllo delle chiavi host conosciute a livello globale.


2
Mentre questo codice può aiutare a rispondere alla domanda, solo le risposte al codice non sono di alta qualità. Una risposta migliore spiegherebbe cosa fa il codice, dire dove inserirlo, spiegare perché questo approccio è stato adottato e collegarsi alla documentazione pertinente.
Stephen Ostermiller,

6

Puoi anche eseguire il seguente codice. È testato e funzionante.

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;

public class SFTPTest {

    public static void main(String[] args) {
        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession("username", "mywebsite.com", 22); //default port is 22
            UserInfo ui = new MyUserInfo();
            session.setUserInfo(ui);
            session.setPassword("123456".getBytes());
            session.connect();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            System.out.println("Connected");
        } catch (JSchException e) {
            e.printStackTrace(System.out);
        } catch (Exception e){
            e.printStackTrace(System.out);
        } finally{
            session.disconnect();
            System.out.println("Disconnected");
        }
    }

    public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {

        @Override
        public String getPassphrase() {
            return null;
        }
        @Override
        public String getPassword() {
            return null;
        }
        @Override
        public boolean promptPassphrase(String arg0) {
            return false;
        }
        @Override
        public boolean promptPassword(String arg0) {
            return false;
        }
        @Override
        public boolean promptYesNo(String arg0) {
            return false;
        }
        @Override
        public void showMessage(String arg0) {
        }
        @Override
        public String[] promptKeyboardInteractive(String arg0, String arg1,
                String arg2, String[] arg3, boolean[] arg4) {
            return null;
        }
    }
}

Si prega di sostituire i valori appropriati.


Sì, l'avevo aggiunto come riferimento. Lo rimuoverò. Grazie.
Vishnu Prasad Kallummel,

1
questo ha creato una sorta di strani problemi di autenticazione durante la connessione a determinati server SSH che offrono un metodo di autenticazione interattivo da tastiera. L'ho usato per anni per sbarazzarmi della cosa chiave e poi sono stato bruciato proprio oggi con un determinato server. Perché non ho fornito la PW tramite getPassword () ma direttamente all'oggetto Session. Tienilo a mente. Non lo userei più.
Marc

1

Basta sostituire "user", "pass", "SSHD_IP". E crea un file chiamato known_hosts.txt con il contenuto del ~ / .ssh / known_hosts del server. Otterrai una conchiglia.

public class Known_Hosts {
public static void main(String[] arg) {
    try {
        JSch jsch = new JSch();
        jsch.setKnownHosts("known_hosts.txt");
        Session session = jsch.getSession("user", "SSHD_IP", 22);
        session.setPassword("pass");
        session.connect();
        Channel channel = session.openChannel("shell");
        channel.setInputStream(System.in);
        channel.setOutputStream(System.out);
        channel.connect();
    } catch (Exception e) {
        System.out.println(e);
    }
  }
}

No, non funziona per me. Allo stesso modo, la risposta di Eric Leschinski / Rakesh Acharya fallisce se commento config.put("StrictHostKeyChecking", "no"); Una ssh -vconnessione manuale rivela che il .ssh/known_hostsfile contiene la chiave ( ecdsa-sha2-nistp256) ma il codice fa questo: com.jcraft.jsch.JSchException: UnknownHostKey: 131.132.x.x. RSA key fingerprint is c2:... at com.jcraft.jsch.Session.checkHost(Session.java:805) at com.jcraft.jsch.Session.connect(Session.java:345)
Urhixidur,

È passato un po 'di tempo, quello che proverei a fare, è usare la versione della libreria JSCH disponibile il 13 giugno 2013, perché le cose probabilmente sono cambiate nella libreria da allora
dalvarezmartinez1

1

l'impostazione dell'host noto è meglio dell'impostazione del valore di stampa fingure.

Quando si imposta l'host noto, provare a ssh manualmente (la prima volta prima dell'esecuzione dell'applicazione) dalla casella in cui viene eseguita l'applicazione.


1

Ho perso molto tempo su questo stupido problema e penso che il messaggio sia corretto "non c'è l'host nel file a cui sto accedendo" ma puoi avere più di un file know_host in giro sul tuo sistema (come esempio sto usando mobaXterm e lo mantiene nella directory di installazione montando la home da quel root).

Se si verifica: funziona dalla riga di comando ma non dall'applicazione provare ad accedere al server remoto con ssh e verificare con l'opzione -v dettagliata quale file è attualmente utilizzato un esempio seguente:

 ssh -v git@gitlab.com
 OpenSSH_6.2p2, OpenSSL 1.0.1g 7 Apr 2014
 debug1: Reading configuration data /etc/ssh_config
 debug1: Connecting to gitlab.com [104.210.2.228] port 22.
 debug1: Connection established.
 debug1: identity file /home/mobaxterm/.ssh/id_rsa type 1
 debug1: identity file /home/mobaxterm/.ssh/id_rsa-cert type -1
 debug1: identity file /home/mobaxterm/.ssh/id_dsa type -1
 debug1: identity file /home/mobaxterm/.ssh/id_dsa-cert type -1
 debug1: identity file /home/mobaxterm/.ssh/id_ecdsa type -1
 debug1: identity file /home/mobaxterm/.ssh/id_ecdsa-cert type -1
 debug1: Enabling compatibility mode for protocol 2.0
 debug1: Local version string SSH-2.0-OpenSSH_6.2
 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2p2      Ubuntu-4ubuntu2.1
 debug1: match: OpenSSH_7.2p2 Ubuntu-4ubuntu2.1 pat OpenSSH*
 debug1: SSH2_MSG_KEXINIT sent
 debug1: SSH2_MSG_KEXINIT received
 debug1: kex: server->client aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com
 debug1: kex: client->server aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com
 debug1: sending SSH2_MSG_KEX_ECDH_INIT
 debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
 debug1: Server host key: RSA b6:03:0e:39:97:9e:d0:e7:24:ce:a3:77:3e:01:42:09
 debug1: Host 'gitlab.com' is known and matches the RSA host key.
 debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19
 debug1: ssh_rsa_verify: signature correct

come puoi vedere la chiave è stata trovata in:

debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19

e non nella mia finestra di Windows sotto C: \ Users \ my_local_user \ .ssh, li ho semplicemente uniti e allineati per risolvere il problema.

Spero che questo aiuti qualcuno in futuro


0

Qualcuno è stato in grado di risolvere questo problema? Sto usando Jscp per scp i file usando l'autenticazione con chiave pubblica (non voglio usare l'autenticazione con password). L'aiuto sarà apprezzato !!!

Questa voce dello stackover riguarda il controllo della chiave host e non esiste alcuna relazione con l'autenticazione della chiave pubblica.

Per quanto riguarda l'autenticazione con chiave pubblica, prova il seguente esempio con la tua chiave privata semplice (non crittografata),


0
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession("user", "hostname", 22); // default
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.setPassword("password".getBytes());
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
System.out.println("Connected");
} catch (JSchException e) {
e.printStackTrace(System.out);
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
session.disconnect();
System.out.println("Disconnected");
}
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.