[java] com.jcraft.jsch.JSchException : UnknownHostKey

Jsch 를 사용 하여 Java에서 SSH 연결을 설정 하려고합니다 . 내 코드는 다음 예외를 생성합니다.

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. 다음 코드를 사용하여 “StrictHostKeyChecking”을 사용하지 않도록 JSch를 구성하십시오 (이로 인해 보안 문제가 발생하고 테스트 목적으로 만 사용해야 함).

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

옵션 # 1 (호스트를 ~/.ssh/known_hosts파일에 추가 )이 선호됩니다.


답변

이 질문은 일반적으로 답변되었지만 기존 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

또는 로컬 HostKeyAlgorithms 설정 을 사용하는 대신 SHA_RSA 를 선호 하는 것에 대해 Jcraft 에 불만을 제기 하지만 버그 를 수정 하기에는 너무 열망 하지는 않습니다 .


답변

호스트 키 검사를 피하는 것은 보안 위험입니다.

JSch는이를 관리하기 위해 HostKeyRepository 인터페이스와 기본 구현 KnownHosts 클래스를 사용합니다. HostKeyRepository를 구현하여 특정 키를 허용하는 대체 구현을 제공 할 수 있습니다. 또는 당신은에있는 파일에 허용하려는 키를 유지할 수 에서 known_hosts 형식 및 호출

jsch.setKnownHosts(knownHostsFileName);

또는 아래와 같이 공개 키 문자열을 사용하십시오.

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

자세한 내용 은 Javadoc 을 참조하십시오.

보다 안전한 솔루션입니다.

Jsch는 오픈 소스이며 여기 에서 소스를 다운로드 할 수 있습니다 . 예제 폴더에서 KnownHosts.java를 찾아 자세한 내용을 확인하십시오.


답변

ssh에 사용하는 프로그램에 따라 적절한 키를 얻는 방법이 다를 수 있습니다. 퍼티 (Windows에서 인기)는 ssh 키에 대해 자체 형식을 사용합니다. 내가 본 Linux와 BSD의 대부분의 변종은에서 찾아보아야한다 ~/.ssh/known_hosts. 나는 보통 리눅스 머신에서 ssh를 한 다음이 파일을 윈도우 머신으로 복사한다. 그런 다음 비슷한 것을 사용합니다.

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

파일을 C:\Users\cabbottWindows 컴퓨터에 저장했다고 가정 합니다. Linux 시스템에 액세스 할 수 없으면 http://www.cygwin.com/을 시도 하십시오

다른 사람이 다른 Windows 대안을 제안 할 수 있습니다. SSH 키를 레지스트리에 비표준 형식으로 저장하여 추출하는 귀찮은 퍼티 방식을 발견했습니다.


답변

호스트의 공개 rsa 키를 제공하십시오 :-

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

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


답변

간단하게 할 수도 있습니다

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

안전하지 않으며 전 세계적으로 알려진 호스트 키 검사를 비활성화하므로 라이브 환경에 적합하지 않은 해결 방법입니다.


답변

다음 코드를 실행할 수도 있습니다. 테스트되고 작동합니다.

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

적절한 값으로 대체하십시오.