web-dev-qa-db-ja.com

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

私はどちらか:

  1. コマンドラインからsshを試して、公開鍵を受け入れます(ホストが~/.ssh/known_hostsに追加され、Jschですべてが正常に動作するはずです)-OR-
  2. 次のコードを使用して、「StrictHostKeyChecking」を使用しないようにJSchを構成します(これにより、不安定さが生じ、テスト目的でのみ使用する必要があります)。

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

オプション#1(ホストを~/.ssh/known_hostsファイルに追加する)には私の好みがあります。

202
Pascal Thivent

ホストキーチェックを回避することはセキュリティ上のリスクです。

JSchは、HostKeyRepositoryインターフェースとそのデフォルト実装KnownHostsクラスを使用してこれを管理します。 HostKeyRepositoryを実装することにより、特定のキーを許可する代替実装を提供できます。または、許可するキーを known_hosts format のファイルに保持して呼び出します

jsch.setKnownHosts(knownHostsFileName);

または、以下の公開キー文字列を使用します。

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

詳細については、 Javadoc を参照してください。

これは、より安全なソリューションです。

Jschはオープンソースであり、 here からソースをダウンロードできます。サンプルフォルダーで、KnownHosts.Javaを探して詳細を確認します。

32
krishnakumarp

一般的には質問に回答しましたが、既存のknown_hostsエントリでも役に立たない場合は case があることに気付きました。これは、SSHサーバーがECDSAフィンガープリントを送信すると発生し、その結果、次のようなエントリがあります。

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

問題は、JSchprefersSHA_RSAであり、接続中にSHA-RSAフィンガープリントを比較しようとし、「不明なホスト」に関するエラーが発生することです。

これを修正するには、単に次を実行します:

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

または Jcraft ローカルHostKeyAlgorithms設定を使用する代わりにSHA_RSAを優先することについて文句を言いますが、あまりにも思えません eager = バグ を修正します。

28
kszatan

Sshに使用するプログラムに応じて、適切なキーを取得する方法は異なります。 PuTTY(Windowsで人気)は、sshキーに独自の形式を使用します。私が見たLinuxとBSDのほとんどのバリエーションでは、~/.ssh/known_hostsを調べるだけです。通常、Linuxマシンからsshを実行し、このファイルをWindowsマシンにコピーします。次に、私は似たようなものを使用します

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

WindowsマシンのC:\Users\cabbottにファイルを配置したと仮定します。 Linuxマシンにアクセスできない場合は、 http://www.cygwin.com/ を試してください。

他の誰かが別のWindowsの代替案を提案できるかもしれません。 SSHキーを非標準形式でレジストリに保存することで、SSHキーを処理するPuTTYの方法を見つけるのは面倒です。

16

ホストのRSA公開鍵を提供します:

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
10
Mark Beer

次のコードも実行できます。テスト済みで動作しています。

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

適切な値に置き換えてください。

また、単に行うことができます

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

これは安全ではなく、グローバルに既知のホストキーチェックを無効にするため、ライブ環境には適していません。

5
Amaury D

私はこの愚かな問題で多くの時間を失いました、そして、私はメッセージが「私がアクセスしているファイルにホストがありません」とかなり正しいと思いますが、あなたのシステム上に知っているホストファイル以上のものを持つことができます(例として「mobaXtermを使用しており、インストールディレクトリ内にそれを保持し、そのルートからホームをマウントします)。

あなたが経験している場合:それはコマンドラインから動作していますが、アプリケーションを形成せずにsshでリモートサーバーにアクセスし、現在使用されているファイルをverbose -vオプションで確認してください:

 ssh -v [email protected]
 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 [email protected] [email protected]
 debug1: kex: client->server aes128-ctr [email protected] [email protected]
 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

c:\ Users\my_local_user \。sshの下のWindowsホームではなく、単にそれらをマージし、問題を解決するために調整しました。

これが将来誰かを助けることを願っています

1
loreii

「user」、「pass」、「SSHD_IP」に置き換えるだけです。そして、サーバーの〜/ .ssh/known_hostsの内容を含むknown_hosts.txtというファイルを作成します。シェルが手に入ります。

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

既知のホストを設定することは、指紋値を設定するよりも優れています。

既知のホストを設定したら、アプリケーションが実行されるボックスから手動でsshを実行します(アプリケーションを実行する前に初めて)。

0
sreenath V

誰もこの問題を解決できましたか? Jscpを使用して、公開キー認証を使用してファイルをscpしています(パスワード認証を使用したくない)。助けていただければ幸いです!!!

このstackoverflowエントリはホストキーチェックに関するものであり、公開キー認証とは関係がありません。

公開鍵認証については、プレーン(非暗号化)秘密鍵で 次のサンプル を試してください。

0
ymnk
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");
}
}
0
Rakesh Acharya