com.jcraft.jsch.JSchException: UnknownhostKey


179

Tôi đang cố gắng sử dụng Jsch để thiết lập kết nối SSH trong Java. Mã của tôi tạo ra ngoại lệ sau:

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

Tôi không thể tìm thấy cách xác minh khóa máy chủ trong tài liệu Jsch. Tôi đã bao gồm mã của tôi dưới đây.

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

Cố gắng tắt sshd trên máy chủ * nix của bạn và bắt đầu một chuỗi ở phía trước: / usr / sbin / sshd -d Điều này sẽ cung cấp cho bạn rất nhiều thông tin gỡ lỗi từ phía sshd.

@AmmSokun mọi người đã có thể giải quyết vấn đề này. Xem câu trả lời.
bmargulies

Câu trả lời:


226

Tôi cũng sẽ:

  1. Cố gắng sshtừ dòng lệnh và chấp nhận khóa công khai (dẫn chương trình sẽ được thêm vào ~/.ssh/known_hostsvà tất cả mọi thứ nên sau đó làm việc tốt từ Jsch) -HOẶC-
  2. Định cấu hình JSch để không sử dụng "StricthostKeyChecking" (điều này giới thiệu sự không an toàn và chỉ nên được sử dụng cho mục đích thử nghiệm), sử dụng mã sau:

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

Tùy chọn # 1 (thêm máy chủ vào ~/.ssh/known_hoststệp) có tùy chọn của tôi.


37
JSch#setConfig("StrictHostKeyChecking", "no")sẽ làm cùng một công việc, nhưng chỉ trong một dòng
yegor256

2
Lưu ý bên lề: Tôi đã sử dụng phản hồi này để định cấu hình ~/.ssh/configtệp của mình để sửa lỗi trên khi tôi không có quyền truy cập để sửa đổi mã nguồn
Adam Rofer

Bạn đã làm gì với .ssh / config của bạn? Tôi có cùng một lỗi.
Bernard Igiri

19
Điều này là không an toàn và thực sự không nên được chọn là câu trả lời đúng theo nguyên tắc đó. Các tùy chọn setKnownhosts () và setFingerPrint () là cách để thực hiện việc này mà không bỏ qua một khía cạnh quan trọng của quy trình ssh. Chỉnh sửa: theo kinh nghiệm của tôi, # 1 không hoạt động trong một số môi trường IDE như Eclipse.
Rondo

1
Nó đã làm công việc cho tôi bên trong nhật thực ... chỉ là những gì tôi cần trong môi trường thử nghiệm ....
ProfVersaggi

46

Mặc dù câu hỏi đã được trả lời nói chung, tôi đã thấy rằng có một trường hợp khi ngay cả mục nhập know_hosts hiện tại không có ích. Điều này xảy ra khi máy chủ SSH gửi dấu vân tay ECDSA và kết quả là bạn sẽ có một mục như thế này:

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

Vấn đề là JSch thích SHA_RSA và trong khi kết nối, nó sẽ cố gắng so sánh dấu vân tay SHA-RSA, điều này sẽ dẫn đến lỗi về "máy chủ không xác định".

Để khắc phục điều này chỉ cần chạy:

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

hoặc phàn nàn với Jcraft về việc thích SHA_RSA thay vì sử dụng cài đặt HostKeyAlacticms , mặc dù họ dường như không quá háo hức để sửa lỗi .


1
Chúng tôi đang ở trong một trường hợp tương tự, với ecdsa-sha2-nistp384, và giải pháp của bạn hoạt động rất tốt. Theo hướng dẫn sử dụng openssh-keyscan và nhu cầu của chúng tôi, chúng tôi chạy ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
taringamberini

1
Tôi đã gặp một vấn đề như vậy, nhưng ngoại lệ là JSchException: từ chối HostKey: thay vì JSchException: UnknownhostKey (điều này có thể giúp một số người dùng khác)
bdulac

Tôi đã phải thêm tệp setKnownhosts theo đề xuất của @krishnakumarp
Wolfgang Fahl

34

Đó là một rủi ro bảo mật để tránh kiểm tra khóa máy chủ.

JSch sử dụng giao diện HostKeyRep repository và lớp Knownhosts triển khai mặc định của nó để quản lý việc này. Bạn có thể cung cấp một triển khai thay thế cho phép các khóa cụ thể bằng cách triển khai HostKeyRep repository. Hoặc bạn có thể giữ các khóa mà bạn muốn cho phép trong một tệp ở định dạng đã biết và gọi

jsch.setKnownHosts(knownHostsFileName);

Hoặc với một chuỗi khóa công khai như dưới đây.

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

xem Javadoc để biết thêm chi tiết.

Đây sẽ là một giải pháp an toàn hơn.

Jsch là mã nguồn mở và bạn có thể tải nguồn từ đây . Trong thư mục ví dụ, hãy tìm Knownhosts.java để biết thêm chi tiết.


16

Tùy thuộc vào chương trình bạn sử dụng cho ssh, cách để lấy khóa thích hợp có thể khác nhau. Putty (phổ biến với Windows) sử dụng định dạng riêng cho các phím ssh. Với hầu hết các biến thể của Linux và BSD mà tôi đã thấy, bạn chỉ cần nhìn vào ~/.ssh/known_hosts. Tôi thường ssh từ máy Linux và sau đó sao chép tệp này sang máy Windows. Sau đó, tôi sử dụng một cái gì đó tương tự như

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

