com.jcraft.jsch.JSchException: UnknownHostKey

179

Estou tentando usar o 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 como verificar a chave do host na documentação do 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);
        } 
    }
}
Alex
fonte
Tente desligar o sshd em seu host * nix e inicie um único thread em primeiro plano: / usr / sbin / sshd -d Isso fornecerá muitas informações de depuração no lado sshd.
Todo mundo @AmmSokun conseguiu resolver esse problema. Veja as respostas.
bmargulies

Respostas:

226

Eu iria:

  1. Tente sshna linha de comando e aceite a chave pública (o host será adicionado ~/.ssh/known_hostse tudo deverá funcionar bem no Jsch) -OR-
  2. Configure o JSch para não usar "StrictHostKeyChecking" (isso introduz inseguranças e deve ser usado apenas para fins de teste), usando o seguinte código:

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

A opção 1 (adicionar o host ao ~/.ssh/known_hostsarquivo) tem minha preferência.

Pascal Thivent
fonte
37
JSch#setConfig("StrictHostKeyChecking", "no")fará o mesmo trabalho, mas em apenas uma linha
yegor256 31/03
2
Nota lateral: Eu usei esse feedback para configurar meu ~/.ssh/configarquivo de corrigir o erro acima quando eu não tinha acesso a modificar o código fonte
Adam Rofer
O que você fez com o seu .ssh / config? Estou tendo o mesmo erro.
Bernard Igiri 11/08/2012
19
Isso é inseguro e realmente não deveria ter sido selecionado como a resposta certa para esse princípio. As opções setKnownHosts () e setFingerPrint () são a maneira de fazer isso sem ignorar um aspecto importante do processo ssh. Edit: na minha experiência, o número 1 não funciona em alguns ambientes IDE como o Eclipse.
Rondo
1
Ele fez o trabalho para mim dentro do eclipse ... apenas o que eu precisava em um ambiente de teste ....
ProfVersaggi
46

Embora a pergunta tenha sido respondida em geral, percebi que há um caso em que mesmo a entrada existente de known_hosts não ajuda. Isso acontece quando um servidor SSH envia uma impressão digital ECDSA e, como resultado, você terá uma entrada como esta:

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

O problema é que o JSch prefere o SHA_RSA e, ao conectá-lo, tentará comparar a impressão digital do SHA-RSA, o que resultará em erro sobre "host desconhecido".

Para corrigir isso, execute:

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

ou reclame com a Jcraft sobre preferir o SHA_RSA em vez de usar a configuração local HostKeyAlgorithms , embora eles não pareçam estar muito ansiosos para corrigir seus erros .

kszatan
fonte
1
Estamos em um caso semelhante, com ecdsa-sha2-nistp384, e sua solução funciona muito bem. De acordo com o manual openssh-keyscan , e nossa necessidade, corremos ssh-keyscan -t rsa,ecdsa example.org >> known_hosts.
Taringamberini
1
Eu tive um problema tão grande, mas a excepção foi JSchException: rejeitar HostKey: em vez de JSchException: UnknownHostKey (isso pode ajudar alguns outros usuários)
bdulac
Eu tive que adicionar adicionalmente o arquivo setKnownHosts como proposto por @krishnakumarp
Wolfgang Fahl
34

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

JSch usa a interface HostKeyRepository e sua classe KnownHosts de implementação padrão para gerenciar isso. Você pode fornecer uma implementação alternativa que permita chaves específicas implementando HostKeyRepository. Ou você pode manter as chaves que deseja permitir em um arquivo no formato known_hosts e chamar

jsch.setKnownHosts(knownHostsFileName);

Ou com uma chave pública String como abaixo.

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

veja Javadoc para mais detalhes.

Essa seria uma solução mais segura.

Jsch é de código aberto e você pode fazer o download do código aqui . Na pasta de exemplos, procure KnownHosts.java para saber mais detalhes.

krishnakumarp
fonte
16

Dependendo do programa usado para o ssh, a maneira de obter a chave correta pode variar. O Putty (popular no Windows) usa seu próprio formato para chaves ssh. Com a maioria das variantes de Linux e BSD que eu já vi, é só procurar ~/.ssh/known_hosts. Eu normalmente ssh de uma máquina Linux e copio esse arquivo para uma máquina Windows. Então eu uso algo semelhante a

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

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

