web-dev-qa-db-fra.com

com.jcraft.jsch.JSchException: UnknownHostKey

J'essaie 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é de l'hôte dans la documentation de 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);
        } 
    }
}
163
Alex

Je voudrais soit:

  1. Essayez de ssh à partir de la ligne de commande et acceptez la clé publique (l'hôte sera ajouté à ~/.ssh/known_hosts et tout devrait alors fonctionner correctement à partir de Jsch) - OU -
  2. Configurez JSch pour qu'il n'utilise pas "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 fichier ~/.ssh/known_hosts] a ma préférence.

205
Pascal Thivent

Éviter la vérification de la clé de l'hôte est un risque pour la sécurité.

JSch utilise l'interface HostKeyRepository et sa classe KnownHosts à implémentation par défaut 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 format et appeler

jsch.setKnownHosts(knownHostsFileName);

Ou avec une clé publique String 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écurisée.

Jsch est open source et vous pouvez télécharger le code source à partir de ici . Dans le dossier des exemples, recherchez KnownHosts.Java pour en savoir plus.

32
krishnakumarp

Bien que la question ait été résolue en général, je me suis trouvé qu'il y avait une entrée cas quand même une entrée existante known_hosts n'aidait pas. Cela se produit lorsqu'un serveur SSH envoie une empreinte ECDSA et que, 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 essayera de comparer les empreintes digitales SHA-RSA, ce qui entraînera une erreur concernant "hôte inconnu".

Pour résoudre ce problème, lancez 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 local HostKeyAlgorithms , bien qu'ils ne semblent pas trop trop impatient = corriger leurs bugs .

29
kszatan

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 suffit de regarder dans ~/.ssh/known_hosts. Je généralement ssh à partir d'une machine Linux, puis copiez 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 dans C:\Users\cabbott sur mon ordinateur 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 dont PuTTY gère les clés SSH en les stockant dans le registre dans un format non standard gênant à extraire.

16
Charity Leschinski

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

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
10
Mark Beer

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 à un environnement réel, car elle désactivera la vérification des clés d'hôte globalement connue.

6
Amaury D

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

S'il vous plaît substituer les valeurs appropriées.

6

J'ai perdu beaucoup de temps sur cette question stupide, et je pense que le message est tout à fait correct "il n'y a pas l'hôte dans le fichier auquel j'accède" mais vous pouvez avoir plus qu'un fichier know_Host sur votre système (par exemple J'utilise mobaXterm et conserve le sien dans le répertoire d'installation de la maison à partir de cette racine).

Si vous rencontrez ce problème: cela fonctionne à partir de la ligne de commande, mais pas de l'application, essayez d'accéder à votre serveur distant avec ssh et vérifiez avec l'option verbose -v quel fichier est actuellement utilisé, par exemple:

 ssh -v [email protected]
 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 [email protected] [email protected]
 debug1: kex: client->server aes128-ctr [email protected] [email protected]
 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:\Utilisateurs\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

1
loreii

Il suffit de remplacer "utilisateur", "pass", "SSHD_IP". Et créez un fichier appelé known_hosts.txt avec le contenu du serveur ~/.ssh/known_hosts. Vous obtiendrez un shell.

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);
    }
  }
}
1
dalvarezmartinez1

définir l'hôte connu est préférable à la définition de la valeur de l'empreinte digitale.

Lorsque vous définissez un hôte connu, essayez de ssh manuellement (la toute première fois, avant l'exécution de l'application) à partir de la zone d'exécution de l'application.

0
sreenath V

Quelqu'un at-il été capable de résoudre ce problème? J'utilise Jscp pour scp des fichiers 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 de la clé publique.

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

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