2016-02-10 4 views
3

Я пытаюсь установить SSH-соединение через код Java, но получаю ниже исключения. Я проверил свое соединение с помощью инструментов Putty/Winscp, и он отлично работает. Проблема с моим Java кодом ...SSH-соединение с использованием Java

SEVERE: The Transport Protocol thread failed 
java.io.IOException: The socket is EOF 
    at com.sshtools.j2ssh.transport.TransportProtocolInputStream.readBufferedData(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolInputStream.readMessage(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolCommon.readMessage(Unknown Source) 
    at com.sshtools.j2ssh.transport.kex.DhGroup1Sha1.performClientExchange(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolClient.performKeyExchange(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolCommon.beginKeyExchange(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolCommon.onMsgKexInit(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolCommon.startBinaryPacketProtocol(Unknown Source) 
    at com.sshtools.j2ssh.transport.TransportProtocolCommon.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 

Ниже мой кусок кода Java, чтобы установить соединение

public class MySSHClient { 

    static SshClient ssh = null; 
    static SshConnectionProperties properties = null; 
    SessionChannelClient session = null; 

    private static void MySSHClient(String hostName, String userName, String passwd) 
    { 

    try 
    { 
     // Make a client connection 
     ssh = new SshClient(); 
     properties = new SshConnectionProperties(); 
     properties.setHost("192.168.1.175"); 

     // Connect to the host 
     ssh.connect(properties, new IgnoreHostKeyVerification()); 

     // Create a password authentication instance 
     PasswordAuthenticationClient pwd = new PasswordAuthenticationClient(); 

     pwd.setUsername("root"); 
     pwd.setPassword("123456"); 

     // Try the authentication 
     int result = ssh.authenticate(pwd); 

     // Evaluate the result 
     if (result==AuthenticationProtocolState.COMPLETE) { 

     System.out.println("Connection Authenticated"); 
     } 
    } 
    catch(Exception e) 
    { 
     System.out.println("Exception : " + e.getMessage()); 
    } 

    }//end of method. 


    public String execCmd(String cmd) 
    { 
    String theOutput = ""; 
    try 
    { 
     // The connection is authenticated we can now do some real work! 
     session = ssh.openSessionChannel(); 

     if (session.executeCommand(cmd)) 
     { 
     IOStreamConnector output = new IOStreamConnector(); 
     java.io.ByteArrayOutputStream bos = new 
     java.io.ByteArrayOutputStream(); 
     output.connect(session.getInputStream(), bos); 
     session.getState().waitForState(ChannelState.CHANNEL_CLOSED); 
     theOutput = bos.toString(); 
     } 
     //else 
     //throw Exception("Failed to execute command : " + cmd); 
     //System.out.println("Failed to execute command : " + cmd); 
    } 
    catch(Exception e) 
    { 
     System.out.println("Exception : " + e.getMessage()); 
    } 

    return theOutput; 
    } 

    public static void main(String[] args){ 
     MySSHClient(null, null, null); 
    } 
+1

попробуйте использовать http://www.jcraft.com/jsch/ –

+0

, если честно, исключение и размещенный код, похоже, не совпадают, также 'execCmd' не используется. –

+0

Что такое версия 'ssh' на хосте linux? –

ответ

1

Этой ошибка («Нить транспортного протокола не удалась. Java.io. IOException: сокет EOF») происходит, когда j2ssh.jar файл не совместим с текущей версией SSH сервера SFTP

Вы можете попробовать использовать Java Secure Channel (JSch) от here

0..

Предоставлено: http://techydiary.com/the-transport-protocol-thread-failed-java-io-ioexception-the-socket-is-eof/

+1

Спасибо Infinity, я попробую использовать АОH. –

+0

@ KarthickSambanghi: Рад, что это помогло. Позже вы можете принять этот ответ :) –

0

Следующий пример кода может помочь вам,

import java.io.InputStream; 
import org.apache.commons.io.IOUtils; 


import com.jcraft.jsch.Channel; 
import com.jcraft.jsch.ChannelExec; 
import com.jcraft.jsch.JSch; 
import com.jcraft.jsch.Session; 


public class SSHClient { 

    /** 
    * Constant EXCUTE_CHANNEL 
    */ 
    public static final String EXCUTE_CHANNEL = "exec"; 

    /** 
    * Constant STRICT_KEY_CHECKING 
    */ 
    public static final String STRICT_KEY_CHECKING = "StrictHostKeyChecking"; 


    /** Name/ip of the remote machine/device **/ 
    private String host; 
    private String userName; 
    private String password; 

    /** 
    * This method used to initilze user and host 
    * 
    * @param userName 
    * @param password 
    * @param host 
    */ 
    public SSHClient(String userName,String password, String host) { 
     super(); 
     this.userName = userName; 
     this.password = password; 
     this.host = host; 
    } 

    /** 
    * This method used to execute commands remotly by using SSHV2 
    * 
    * @param host 
    * @param username 
    * @param password 
    * @param command 
    * @return 
    */ 
    public String executeCommand(String command) { 
     StringBuilder log = new StringBuilder(); 
     String response = null; 
     Channel channel = null; 
     Session session = null; 

     try { 
      JSch jsch = new JSch(); 
      JSch.setConfig(STRICT_KEY_CHECKING, Constants.NO); 

      session = jsch.getSession(userName, host, 22); 


      // If two machines have SSH passwordless logins setup, the following 
      // line is not needed: 
      session.setPassword(password); 
      session.connect(); 

      channel = session.openChannel(EXCUTE_CHANNEL); 
      ((ChannelExec) channel).setCommand(command); 

      // channel.setInputStream(System.in); 
      channel.setInputStream(null); 

      ((ChannelExec) channel).setErrStream(System.err); 

      InputStream in = channel.getInputStream(); 

      channel.connect(); 

      response = IOUtils.toString(in); 

     } catch (Exception ex) { 
       //handle exception 
     } finally { 
      try { 
       if (session != null) { 
        session.disconnect(); 
       } 
      } catch (Exception ex) { 
       //handle exception 
      } 
      try { 
       if (channel != null) { 
        channel.disconnect(); 
       } 
      } catch (Exception ex) { 
       //handle exception 
      } 

     } 
     System.ou.println("Response received :"+ response)); 
     return response; 
    } 
} 
8

Мотивация

я наткнулся на этот вопрос и ответы при расследовании ошибки в вопросе java.io.IOException: The socket is EOF. Поскольку изменение кода для использования какой-либо другой библиотеки Java SSH невозможно сразу в моем случае, и указанное объяснение с помощью @ a3.14_Infinity не было достаточно детально для меня, я хотел бы добавить свое мнение о нем.

java.io.IOException: Сокет EOF - Почему?

Поскольку это исключение не очень полезно, я сначала попробовал Wireshark, чтобы узнать, что происходит по проводам, но безрезультатно. Поэтому я установил sshd_config (OpenSSH 6.9) для входа на уровень DEBUG3 и получил ответ в файле /var/log/auth.log моего тестового компьютера. В нем указана фатальная ошибка при попытке согласовать алгоритм обмена ключами с клиентом SSH (Java SSH library).

Поскольку сервер SSH и клиент не смогли согласовать алгоритм обмена общими ключами, сервер OpenSSH завершает соединение с клиентом. Следовательно, код библиотеки Java SSH генерирует исключение.

Но почему это происходит?

Код библиотеки sshtools.j2ssh (sshtools : j2ssh-core : 0.2.9) довольно старый и прекращен. Начиная с OpenSSH 6.7 (выпущенный в октябре 2014 года) шифры по умолчанию и MAC были изменены для удаления небезопасных алгоритмов, которые включают в себя шифр blowfish-cbc. И с OpenSSH 6.9 (выпущенный в июне 2015 года) поддержка обмена ключами 1024-бит diffie-hellman-group1-sha1 по умолчанию отключена.

Если вы до сих пор используете доисторическую библиотеку SSH Tools j2ssh (не дай Бог), подключающуюся к новому серверу OpenSSH, вы получите описанную ошибку. Код библиотеки предлагает только алгоритм обмена ключами diffie-hellman-group1-sha1 на сервере OpenSSH, который по умолчанию не поддерживается. Таким образом, безопасное соединение не может быть установлено.

Не можете изменить код?

Если переместить в другую библиотеку Java SSH невозможно сразу (в моем случае), вы можете снова включить отключенный алгоритм обмена ключами diffie-hellman-group1-sha1 в конфигурационном файле сервера OpenSSH sshd_config. Например, вот так.

Ciphers aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected],[email protected],blowfish-cbc 

KexAlgorithms diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1 

Но позвольте мне пояснить это. Алгоритм обмена ключами , а также шифр blowfish-cbc отключены по умолчанию, поскольку они небезопасны. Повторное их использование должно быть только временной мерой, пока вы не сможете заменить эту устаревшую Java SSH-библиотеку.

И наконец, я хотел бы отметить, что предлагаемая библиотека Java Secure Channel (JSch) в других ответах прекращена. Таким образом, вы можете рассмотреть вместо sshj или даже ssh2j-maverick.

Edit: я был неправ, то Java Secure Channel JSch библиотека жива (JSch 0.1.54 был выпущен на 2016-09-03 on MavenCentral) и, безусловно, стоит вашего внимания. В качестве альтернативы, вы также можете рассмотреть также sshj или ssh2j-maverick.

Добавление: Миграция

Чтобы сохранить работу по перенастройке для sshtools.j2ssh (sshtools : j2ssh-core : 0.2.9) библиотеки минимальна Я смотрел на коммерческой унаследованной библиотеке SSH клиента из SSHTOOLS (версия 1.7.1). Это позволило сохранить существующий код интеграции библиотеки с небольшими незначительными изменениями в отношении API библиотек и обработки исключений. Таким образом, если вы не хотите перезапускать с нуля, то кусать пулю и придерживаться SSHTOOLS - это, вероятно, ваш лучший вариант. Наконец, чтобы оценить усилия по миграции, я сначала заменил библиотеку библиотекой с открытым исходным кодом SSHTOOLS ssh2j-maverick, которая почти имеет тот же API, что и его последняя коммерческая версия (версия 1.7.1).