com.jcraft.jsch.JSchException: UnknownHostKey

179

J'essaye d' utiliser Jsch pour établir une connexion SSH en Java. Mon code produit l'exception suivante:

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

Je ne trouve pas comment vérifier la clé d'hôte dans la documentation Jsch. J'ai inclus mon code ci-dessous.

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);
        } 
    }
}
Alex
la source
Essayez d'arrêter sshd sur votre hôte * nix, et démarrez un seul thread au premier plan: / usr / sbin / sshd -d Cela vous donnera beaucoup d'informations de débogage du côté sshd.
@AmmSokun tout le monde a pu résoudre ce problème. Voyez les réponses.
bmargulies

Réponses:

226

Je voudrais soit:

  1. Essayez sshdepuis la ligne de commande et acceptez la clé publique (l'hôte sera ajouté ~/.ssh/known_hostset tout devrait alors fonctionner correctement à partir de Jsch) -OU-
  2. Configurez JSch pour ne pas utiliser "StrictHostKeyChecking" (cela introduit des insécurités et ne doit être utilisé qu'à des fins de test), en utilisant le code suivant:

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

L'option n ° 1 (ajouter l'hôte au ~/.ssh/known_hostsfichier) a ma préférence.

Pascal Thivent
la source
37
JSch#setConfig("StrictHostKeyChecking", "no")fera le même travail, mais en une seule ligne
yegor256
2
Note latérale: j'ai utilisé ces commentaires pour configurer mon ~/.ssh/configfichier afin de corriger l'erreur ci-dessus lorsque je n'avais pas accès pour modifier le code source
Adam Rofer
Qu'avez-vous fait à votre .ssh / config? J'ai la même erreur.
Bernard Igiri
19
Ceci n'est pas sûr et n'aurait vraiment pas dû être choisi comme la bonne réponse sur ce principe. Les options setKnownHosts () et setFingerPrint () sont le moyen de le faire sans ignorer un aspect important du processus ssh. Edit: d'après mon expérience, # 1 ne fonctionne pas à partir de certains environnements IDE comme Eclipse.
Rondo
1
Il a fait le travail pour moi à l'intérieur d'Eclipse ... juste ce dont j'avais besoin dans un environnement de test ....
ProfVersaggi
46

Bien que la question ait reçu une réponse en général, je me suis rendu compte qu'il y a un cas où même l' entrée known_hosts existante n'aide pas. Cela se produit lorsqu'un serveur SSH envoie une empreinte digitale ECDSA et, par conséquent, vous aurez une entrée comme celle-ci:

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

Le problème est que JSch préfère SHA_RSA et lors de la connexion, il essaiera de comparer l'empreinte digitale SHA-RSA, ce qui entraînera une erreur sur "l'hôte inconnu".

Pour résoudre ce problème, exécutez simplement:

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

ou se plaindre à Jcraft de préférer SHA_RSA au lieu d'utiliser le paramètre HostKeyAlgorithms local , bien qu'ils ne semblent pas trop désireux de corriger leurs bogues .

kszatan
la source
1
Nous sommes dans un cas similaire, avec ecdsa-sha2-nistp384, et votre solution fonctionne très bien. Conformément au manuel openssh-keyscan , et à nos besoins, nous exécutonsssh-keyscan -t rsa,ecdsa example.org >> known_hosts .
taringamberini
1
J'ai eu un tel problème, mais l'exception était JSchException: rejeter HostKey: au lieu de JSchException: UnknownHostKey (cela pourrait aider certains autres utilisateurs)
bdulac
J'ai dû en plus ajouter le fichier setKnownHosts comme proposé par @krishnakumarp
Wolfgang Fahl
34

C'est un risque de sécurité d'éviter la vérification des clés de l'hôte.

JSch utilise l'interface HostKeyRepository et sa classe d'implémentation par défaut KnownHosts pour gérer cela. Vous pouvez fournir une autre implémentation qui autorise des clés spécifiques en implémentant HostKeyRepository. Ou vous pouvez conserver les clés que vous souhaitez autoriser dans un fichier au format known_hosts et appeler

jsch.setKnownHosts(knownHostsFileName);

Ou avec une chaîne de clé publique comme ci-dessous.

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

voir Javadoc pour plus de détails.

Ce serait une solution plus sûre.

Jsch est open source et vous pouvez télécharger la source à partir d' ici . Dans le dossier des exemples, recherchez KnownHosts.java pour en savoir plus.

krishnakumarp
la source
16

Selon le programme que vous utilisez pour ssh, la manière d'obtenir la clé appropriée peut varier. Putty (populaire avec Windows) utilise son propre format pour les clés ssh. Avec la plupart des variantes de Linux et BSD que j'ai vues, il vous suffit de regarder ~/.ssh/known_hosts. Je ssh généralement depuis une machine Linux, puis je copie ce fichier sur une machine Windows. Ensuite, j'utilise quelque chose de similaire à

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

En supposant que j'ai placé le fichier C:\Users\cabbottsur ma machine Windows. Si vous n'avez pas accès à une machine Linux, essayez http://www.cygwin.com/

Peut-être que quelqu'un d'autre peut suggérer une autre alternative Windows. Je trouve la manière de putty de gérer les clés SSH en les stockant dans le registre dans un format non standard gênant à extraire.

Charité Leschinski
la source
Sur Windows en utilisanth ssh in cygwin(vous devez télécharger le opensslpackage et les dépendances), j'ai pu télécharger ~/.ssh/known_hosts. Merci à @CharityAbbott.
taringamberini
10

Fournissez la clé publique rsa de l'hôte: -

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
Mark Beer
la source
1
Cela n'a pas fonctionné pour moi avec la version jsch 0.1.50 (toujours un NPE dans jsch) mais avec la dernière version 0.1.53 cela fonctionne.
Udo
Est-ce que cela (String.getBytes ()) fournira un tableau d'octets de caractères codés en Unicode, lorsque le code Jsch (Util.byte2str ()) attend un codage UTF-8?
riche p
7

Vous pouvez aussi simplement faire

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

Ce n'est pas sécurisé et c'est une solution de contournement qui ne convient pas à l'environnement en direct car elle désactivera la vérification des clés d'hôte mondialement connues.

Amaury D
la source
2
Bien que ce code puisse aider à répondre à la question, les réponses de code uniquement ne sont pas de haute qualité. Une meilleure réponse expliquerait ce que fait le code, indiquerait où l'insérer, expliquerait pourquoi cette approche a été adoptée et établirait un lien vers la documentation pertinente.
Stephen Ostermiller
6

Vous pouvez également exécuter le code suivant. Il est testé et fonctionne.

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;
        }
    }
}

