com.jcraft.jsch.JSchException: UnknownHostKey

177

Ich versuche, mit Jsch eine SSH-Verbindung in Java herzustellen. Mein Code erzeugt die folgende Ausnahme:

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

Ich kann in der Jsch-Dokumentation nicht finden, wie der Hostschlüssel überprüft werden kann. Ich habe meinen Code unten angegeben.

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
quelle
Versuchen Sie, sshd auf Ihrem * nix-Host herunterzufahren und einen einzelnen Thread im Vordergrund zu starten: / usr / sbin / sshd -d Dies gibt Ihnen viele Debugging-Informationen von der sshd-Seite.
@AmmSokun Jeder konnte dieses Problem lösen. Siehe die Antworten.
Bmargulies

Antworten:

225

Ich würde entweder:

  1. Versuchen Sie es sshüber die Befehlszeile und akzeptieren Sie den öffentlichen Schlüssel (der Host wird hinzugefügt ~/.ssh/known_hostsund alles sollte dann von Jsch aus einwandfrei funktionieren) -OR-
  2. Konfigurieren Sie JSch so, dass "StrictHostKeyChecking" nicht verwendet wird (dies führt zu Unsicherheiten und sollte nur zu Testzwecken verwendet werden). Verwenden Sie dazu den folgenden Code:

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

Option 1 (Hinzufügen des Hosts zur ~/.ssh/known_hostsDatei) hat meine Präferenz.

Pascal Thivent
quelle
37
JSch#setConfig("StrictHostKeyChecking", "no")wird den gleichen Job machen, aber in nur einer Zeile
yegor256
2
Randnotiz: Ich habe dieses Feedback verwendet, um meine ~/.ssh/configDatei so zu konfigurieren , dass der obige Fehler
behoben
Was hast du mit deiner .ssh / config gemacht? Ich habe den gleichen Fehler.
Bernard Igiri
19
Dies ist unsicher und hätte eigentlich nicht als die richtige Antwort auf dieses Prinzip ausgewählt werden sollen. Mit den Optionen setKnownHosts () und setFingerPrint () können Sie dies tun, ohne einen wichtigen Aspekt des ssh-Prozesses zu ignorieren. Bearbeiten: Nach meiner Erfahrung funktioniert # 1 in einigen IDE-Umgebungen wie Eclipse nicht.
Rondo
1
Es hat den Job für mich innerhalb von Eclipse gemacht ... genau das, was ich in einer Testumgebung brauchte ...
ProfVersaggi
46

Obwohl die Frage im Allgemeinen beantwortet wurde, habe ich festgestellt, dass es einen Fall gibt, in dem selbst der vorhandene Eintrag " unknown_hosts" nicht hilft. Dies geschieht, wenn ein SSH-Server einen ECDSA-Fingerabdruck sendet und Sie daher einen Eintrag wie den folgenden haben:

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

Das Problem ist, dass JSch SHA_RSA bevorzugt und beim Verbinden versucht, den SHA-RSA-Fingerabdruck zu vergleichen, was zu einem Fehler bezüglich "unbekannter Host" führt.

Um dies zu beheben, führen Sie einfach Folgendes aus:

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

oder beschweren Sie sich bei Jcraft darüber , dass Sie SHA_RSA bevorzugen, anstatt die lokale HostKeyAlgorithms- Einstellung zu verwenden, obwohl sie nicht zu eifrig zu sein scheinen, ihre Fehler zu beheben .

kszatan
quelle
1
Wir sind in einem ähnlichen Fall mit ecdsa-sha2-nistp384und Ihre Lösung funktioniert sehr gut. Entsprechend dem Handbuch openssh-keyscan und unserem Bedarf laufen wir ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
Taringamberini
1
Ich hatte ein solches Problem, aber die Ausnahme war JSchException: HostKey ablehnen: anstelle von JSchException: UnknownHostKey (dies könnte einigen anderen Benutzern helfen)
bdulac
Ich musste zusätzlich die setKnownHosts-Datei hinzufügen, wie von @krishnakumarp
Wolfgang Fahl
34

Es ist ein Sicherheitsrisiko, die Überprüfung des Hostschlüssels zu vermeiden.

JSch verwendet die HostKeyRepository-Schnittstelle und die KnownHosts-Klasse für die Standardimplementierung, um dies zu verwalten. Sie können eine alternative Implementierung bereitstellen, die bestimmte Schlüssel zulässt, indem Sie HostKeyRepository implementieren. Oder Sie können die Schlüssel, die Sie zulassen möchten, in einer Datei im Format unknown_hosts behalten und aufrufen

jsch.setKnownHosts(knownHostsFileName);

Oder mit einem öffentlichen Schlüssel String wie unten.

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

Weitere Informationen finden Sie in Javadoc .

Dies wäre eine sicherere Lösung.

Jsch ist Open Source und Sie können die Quelle hier herunterladen . Suchen Sie im Beispielordner nach KnownHosts.java, um weitere Details zu erfahren.

krishnakumarp
quelle
16

Je nachdem, welches Programm Sie für ssh verwenden, kann der Weg zum richtigen Schlüssel variieren. Putty (beliebt bei Windows) verwendet ein eigenes Format für SSH-Schlüssel. Bei den meisten Varianten von Linux und BSD, die ich gesehen habe, muss man nur nachsehen ~/.ssh/known_hosts. Normalerweise ssh ich von einem Linux-Computer und kopiere diese Datei dann auf einen Windows-Computer. Dann benutze ich etwas ähnliches wie

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

Angenommen, ich habe die Datei C:\Users\cabbottauf meinem Windows-Computer abgelegt . Wenn Sie keinen Zugriff auf einen Linux-Computer haben, versuchen Sie es unter http://www.cygwin.com/.

