Com.jcraft.jsch.JSchException: UnknownHostKey

Я пытаюсь использовать Jsch, чтобы установить соединение SSH в Java. Мой код создает следующее исключение:

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

Я не могу найти, как проверить ключ хоста в документации Jsch. Я включил свой код ниже.

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

Ответ 1

Я хотел бы:

  • Попробуйте ssh из командной строки и принять открытый ключ (хост будет добавлен в ~/.ssh/known_hosts, и тогда все должно работать отлично от Jsch) -OR -
  • Настройте JSch, чтобы не использовать "StrictHostKeyChecking" (это вводит неуверенность и должно использоваться только для целей тестирования), используя следующий код:

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

Вариант №1 (добавление хоста к файлу ~/.ssh/known_hosts) имеет мои предпочтения.

Ответ 2

Это опасно для безопасности, чтобы избежать проверки ключа хоста.

JSch использует интерфейс HostKeyRepository и его класс KnownHosts по умолчанию для управления этим. Вы можете предоставить альтернативную реализацию, которая позволяет использовать определенные ключи, реализуя HostKeyRepository. Или вы можете сохранить ключи, которые вы хотите разрешить в файле known_hosts format, и вызвать

jsch.setKnownHosts(knownHostsFileName);

Или с открытым ключом Строка, как показано ниже.

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

см. Javadoc для более подробной информации.

Это будет более безопасное решение.

Jsch является открытым исходным кодом, и вы можете скачать исходный код из здесь. В папке примеров найдите KnownHosts.java, чтобы узнать подробности.

Ответ 3

Хотя на вопрос был дан ответ в целом, я обнаружил, что существует случай, когда даже существующая запись known_hosts не помогает. Это происходит, когда SSH-сервер отправляет отпечаток ECDSA, и в результате у вас будет такая запись:

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

Проблема в том, что JSch предпочитает SHA_RSA, и при подключении он попытается сравнить отпечаток SHA-RSA, что приведет к ошибке об "неизвестном хосте".

Чтобы исправить это, просто выполните:

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

или жалуются Jcraft на то, что предпочитают SHA_RSA вместо использования локальной настройки HostKeyAlgorithms, хотя они, похоже, не слишком стремятся исправить свои ошибки.

Ответ 4

В зависимости от того, какую программу вы используете для ssh, способ получить правильный ключ может отличаться. Putty (популярный в Windows) использует свой собственный формат для ssh-ключей. С большинством вариантов Linux и BSD, которые я видел, вам просто нужно посмотреть ~/.ssh/known_hosts. Я обычно ssh с Linux-машины, а затем копирую этот файл на компьютер с Windows. Затем я использую нечто похожее на

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

Предположим, что я разместил файл в C:\Users\cabbott на моей машине Windows. Если у вас нет доступа к машине Linux, попробуйте http://www.cygwin.com/

Возможно, кто-то другой может предложить другую альтернативу Windows. Я нахожу метод шпатлевки для обработки SSH-ключей, сохраняя их в реестре в нестандартном формате, который надо извлечь.

Ответ 5

Поставьте общедоступный ключ rsa хоста: -

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

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

Ответ 6

Вы также можете выполнить следующий код. Он протестирован и работает.

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

Подставьте соответствующие значения.

Ответ 7

Вы также можете просто сделать

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

Он не защищен, и это обходное решение не подходит для живой среды, так как оно отключит глобально известные проверки ключей хоста.

Ответ 8

Просто замените "пользователь", "проход", "SSHD_IP". И создайте файл с именем known_hosts.txt с содержимым сервера ~/.ssh/known_hosts. Вы получите оболочку.

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

Ответ 9

Я потерял много времени на эту глупую проблему, и я думаю, что сообщение совершенно правильно: "в файле, к которому я обращаюсь, нет хоста", но вы можете иметь больше, чем файл know_host в вашей системе ( в качестве примера я использую mobaXterm и сохраняю его в каталоге установки, устанавливая дом из этого корня).

Если вы столкнулись с этим: он работает из командной строки, но не формирует приложение, попробуйте получить доступ к удаленному серверу с помощью ssh и проверите с помощью verbose -v, в котором в настоящее время используется следующий файл:

 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]h.com
 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

как вы можете видеть, ключ найден в:

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

а не в моих окнах дома под C:\Users\ my_local_user \. ssh, я просто объединил их и выровнял для решения проблемы.

Надеюсь, что это поможет кому-то в будущем

Ответ 10

Добавьте этот хост к ~/.ssh/known_hosts.

Ответ 11

Кто-нибудь смог решить эту проблему? Я использую Jscp для scp файлов, используя открытый ключ аутентификация (я не хочу использовать аутентификацию по паролю). Помощь будет оценена.

Эта запись stackoverflow относится к проверке ключа хоста, и нет никакой связи с аутентификацией открытого ключа.

Что касается аутентификации с открытым ключом, попробуйте следующий пример с помощью обычного (не зашифрованного) закрытого ключа,

Ответ 12

настройка известного хоста лучше, чем установка значения печати пальца.

Когда вы устанавливаете известный хост, попробуйте вручную ssh (в первый раз, до запуска приложения) из окна, в котором запускается приложение.

Ответ 13

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