Talvez alguém possa sugerir outra alternativa do Windows. Acho a maneira do putty de manipular chaves SSH armazenando-as no registro em um formato não-padrão, incômodo de extrair.

Charity Leschinski
fonte
No Windows, usando h ssh in cygwin(você precisa fazer o download do opensslpacote e das dependências), consegui fazer o download ~/.ssh/known_hosts. Graças a @CharityAbbott.
taringamberini
10

Forneça a chave rsa pública do host: -

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

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
Mark Beer
fonte
1
Não funcionou para mim com a versão 0.1.50 do jsch (sempre obtive um NPE no jsch), mas com a versão mais recente 0.1.53 está funcionando.
Udo #
isso (String.getBytes ()) fornece uma matriz de bytes de caracteres codificados em unicode, quando o código Jsch (Util.byte2str ()) espera a codificação UTF-8?
rich p
7

Você também pode simplesmente fazer

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

Não é seguro e é uma solução alternativa não adequada para o ambiente ativo, pois desativará a verificação de chaves de host conhecidas globalmente.

Amaury D
fonte
2
Embora esse código possa ajudar a responder à pergunta, as respostas somente de código não são de alta qualidade. Uma resposta melhor explicaria o que o código faz, diria onde inseri-lo, explicaria por que essa abordagem foi adotada e criaria um link para a documentação relevante.
Stephen Ostermiller
6

Você também pode executar o seguinte código. É 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;
        }
    }
}

Substitua os valores apropriados.

Vishnu Prasad Kallummel
fonte
Sim, eu adicionei isso para minha referência. Eu vou remover isso. Obrigado.
Vishnu Prasad Kallummel
1
isso criou algum tipo de problema de autenticação estranho ao se conectar a determinados servidores SSH, oferecendo o método de autenticação interativa por teclado. Usei-o durante anos para me livrar da coisa-chave e depois me queimei apenas hoje com um determinado servidor. Porque eu não forneci o PW via getPassword (), mas diretamente ao objeto Session. Tenha isso em mente. Eu não usaria mais.
Marc
1

Basta substituir "user", "pass", "SSHD_IP". E crie um arquivo chamado known_hosts.txt com o conteúdo do servidor ~ / .ssh / known_hosts. Você receberá uma concha.

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);
    }
  }
}
dalvarezmartinez1
fonte
Não, não funciona para mim. Da mesma forma, a resposta Eric Leschinski / Rakesh do Acharya falha se eu comentar config.put("StrictHostKeyChecking", "no"); Um manual de ssh -vligação revela o .ssh/known_hostsarquivo contém a chave ( ecdsa-sha2-nistp256), mas o código faz isso: 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
Já faz algum tempo, o que eu tente fazer, é usar a versão jsch biblioteca disponível em 13 de junho de 2013, porque as coisas provavelmente mudou na biblioteca desde então
dalvarezmartinez1
1

A configuração do host conhecido é melhor do que a definição do valor da impressão digital.

Ao definir o host conhecido, tente ssh manualmente (primeira vez, antes da execução do aplicativo) na caixa em que o aplicativo é executado.

sreenath V
fonte
1

Perdi muito tempo com esse problema estúpido e acho que a mensagem está certa: "não há o host no arquivo que estou acessando", mas você pode ter mais do que um arquivo know_host no seu sistema (por exemplo, i estou usando o mobaXterm e ele se mantém dentro do diretório de instalação que monta a casa a partir dessa raiz).

Se você estiver enfrentando: ele está trabalhando na linha de comando, mas não no aplicativo, tente acessar o servidor remoto com ssh e verifique com a opção -v verbose qual arquivo está sendo usado atualmente no 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 na casa do meu Windows em C: \ Users \ my_local_user \ .ssh, simplesmente os mesclei e alinhei para resolver o problema.

Espero que isso ajude alguém no futuro

loreii
fonte
0

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

Essa entrada stackoverflow é sobre a verificação de chave do host e não há relação com a autenticação de chave pública.

Quanto à autenticação de chave pública, tente o seguinte exemplo com sua chave privada simples (não codificada),

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