Vielleicht kann jemand anderes eine andere Windows-Alternative vorschlagen. Ich finde die Art und Weise, wie Putty mit SSH-Schlüsseln umgeht, indem ich sie in einem nicht standardmäßigen Format in der Registrierung speichere, mühsam zu extrahieren.

Wohltätigkeit Leschinski
quelle
Unter Windows mit h ssh in cygwin(Sie müssen das opensslPaket und die Abhängigkeiten herunterladen ) konnte ich herunterladen ~/.ssh/known_hosts. Vielen Dank an @CharityAbbott.
Taringamberini
10

Geben Sie den öffentlichen RSA-Schlüssel des Hosts an: -

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
Mark Beer
quelle
1
Hat bei mir mit jsch Version 0.1.50 nicht funktioniert (habe immer eine NPE in jsch), aber mit der neuesten Version 0.1.53 funktioniert es.
Udo
Wird dies (String.getBytes ()) ein Byte-Array von Unicode-codierten Zeichen bereitstellen, wenn der Jsch-Code (Util.byte2str ()) eine UTF-8-Codierung erwartet?
reich p
7

Sie können auch einfach tun

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

Es ist nicht sicher und eine Problemumgehung, die nicht für Live-Umgebungen geeignet ist, da dadurch die weltweit bekannte Überprüfung von Hostschlüsseln deaktiviert wird.

Amaury D.
quelle
2
Während dieser Code bei der Beantwortung der Frage hilfreich sein kann, sind nur Code-Antworten nicht von hoher Qualität. Eine bessere Antwort würde erklären, was der Code tut, wo er eingefügt werden soll, warum dieser Ansatz gewählt wurde und auf relevante Dokumentationen verweisen.
Stephen Ostermiller
6

Sie können auch den folgenden Code ausführen. Es ist getestet und funktioniert.

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

Bitte ersetzen Sie die entsprechenden Werte.

Vishnu Prasad Kallummel
quelle
Ja, das hatte ich als Referenz hinzugefügt. Ich werde das entfernen. Vielen Dank.
Vishnu Prasad Kallummel
1
Dies führte zu seltsamen Authentifizierungsproblemen bei der Verbindung mit bestimmten SSH-Servern, die eine tastaturinteraktive Authentifizierungsmethode anbieten. Ich habe es jahrelang benutzt, um die Schlüsselsache loszuwerden und wurde dann erst heute mit einem bestimmten Server verbrannt. Weil ich das PW nicht über getPassword (), sondern direkt an das Session-Objekt geliefert habe. Vergiss das nicht. Ich würde es nicht mehr benutzen.
Marc
1

Ersetzen Sie einfach "Benutzer", "Pass", "SSHD_IP". Erstellen Sie eine Datei mit dem Namen unknown_hosts.txt mit dem Inhalt der ~ / .ssh / unknown_hosts des Servers. Sie erhalten eine Muschel.

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
quelle
Nein, das funktioniert bei mir nicht. In ähnlicher Weise schlägt die Antwort von Eric Leschinski / Rakesh Acharya fehl, wenn ich auskommentiere. config.put("StrictHostKeyChecking", "no"); Eine manuelle ssh -vVerbindung zeigt, dass die .ssh/known_hostsDatei den Schlüssel ( ecdsa-sha2-nistp256) enthält, aber der Code tut dies: 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
Es ist einige Zeit her, ich würde versuchen, die am 13. Juni 2013 verfügbare JSCH-Bibliotheksversion zu verwenden, da sich die Dinge seitdem wahrscheinlich in der Bibliothek geändert haben
dalvarezmartinez1
1

Das Einstellen des bekannten Hosts ist besser als das Einstellen des Fingerabdruckwerts.

Wenn Sie einen bekannten Host festlegen, versuchen Sie, ssh (zum ersten Mal, bevor die Anwendung ausgeführt wird) manuell über das Feld zu aktivieren, in dem die Anwendung ausgeführt wird.

Sreenath V.
quelle
1

Ich habe viel Zeit mit diesem dummen Problem verloren, und ich denke, die Nachricht ist ganz richtig "Es gibt nicht den Host in der Datei, auf die ich zugreife", aber Sie können mehr als eine know_host-Datei auf Ihrem System haben (als Beispiel i Ich verwende mobaXterm und es bleibt im Installationsverzeichnis, in dem sich das Home von diesem Stamm aus befindet.

Wenn Folgendes auftritt: Es funktioniert über die Befehlszeile, aber nicht über die Anwendung. Versuchen Sie, mit ssh auf Ihren Remote-Server zuzugreifen, und überprüfen Sie mit der Option verbose -v, welche Datei derzeit verwendet wird.

 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

Wie Sie sehen können, wurde der Schlüssel gefunden in:

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

und nicht in meinem Windows-Home unter C: \ Users \ my_local_user \ .ssh, ich habe sie einfach zusammengeführt und ausgerichtet, um das Problem zu lösen.

Hoffe das hilft jemandem in Zukunft

loreii
quelle
0

Hat jemand dieses Problem lösen können? Ich verwende Jscp, um Dateien mithilfe der Authentifizierung mit öffentlichem Schlüssel zu scpen (ich möchte keine Kennwortauthentifizierung verwenden). Hilfe wird geschätzt !!!

Bei diesem Stackoverflow-Eintrag geht es um die Überprüfung des Hostschlüssels, und es besteht keine Beziehung zur Authentifizierung mit öffentlichem Schlüssel.

Versuchen Sie für die Authentifizierung mit öffentlichem Schlüssel das folgende Beispiel mit Ihrem einfachen (nicht verschlüsselten) privaten Schlüssel:

ymnk
quelle
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
quelle