com.jcraft.jsch.JSchException: UnknownHostKey
Question
Je suis en train 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 peux pas trouver 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);
}
}
}
La solution
Je voudrais soit:
- Essayez de
ssh
de la ligne de commande et d'accepter la clé publique (l'hôte sera ajouté à~/.ssh/known_hosts
et tout devrait alors fonctionner correctement à partir jsch) -OR - -
Configurer JSch de ne pas utiliser « StrictHostKeyChecking » (ce qui introduit insécurités et ne doit être utilisé à des fins de test), en utilisant le code suivant:
java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config);
Option n ° 1 (en ajoutant l'hôte au fichier ~/.ssh/known_hosts
) a ma préférence.
Autres conseils
Il est un risque de sécurité pour éviter la vérification de la clé d'hôte.
JSch utilise l'interface HostKeyRepository et sa classe implémentation par défaut de knownhosts pour gérer cela. Vous pouvez fournir une implémentation alternative qui permet des clés spécifiques mettant en œuvre HostKeyRepository. Ou vous pouvez garder les clés que vous souhaitez autoriser dans un fichier dans le répertoire Format known_hosts et appel
jsch.setKnownHosts(knownHostsFileName);
Ou avec une clé publique chaîne comme ci-dessous.
String knownHostPublicKey = "mysite.com ecdsa-sha2-nistp256 AAAAE............/3vplY";
jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
voir ici . Dans le dossier des exemples, recherchez KnownHosts.java de connaître plus de détails.
Alors que la question moi-même a été répondu en général, j'ai trouvé qu'il ya un cas quand même existant known_hosts entrée ne vous aide pas. Cela se produit lorsqu'un serveur SSH envoie les empreintes digitales ECDSA et par conséquent, vous aurez une entrée comme ceci:
|1|+HASH=|HASH= ecdsa-sha2-nistp256 FINGERPRINT=
Le problème est que JSch préfère SHA_RSA et lors de la connexion, il va essayer de comparer les empreintes digitales SHA-RSA, ce qui se traduira par une erreur de « hôte inconnu ».
Pour résoudre ce problème il suffit de lancer:
$ ssh-keyscan -H -t rsa example.org >> known_hosts
ou se plaindre à Jcraft sur SHA_RSA au lieu de préférant l'utilisation local HostKeyAlgorithms réglage, bien qu'ils ne semblent pas être trop désireux pour corriger les bogues de leur .
Selon le programme que vous utilisez pour ssh, la façon 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 je l'ai vu, il vous suffit de regarder dans ~/.ssh/known_hosts
. Je ssh habituellement d'une machine Linux puis copier ce fichier sur une machine Windows. Puis-je utiliser quelque chose de similaire à
jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts");
En supposant que je l'ai placé le fichier dans C:\Users\cabbott
sur ma machine Windows. Si vous ne disposez pas d'un accès à une machine Linux, essayez http://www.cygwin.com/
Peut-être que quelqu'un d'autre peut proposer une autre alternative de Windows. Je trouve la manière de mastic de gérer les clés SSH en les stockant dans le registre dans un format non standard gênant pour extraire.
Alimenter la clé rsa publique de l'hôte: -
String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/";
session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
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 remplacer les valeurs appropriées.
Vous pouvez aussi tout simplement faire
session.setConfig("StrictHostKeyChecking", "no");
Il est pas sûr et est une solution de contournement ne convient pas pour l'environnement en direct car il désactivera les clés d'hôte mondialement connu de contrôle.
Juste remplacer "utilisateur", "pass", "SSHD_IP". Et créer un fichier appelé known_hosts.txt avec le contenu de ~ / .ssh / known_hosts les 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);
}
}
}
J'ai perdu beaucoup de temps sur cette question stupide, et je pense que le message est tout à fait raison « il n'y a pas l'hôte dans le fichier que je suis accès », mais vous pouvez avoir plus d'un fichier know_host autour de votre système ( comme par exemple j'utilise MobaXterm et le garder propre à l'intérieur du répertoire d'installation de montage de la maison de cette racine).
Si vous rencontrez: il fonctionne de la ligne de commande, mais pas former l'application essayer d'accéder à votre serveur distant avec ssh et vérifiez avec l'option -v verbeux 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 voir la clé a été trouvée dans:
debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19
et non pas dans mes fenêtres à la maison sous C:.. \ Users \ my_local_user \ ssh, je les simplement fusionnées et alignées pour résoudre le problème
quelqu'un Hope this aide à l'avenir
Quelqu'un at-il été en mesure de résoudre ce problème? J'utilise JSPCP à scp fichiers en utilisant la clé publique l'authentification (je ne veux pas utiliser l'authentification par mot de passe). Aide sera appréciée !!!
Cette entrée stackoverflow est sur le contrôle-clé hôte, et il n'y a aucune relation avec l'authentification par clé publique.
En ce qui concerne l'authentification par clé publique, essayez le suivant échantillon avec votre simple (non chiffrée) clé privée,
paramètre d'hôte connue est mieux que la mise en valeur d'impression fingure.
Lorsque vous définissez hôte connu, essayez de ssh manuellement (première fois, avant l'application est exécutée) dans la zone l'application est exécutée.
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");
}
}