com.jcraft.jsch.JSchException: UnknownHostKey

179

Я пытаюсь использовать 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);
        } 
    }
}
Alex
источник
Попробуйте выключить sshd на вашем * nix хосте и запустить один поток на переднем плане: / usr / sbin / sshd -d. Это даст вам много информации для отладки со стороны sshd.
@ AmmSokun каждый смог решить эту проблему. Смотрите ответы.
bmargulies

Ответы:

226

Я бы либо:

  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файл) имеет мои предпочтения.

Паскаль Тивент
источник
37
JSch#setConfig("StrictHostKeyChecking", "no")будет выполнять ту же работу, но только в одной строке
yegor256
2
Примечание: я использовал этот отзыв, чтобы настроить свой ~/.ssh/configфайл для исправления вышеуказанной ошибки, когда у меня не было доступа к изменению исходного кода
Адам Рофер,
Что вы сделали со своим .ssh / config? У меня та же ошибка.
Бернард Игири
19
Это небезопасно и действительно не должно быть выбрано как правильный ответ по этому принципу. Параметры setKnownHosts () и setFingerPrint () - это способ сделать это, не игнорируя важный аспект процесса ssh. Изменить: по моему опыту, # 1 не работает в некоторых средах IDE, таких как Eclipse.
Рондо
1
Это
помогло
46

Хотя на этот вопрос был дан общий ответ, я обнаружил, что есть случай, когда даже существующая запись 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 , хотя они, похоже, не слишком хотят исправлять свои ошибки .

kszatan
источник
1
Мы в аналогичном случае с ecdsa-sha2-nistp384вами, и ваше решение работает очень хорошо. Соответственно руководству openssh-keyscan и нам нужно, мы запускаем ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
Тарингамберини
1
У меня была такая проблема, но исключением было JSchException: отклонить HostKey: вместо JSchException: UnknownHostKey (это могло бы помочь некоторым другим пользователям)
bdulac
Мне пришлось дополнительно добавить файл setKnownHosts, предложенный @krishnakumarp
Вольфганг Фаль
34

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

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

jsch.setKnownHosts(knownHostsFileName);

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

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

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

Это было бы более безопасным решением.

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

krishnakumarp
источник
16

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

Благотворительность Лещинского
источник
В Windows, используя h ssh cygwin(вы должны загрузить opensslпакет и зависимости), я смог скачать ~/.ssh/known_hosts. Благодаря @CharityAbbott.
Тарингамберини
10

Предоставить открытый ключ RSA хоста: -

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
Марк Пиво
источник
1
Не работал для меня с jsch версии 0.1.50 (всегда есть NPE в jsch), но с новейшей версией 0.1.53 работает.
Удо
будет ли это (String.getBytes ()) предоставлять байтовый массив символов в кодировке Юникод, когда код Jsch (Util.byte2str ()) ожидает кодирования UTF-8?
Рич Р
7

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

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

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

Amaury D
источник
2
Хотя этот код может помочь ответить на вопрос, ответы только на код не высокого качества. Лучший ответ объяснит, что делает код, скажет, куда его вставить, объяснит, почему был использован этот подход, и даст ссылку на соответствующую документацию.
Стивен Остермиллер
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;
        }
    }
}

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

Вишну Прасад Каллуммель
источник
Да, я добавил это для справки. Я удалю это. Спасибо.
Вишну Прасад Каллуммель
1
это создало какие-то странные проблемы с аутентификацией при подключении к определенным серверам SSH, предлагающим интерактивный метод аутентификации с помощью клавиатуры Я годами использовал его, чтобы избавиться от ключевой вещи, а затем сгорел только сегодня с определенным сервером. Потому что я не предоставлял PW через getPassword (), но напрямую к объекту Session. Запомни. Я бы больше не использовал его.
Марк
1

Просто замените «user», «pass», «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);
    }
  }
}
dalvarezmartinez1
источник
Нету не работает для меня. Кроме того , ответ Эрик Лещинский / Ракеш Ачарья терпит неудачу , если я закомментировать config.put("StrictHostKeyChecking", "no"); ручное ssh -vподключение раскрывает .ssh/known_hostsфайл действительно содержит ключ ( ecdsa-sha2-nistp256) , но код делает это: 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
Некоторое время я пытался использовать библиотечную версию JSCH, доступную 13 июня 2013 года, потому что с тех пор в библиотеке, вероятно, произошли изменения
dalvarezmartinez1
1

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

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

скринат V
источник
1

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

Если у вас возникли проблемы: он работает из командной строки, но не из приложения, попробуйте получить доступ к удаленному серверу с помощью ssh и проверьте с опцией verbose -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, я просто слил их и выровнял для решения проблемы.

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

loreii
источник
0

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

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

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

ymnk
источник
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");
}
}
Ракеш Ачарья
источник