Pergunta

Eu estou tentando usar jsch para estabelecer uma conexão SSH em Java. Meu código produz a seguinte exceção:

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

Não consigo encontrar a forma de verificar a chave de host na documentação jsch. Eu incluí meu código abaixo.

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);
        } 
    }
}
Foi útil?

Solução

Eu faria qualquer um:

  1. Tente ssh a partir da linha de comando e aceitar a chave pública (o host será adicionado ao ~/.ssh/known_hosts e tudo deve, em seguida, bom trabalho de jsch) -OR -
  2. Configurar JSch para não usar "StrictHostKeyChecking" (isto introduz inseguranças e só deve ser utilizado para fins de teste), usando o seguinte código:

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

Opção # 1 (adicionando o host para o arquivo ~/.ssh/known_hosts) tem a minha preferência.

Outras dicas

É um risco de segurança para verificação de chave de host evitar.

JSch usa a interface HostKeyRepository e sua classe KnownHosts implementação padrão para gerenciar isso. Você pode fornecer uma implementação alternativa que permite teclas específicas através da implementação HostKeyRepository. Ou você pode manter as chaves que você deseja permitir em um arquivo no formato known_hosts e chamada

jsch.setKnownHosts(knownHostsFileName);

Ou com uma String chave pública como abaixo.

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

veja Javadoc para mais detalhes.

Esta seria uma solução mais segura.

jsch é open source e você pode baixar a fonte de aqui . Nos exemplos pasta, olhar para KnownHosts.java saber mais detalhes.

Enquanto a pergunta foi respondida, em geral, eu encontrei-me que há um caso quando ainda existente known_hosts entrada não ajuda. Isso acontece quando um servidor SSH envia ECDSA impressão digital e, como resultado, você terá uma entrada como esta:

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

O problema é que JSch prefere SHA_RSA e durante a conexão que irá tentar comparar SHA-RSA de impressões digitais, o que resultará com erro sobre "host desconhecido".

Para corrigir isso basta executar:

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

ou reclamar com Jcraft sobre preferindo SHA_RSA vez de usar o local, HostKeyAlgorithms definição, embora eles não parecem ser muito ansioso para corrigir os seus erros .

Dependendo do que programa que você usa para ssh, a maneira de obter a chave apropriada pode variar. Putty (popular com Windows) usa seu próprio formato de chaves SSH. Com a maioria das variantes do Linux e BSD que eu vi, você apenas tem que olhar em ~/.ssh/known_hosts. Eu costumo SSH a partir de uma máquina Linux e copie este arquivo para uma máquina Windows. Então eu uso algo semelhante a

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

Assumindo que eu coloquei o arquivo no C:\Users\cabbott na minha máquina Windows. Se você não tem acesso a uma máquina Linux, tente http://www.cygwin.com/

Talvez alguém pode sugerir uma outra alternativa do Windows. I encontrar maneira de lidar com as chaves SSH, armazenando-os no registro em um incômodo formato não-padrão ao extrato de massa de vidraceiro.

fornecer a chave RSA pública do host: -

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

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

Você também pode executar o seguinte código. Ele é testado e funcionando.

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

Por favor, substituir os valores apropriados.

Você também pode simplesmente fazer

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

Não é seguro e é uma solução alternativa não é adequado para o ambiente vivo como ele irá desativar globalmente conhecido acolhimento chaves correntes.

Apenas substituto "user", "pass", "SSHD_IP". E criar um arquivo chamado known_hosts.txt com o conteúdo do servidor ~ / .ssh / known_hosts. Você vai ter um shell.

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

Eu perdi muito tempo sobre esta questão estúpida, e eu acho que a mensagem é muito justo "não é o host no arquivo que estou acessando", mas você pode ter mais de um arquivo know_host em torno de seu sistema ( como exemplo, eu estou usando MobaXterm e manter a sua própria dentro do diretório de instalação de montagem da casa do que o root).

Se você está enfrentando: é trabalhar a partir de linha de comando, mas não formam a tentativa de aplicação para acesso ao servidor remoto com ssh e verificar com verbose opção -v qual arquivo é usado atualmente um exemplo a seguir:

 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

Como você pode ver a chave foi encontrada em:

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

e não no meu Windows Home em C:.. \ Users \ my_local_user \ ssh, eu simplesmente fundiu-los e alinhados para resolver a questão

Espero que isso ajuda alguém no futuro

Alguém já foi capaz de resolver este problema? Eu estou usando JSCP a arquivos scp usando a chave pública autenticação (Eu não quero usar autenticação por senha). Ajuda será apreciada !!!

Esta entrada stackoverflow é sobre a verificação de chave de host-, e não há nenhuma relação com a autenticação de chave pública.

Como para a autenticação de chave pública, tentar o seguinte amostra com sua planície chave (cifrada não) privada,

configuração de host conhecido é melhor do que a criação de valor fingure de impressão.

Quando você conjunto conhecido host, tentar ssh manualmente (primeira vez, antes do aplicativo é executado) a partir da caixa o aplicativo é executado.

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");
}
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top