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

Спробуйте вимкнути 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
Це небезпечно і насправді не слід було обрати як правильну відповідь за цим принципом. Параметри setKknownHosts () та setFingerPrint () - це спосіб зробити це, не ігноруючи важливий аспект процесу ssh. Редагувати: за моїм досвідом, номер 1 не працює в деяких середовищах IDE, таких як Eclipse.
Рондо

1
Це зробило роботу для мене в затемненні ... саме те, що мені було потрібно в тестовому середовищі ....
ProfVersaggi

46

Хоча в цілому відповіли на запитання, я зрозумів, що є випадок, коли навіть існуючі записи знаних_хостів не допомагають. Це трапляється, коли 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 , хоча вони, здається, не надто прагнуть виправити свої помилки .


1
Ми в подібному випадку ecdsa-sha2-nistp384, і ваше рішення працює дуже добре. Відповідно до інструкції до відкриття-клавішможна інструкція , і наша потреба, ми працюємо ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
taringamberini

1
У мене була така проблема, але виняток був JSchException: відхилити HostKey: замість JSchException: UnknownHostKey (це може допомогти іншим користувачам)
bdulac

Мені довелося додатково додати файл setK PoznaHosts, як запропонував @krishnakumarp
Вольфганг Фаль

34

Уникнути перевірки ключа хоста є ризиком для безпеки.

Для управління цим JSch використовує інтерфейс HostKeyRepository та його клас за відомою реалізацією за замовчуванням. Ви можете надати альтернативну реалізацію, яка дозволяє певні ключі, впровадивши HostKeyRepository. Або ви можете зберегти ключі, які ви хочете дозволити у файлі у відомому форматі_hosts та зателефонувати

jsch.setKnownHosts(knownHostsFileName);

Або з рядком відкритого ключа, як показано нижче.

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

див. Javadoc для отримання більш детальної інформації.

Це було б більш безпечним рішенням.

Jsch є відкритим кодом, і ви можете завантажити джерело звідси . У папці з прикладами шукайте KposedHosts.java, щоб дізнатися більше деталей.


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 usingh ssh in cygwin(ви повинні завантажити opensslпакет і залежність) я зміг завантажити ~/.ssh/known_hosts. Завдяки @CharityAbbott
taringamberini

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?
багатий p

7

Ви також можете просто зробити

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

Це не безпечно, і це спосіб вирішення не підходить для живого середовища, оскільки він відключить глобально відому хост-перевірку ключів.


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

Будь ласка, замініть відповідні значення.


Так, я додав це для довідки. Я зніму це. Дякую.
Vishnu Prasad Kallummel

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

Ніпе не працює для мене. Аналогічно, відповідь Еріка Лещинського / Ракеша Ачарія провалюється, якщо я коментую 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.

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


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, я просто об'єднав їх і вирівняв для вирішення проблеми.

Сподіваюся, це допоможе комусь у майбутньому


0

Хтось зміг вирішити цю проблему? Я використовую Jscp для сканування файлів за допомогою аутентифікації відкритого ключа (я не хочу використовувати автентифікацію пароля). Допомога буде оцінена !!!

Цей запис stackoverflow стосується перевірки ключа хоста, і немає ніякого відношення до аутентифікації відкритого ключа.

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


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");
}
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.