提问者:小点点

尝试使用java在远程unix服务器上执行脚本时出错,产生[重复]


我正在尝试在远程服务器上运行kafka shell脚本,以检索使用者组和偏移量的列表。这是一种替代方法,而不是通过jvm使用jmx[http://openjdk.java.net/tools/svc/jconsole/jconsole}. 我正在使用jsch并得到未知的主机密钥错误。

其他发布的问题有潜在的解决方案,但我不确定如何以及检索哪个主机密钥。我可以在服务器上看到 3 个主机密钥服务器文件,但不确定要复制哪个文件。

下面是代码和错误:

    JSch jsch = new JSch();
    String keyString = "";
    //byte [] key = Base64.getDecoder().decode("b6:83:60:7c:4a:98:00:ef:b9:4a:ba:b6:80:39:d6:42");
    //HostKey hostkey = new HostKey(host,key);
    //jsch.getHostKeyRepository().add(hostkey, null);

    jsch.setKnownHosts(new FileInputStream("C:\\Users\\.ssh\\host"));

    Session session = jsch.getSession(uname, host, 22);
    Properties config = new Properties();
    //config.put("StrickHostKeyChecking","no");
    session.setConfig(config);
    session.setPassword(pword);

    session.connect();

这是session.connect()行产生的错误:

com.jcraft.jsch.JSchException: UnknownHostKey: 192.168.xx.1xx. RSA key 
         fingerprint is b6:83:60:7c:4a:98:00:ef:b9:4a:ba:b6:80:39:d6:42

编辑:

已尝试对从服务器复制到客户端的 ssh_host_rsa_key.pub 文件进行以下更改。添加了以下内容:

    JSch jsch = new JSch();
    String keyString = "";
    //byte [] key = 
     Base64.getDecoder().
         decode("b6:83:60:7c:4a:98:00:ef:b9:4a:ba:b6:80:39:d6:42");
    //HostKey hostkey = new HostKey(host,key);
    //jsch.getHostKeyRepository().add(hostkey, null);
     jsch.setKnownHosts("C:\\Users\\.ssh\\ssh_host_rsa_key.pub");

    Session session = jsch.getSession(uname, host, 22);
    Properties config = new Properties();
    session.setConfig(config);
    session.setPassword(pword);
    session.connect();

创建相同的 JSchException: UnknownHostKey...RSA密钥是fingerporint。然后尝试以下方式实际读取文件内容:

     String knownHostPublicKey = "";
     String readLine = "";
     BufferedReader fr = new BufferedReader(new 
            FileReader("C:\\Users\\.ssh\\ssh_host_rsa_key.pub"));
    while((readLine = fr.readLine()) != null){
        knownHostPublicKey = readLine;
        System.out.println(knownHostPublicKey);
    }

  //  jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));

    session.connect();

共1个答案

匿名用户

SSH协议(与其他加密协议不同)对客户端到服务器和服务器到客户端进行身份验证。

客户端(您的代码)使用密钥(这通常是自动化系统的首选)或用户名/密码对进行身份验证。您已经弄清楚了这部分。

服务器端(远程系统)使用主机密钥对自身进行身份验证,客户端可以使用该密钥来确认它正在与预期的服务器通信。理论上,如果你是偏执狂,你会通过一些带外安全机制将主机密钥的公钥部分(或至少是其指纹)从服务器传输到客户端。实际上,大多数人只是在第一次连接到服务器时确认主机密钥,然后将其存储在客户端的known_hosts文件中。(也就是说,大多数人使用“首次使用时信任”策略。

当您第一次使用自动化流程连接到新服务器时,问题就出现在这里。如何确定要连接的服务器是您想要的服务器?如果网络上有一个邪恶的人在对你进行中间人攻击,你会给这个人登录真实服务器所需的用户名和密码,而你的代码永远不会更明智。

解决这个问题主要有两种方法。首先,您可以从远程服务器手动收集主机密钥,然后将它保存到已知的hosts文件中,以供自动化流程使用。这很简单,只要您可以手动连接:只需使用命令行SSH客户机连接到服务器,在提示符下确认新的主机密钥,然后复制< code>~/。ssh/known_hosts文件(或等效文件)从用户的主目录复制到自动化流程使用的位置。

根据错误消息,您需要的主机密钥是RSA密钥(带有指纹b6:83:60:7c:4a:98:00:ef:b9:4a:ba:b6:80:39:d6:42)。假设远程Unix服务器使用的是OpenSSH或兼容的实现,RSA主机密钥的默认位置是/etc/ssh/ssh_host_RSA_key,尽管可以通过etc/ssh/shd_config中的指令更改此路径。您要放入known_hosts文件中的值是与此私钥对应的公钥——通常将存储在/etc/ssh/ssh_host_rsa_key.pub中。同样,获得正确格式的最简单方法是,只需连接其他SSH客户端,确认主机密钥,然后检查获得的known_hosts文件。

一个不太安全的选择是告诉你的客户直接忽略主机密钥,并抱最好的希望。(也许你足够信任你的网络,所以你不担心中间的人,尽管如果你如此信任它,那么你可能也不需要SSH。)这就是StrictHostKeyChecking=no设置的作用,我注意到它是在注释中设置的,尽管拼写错误。