com.jcraft.jsch.Исключение JSchException:Неизвестный хост-ключ

StackOverflow https://stackoverflow.com/questions/2003419

  •  18-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь использовать 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) -ИЛИ-
  2. Настройте JSch так, чтобы он не использовал «StrictHostKeyChecking» (это создает небезопасность и должно использоваться только в целях тестирования), используя следующий код:

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

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

Другие советы

Избегать проверки ключа хоста представляет собой угрозу безопасности.

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

jsch.setKnownHosts(knownHostsFileName);

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

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

видеть Javadoc Больше подробностей.

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

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

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

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

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

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

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

или пожаловаться Джкрафт о предпочтении SHA_RSA вместо использования локального Алгоритмы HostKey настройки, хотя они, кажется, не слишком жаждущий исправить их ошибки.

В зависимости от того, какую программу вы используете для 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-ключей в Putty путем сохранения их в реестре в нестандартном формате утомляет извлечение.

Укажите открытый ключ RSA хоста: -

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

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

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

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

Пожалуйста, замените соответствующие значения.

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

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

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

Просто замените «пользователь», «пароль», «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);
    }
  }
}

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

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

 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

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

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

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

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

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

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

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

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

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

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");
}
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top