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ไฟล์ของฉันเพื่อแก้ไขข้อผิดพลาดด้านบนเมื่อฉันไม่สามารถเข้าถึงแก้ไขซอร์สโค้ดได้
Adam Rofer

คุณทำอะไรกับ. ssh / config ฉันมีข้อผิดพลาดเดียวกัน
เบอร์นาร์ด Igiri

19
สิ่งนี้ไม่ปลอดภัยและไม่ควรเลือกเป็นคำตอบที่ถูกต้องสำหรับหลักการนั้น ตัวเลือก setKnownHosts () และ setFingerPrint () เป็นวิธีการทำเช่นนี้โดยไม่ต้องคำนึงถึงส่วนที่สำคัญของกระบวนการ ssh แก้ไข: จากประสบการณ์ของฉัน # 1 ไม่ทำงานจากภายในสภาพแวดล้อม IDE บางอย่างเช่น Eclipse
Rondo

1
มันทำงานให้ฉันภายในอุปราคา ... สิ่งที่ฉันต้องการในสภาพแวดล้อมการทดสอบ ....
ProfVersaggi

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เกี่ยวกับ prefering SHA_RSA แทนการใช้ในท้องถิ่นHostKeyAlgorithmsการตั้งค่าแม้ว่าพวกเขาดูเหมือนจะไม่มากเกินไปความกระตือรือร้นในการแก้ไขปัญหาของพวกเขาข้อบกพร่อง


1
เราอยู่ในกรณีที่คล้ายกันด้วยecdsa-sha2-nistp384และวิธีการแก้ปัญหาของคุณทำงานได้ดีมาก ดังนั้นเพื่อopenssh-KeyScan คู่มือssh-keyscan -t rsa,ecdsa example.org >> known_hostsและความจำเป็นของเราเราทำงาน
taringamberini

1
ฉันมีปัญหาดังกล่าว แต่ข้อยกเว้นคือJSchException: ปฏิเสธ HostKey:แทนที่จะเป็นJSchException: UnknownHostKey (นี่อาจช่วยผู้ใช้รายอื่น)
bdulac

ฉันต้องเพิ่มไฟล์ setKnownHosts เพิ่มเติมตามที่เสนอโดย @krishnakumarp
Wolfgang Fahl

34

ความเสี่ยงด้านความปลอดภัยคือการหลีกเลี่ยงการตรวจสอบคีย์โฮสต์

JSch ใช้ส่วนต่อประสาน HostKeyRepository และคลาส KnownHosts การนำไปใช้งานเริ่มต้นเพื่อจัดการสิ่งนี้ คุณสามารถจัดเตรียมการติดตั้งสำรองที่อนุญาตให้ใช้คีย์เฉพาะได้ หรือคุณสามารถเก็บกุญแจที่คุณต้องการอนุญาตในไฟล์ในรูปแบบ known_hostsและการโทร

jsch.setKnownHosts(knownHostsFileName);

หรือด้วยรหัสสาธารณะสตริงดังต่อไปนี้

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

ดูJavadocสำหรับรายละเอียดเพิ่มเติม

นี่จะเป็นทางออกที่ปลอดภัยยิ่งขึ้น

Jsch เปิดแหล่งที่มาและคุณสามารถดาวน์โหลดแหล่งที่มาจากที่นี่ ในโฟลเดอร์ตัวอย่างค้นหา KnownHosts.java เพื่อทราบรายละเอียดเพิ่มเติม


16

ขึ้นอยู่กับโปรแกรมที่คุณใช้สำหรับ ssh วิธีการรับคีย์ที่เหมาะสมอาจแตกต่างกันไป สีโป๊ว (เป็นที่นิยมกับ Windows) ใช้รูปแบบของตนเองสำหรับคีย์ ssh กับสายพันธุ์มากที่สุดของลินุกซ์และ 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 ที่ใช้ ssh ใน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
Udo

จะ (String.getBytes ()) นี้จะให้อาร์เรย์ไบต์ของอักขระที่เข้ารหัส Unicode เมื่อรหัส Jsch (Util.byte2str ()) คาดว่าการเข้ารหัส UTF-8?
รวย

7

คุณสามารถทำได้ง่ายๆ

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

ไม่ปลอดภัยและเป็นวิธีแก้ปัญหาที่ไม่เหมาะกับสภาพแวดล้อมแบบสดเนื่องจากจะปิดใช้งานการตรวจสอบโฮสต์โฮสต์ที่รู้จักกันทั่วโลก


2
ในขณะที่รหัสนี้อาจช่วยตอบคำถามรหัสเพียงคำตอบไม่ได้คุณภาพสูง คำตอบที่ดีกว่านี้จะอธิบายว่าโค้ดทำอะไรบอกตำแหน่งที่จะแทรกอธิบายว่าเหตุใดจึงใช้วิธีนี้และเชื่อมโยงไปยังเอกสารที่เกี่ยวข้อง
สตีเฟ่น Ostermiller

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

โปรดแทนที่ค่าที่เหมาะสม


ใช่ฉันได้เพิ่มมันไว้สำหรับการอ้างอิงของฉัน ฉันจะลบมัน ขอบคุณ
พระนารายณ์ Prasad Kallummel

1
สิ่งนี้สร้างปัญหาการรับรองความถูกต้องแปลก ๆ บางอย่างเมื่อเชื่อมต่อกับเซิร์ฟเวอร์ SSH บางตัวที่เสนอวิธีการรับรองความถูกต้องด้วยคีย์บอร์ด ฉันใช้มันเป็นเวลาหลายปีเพื่อกำจัดสิ่งที่สำคัญแล้วก็เผาในวันนี้กับเซิร์ฟเวอร์บางอย่าง เพราะฉันไม่ได้จัดหา PW ผ่าน getPassword () แต่โดยตรงไปยังวัตถุเซสชัน เก็บไว้ในใจ ฉันจะไม่ใช้มันอีกต่อไป
Marc

1

เพียงแทนที่ "ผู้ใช้", "ผ่าน", "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);
    }
  }
}

Nope ไม่ได้ผลสำหรับฉัน ในทำนองเดียวกันคำตอบของ Eric Leschinski / Rakesh Acharya ล้มเหลวหากฉันแสดงความคิดเห็น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

การตั้งค่าโฮสต์ที่รู้จักดีกว่าการตั้งค่าการพิมพ์ด้วยนิ้ว

เมื่อคุณตั้งค่าโฮสต์ที่รู้จักให้ลอง 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 เพื่อ scp ไฟล์โดยใช้การตรวจสอบกุญแจสาธารณะ (ฉันไม่ต้องการใช้การพิสูจน์ตัวตนด้วยรหัสผ่าน) ความช่วยเหลือจะได้รับการชื่นชม !!!

รายการ 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");
}
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.