Giả sử tôi đã đặt tệp C:\Users\cabbottvào máy Windows của mình. Nếu bạn không có quyền truy cập vào máy Linux, hãy thử http://www.cygwin.com/

Có lẽ ai đó khác có thể đề xuất một thay thế Windows khác. Tôi thấy cách xử lý các khóa SSH của putty bằng cách lưu trữ chúng trong sổ đăng ký ở định dạng không chuẩn gây khó chịu để giải nén.


Trên windows sử dụng ssh in cygwin(bạn phải tải xuống opensslgói và phụ thuộc) Tôi đã có thể tải xuống ~/.ssh/known_hosts. Cảm ơn @CharityAbbott.
taringamberini

10

Cung cấp khóa rsa công khai của máy chủ: -

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

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

1
Không hoạt động với tôi với phiên bản jsch 0.1.50 (luôn có NPE trong jsch) nhưng với phiên bản mới nhất 0.1.53 thì nó hoạt động.
Udo

điều này (String.getBytes ()) sẽ cung cấp một mảng byte các ký tự được mã hóa unicode, khi mã Jsch (Util.byte2str ()) mong đợi mã hóa UTF-8?
giàu p

7

Bạn cũng có thể đơn giản làm

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

Nó không an toàn và đó là một cách giải quyết không phù hợp với môi trường sống vì nó sẽ vô hiệu hóa việc kiểm tra khóa máy chủ được biết đến trên toàn cầu.


2
Mặc dù mã này có thể giúp trả lời câu hỏi, mã chỉ có câu trả lời không có chất lượng cao. Một câu trả lời tốt hơn sẽ giải thích những gì mã làm, cho biết nơi để chèn nó, giải thích lý do tại sao phương pháp này được thực hiện và liên kết đến các tài liệu liên quan.
Stephen Ostermiller

6

Bạn cũng có thể thực thi đoạn mã sau. Nó được thử nghiệm và làm việc.

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

Vui lòng thay thế các giá trị thích hợp.


Vâng, tôi đã thêm nó để tham khảo. Tôi sẽ loại bỏ điều đó. Cảm ơn.
Vishnu Prasad Kallummel

1
điều này tạo ra một số vấn đề xác thực kỳ lạ khi kết nối với một số Máy chủ SSH cung cấp phương thức xác thực tương tác bàn phím. Tôi đã sử dụng nó trong nhiều năm để loại bỏ Key key và sau đó bị đốt cháy ngay hôm nay với một máy chủ nhất định. Bởi vì tôi đã không cung cấp PW thông qua getPassword () nhưng trực tiếp cho đối tượng Phiên. Ghi nhớ nó trong tâm trí. Tôi sẽ không sử dụng nó nữa.
Marc

1

Chỉ cần thay thế "người dùng", "vượt qua", "SSHD_IP". Và tạo một tệp có tên là know_hosts.txt với nội dung của máy chủ ~ / .ssh / unknown_hosts. Bạn sẽ nhận được một vỏ.

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

Không, không làm việc cho tôi. Tương tự như vậy, câu trả lời Eric Leschinski / Rakesh Acharya thất bại nếu tôi nhận xét ra config.put("StrictHostKeyChecking", "no"); Sổ tay ssh -vkết nối cho thấy .ssh/known_hoststập tin có chứa chìa khóa ( ecdsa-sha2-nistp256) nhưng mã thực hiện điều này: 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

Đã có lúc, những gì tôi cố gắng làm, là sử dụng phiên bản thư viện JSCH có sẵn vào ngày 13 tháng 6 năm 2013, vì mọi thứ có thể đã thay đổi trong thư viện kể từ đó
dalvarezmartinez1

1

thiết lập máy chủ được biết là tốt hơn so với thiết lập giá trị in ngón tay.

Khi bạn đặt máy chủ đã biết, hãy thử ssh thủ công (lần đầu tiên, trước khi ứng dụng chạy) từ hộp ứng dụng chạy.


1

Tôi đã mất rất nhiều thời gian cho vấn đề ngu ngốc này và tôi nghĩ rằng thông báo này hoàn toàn đúng "không có máy chủ lưu trữ trong tệp tôi đang truy cập" nhưng bạn có thể có nhiều hơn một tệp know_host trên hệ thống của mình (ví dụ như tôi Tôi đang sử dụng mobaXterm và nó giữ nó trong thư mục cài đặt gắn nhà từ gốc đó).

Nếu bạn đang gặp phải: nó hoạt động từ dòng lệnh nhưng không tạo thành ứng dụng, hãy thử truy cập vào máy chủ từ xa của bạn bằng ssh và kiểm tra với tùy chọn verbose -v mà tập tin hiện đang sử dụng một ví dụ sau:

 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

như bạn có thể thấy khóa được tìm thấy trong:

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

và không có trong cửa sổ nhà của tôi dưới C: \ Users \ my_local_user \ .ssh, tôi chỉ cần hợp nhất chúng và căn chỉnh để giải quyết vấn đề.

Hy vọng điều này sẽ giúp ai đó trong tương lai


0

Có ai có thể giải quyết vấn đề này? Tôi đang sử dụng Jscp để scp các tập tin bằng xác thực khóa chung (tôi không muốn sử dụng xác thực mật khẩu). Trợ giúp sẽ được đánh giá cao !!!

Mục nhập stackoverflow này là về kiểm tra khóa máy chủ và không liên quan đến xác thực khóa chung.

Đối với xác thực khóa chung, hãy thử mẫu sau với khóa riêng (không được mã hóa) của bạn,


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");
}
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.