Veuillez remplacer les valeurs appropriées.

Vishnu Prasad Kallummel
la source
Oui, j'avais ajouté cela pour ma référence. Je vais supprimer cela. Merci.
Vishnu Prasad Kallummel
1
cela a créé une sorte de problèmes d'authentification étranges lors de la connexion à certains serveurs SSH offrant une méthode d'authentification interactive au clavier. Je l'ai utilisé pendant des années pour me débarrasser de la clé, puis je me suis brûlé aujourd'hui avec un certain serveur. Parce que je n'ai pas fourni le PW via getPassword () mais directement à l'objet Session. Garde cela à l'esprit. Je ne l'utiliserais plus.
Marc
1

Remplacez simplement "utilisateur", "passer", "SSHD_IP". Et créez un fichier appelé known_hosts.txt avec le contenu de ~ / .ssh / known_hosts du serveur. Vous obtiendrez une coquille.

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);
    }
  }
}
dalvarezmartinez1
la source
Nope ne fonctionne pas pour moi. De même, la réponse d'Eric Leschinski / Rakesh Acharya échoue si je commente config.put("StrictHostKeyChecking", "no"); Une ssh -vconnexion manuelle révèle que le .ssh/known_hostsfichier contient la clé ( ecdsa-sha2-nistp256) mais le code le fait: 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
Cela fait un certain temps, ce que j'essaierais de faire, c'est d'utiliser la version de la bibliothèque JSCH disponible le 13 juin 2013, car les choses ont probablement changé dans la bibliothèque depuis lors
dalvarezmartinez1
1

il est préférable de définir un hôte connu que de définir une valeur d’impression digitale.

Lorsque vous définissez l'hôte connu, essayez de ssh manuellement (la toute première fois, avant que l'application ne s'exécute) à partir de la boîte dans laquelle l'application s'exécute.

sreenath V
la source
1

J'ai perdu beaucoup de temps sur ce problème stupide, et je pense que le message est tout à fait exact "il n'y a pas l'hôte dans le fichier auquel j'accède" mais vous pouvez avoir plus d'un fichier know_host sur votre système (par exemple, je J'utilise mobaXterm et il le garde dans le répertoire d'installation en montant le home à partir de cette racine).

Si vous rencontrez: cela fonctionne à partir de la ligne de commande mais pas depuis l'application, essayez d'accéder à votre serveur distant avec ssh et vérifiez avec l'option verbeuse -v quel fichier est actuellement utilisé, un exemple suivant:

 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

comme vous pouvez le voir, la clé a été trouvée dans:

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

et pas dans ma maison Windows sous C: \ Users \ my_local_user \ .ssh, je les ai simplement fusionnés et alignés pour résoudre le problème.

J'espère que cela aidera quelqu'un à l'avenir

loreii
la source
0

Quelqu'un a-t-il pu résoudre ce problème? J'utilise Jscp pour les fichiers scp en utilisant l'authentification par clé publique (je ne veux pas utiliser l'authentification par mot de passe). L'aide sera appréciée !!!

Cette entrée de stackoverflow concerne la vérification de la clé d'hôte et il n'y a aucune relation avec l'authentification par clé publique.

Quant à l'authentification par clé publique, essayez l' exemple suivant avec votre clé privée simple (non chiffrée),

ymnk
la source
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");
}
}
Rakesh Acharya
la source