使用Java的SSH连接

Kar*_*ghi 5 java ssh ssh-keys j2ssh

我试图通过我的Java代码建立SSH连接,但得到以下异常..我通过Putty/Winscp工具测试我的连接,它工作正常.问题出在我的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)
Run Code Online (Sandbox Code Playgroud)

下面是我建立连接的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);
    }
Run Code Online (Sandbox Code Playgroud)

Ivo*_*ori 11

动机

在调查有问题的错误时,我偶然发现了这个问题和答案java.io.IOException: The socket is EOF.因为在我的情况下不能立即改变代码以使用其他SSH Java库,并且@ a3.14_Infinity所述的解释对我来说不够详细,我想补充一下.

java.io.IOException:套接字是EOF - 为什么?

因为这个例外不是很有帮助,所以我首先尝试使用Wireshark查看线路上发生了什么,但无济于事.所以我将sshd_config(OpenSSH 6.9)配置为登录DEBUG3级别并在/var/log/auth.log我的测试机器的文件中得到答案.它在尝试与SSH客户端(Java SSH库)协商密钥交换算法时发出致命错误.

由于SSH服务器和客户端无法就互密钥交换算法达成一致,因此OpenSSH服务器终止与客户端的连接.因此,Java SSH库代码会抛出异常.

但为什么会这样呢?

sshtools.j2ssh(sshtools:J2SSH核心:0.2.9)库中的代码是很老和停产.从OpenSSH 6.7(2014年10月发布)开始,默认密码和MAC已被更改,以删除包含blowfish-cbc密码的不安全算法.使用OpenSSH 6.9(2015年6月发布)diffie-hellman-group1-sha1,默认情况下禁用对1024位密钥交换的支持.

当您仍然使用史前SSH工具j2ssh库(上帝禁止)连接到较新的OpenSSH服务器时,您将收到所描述的错误.库代码仅向diffie-hellman-group1-sha1OpenSSH服务器提供密钥交换算法,默认情况下不支持.因此,无法建立安全连接.

无法更改代码?

如果不能立即转移到另一个Java SSH库(我的情况),那么您可以diffie-hellman-group1-sha1在OpenSSH的服务器配置文件中重新启用禁用的密钥交换算法sshd_config.比如这样.

Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,blowfish-cbc

KexAlgorithms diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1
Run Code Online (Sandbox Code Playgroud)

但请允许我明确这一点.该diffie-hellman-group1-sha1密钥交换算法,以及该blowfish-cbc密码是默认,因为它们是不安全的关闭.重新启用它们应该只是一个临时措施,直到您可以替换这个过时的Java SSH库.

最后,我想指出其他答案中建议的Java安全通道(JSch)库已停止使用.所以,你可能想要考虑sshj甚至是ssh2j-maverick.

编辑:我错了,Java Secure Channel JSch库还活着(JSCH 0.1.54于2016-09-03 在MavenCentral上发布),当然值得您考虑.或者,您可能还需要考虑sshjssh2j-maverick.

附录:移民

为了使sshtools.j2ssh(sshtools:j2ssh-core:0.2.9)库的迁移工作保持最小,我查看了SSHTOOLS(1.7.1版)中的商业旧SSH客户端库.这允许保留现有的库集成代码,只需对库API和异常处理进行一些微小的更改.因此,如果您不想从头开始重新启动,那么咬住子弹并坚持使用SSHTOOLS可能是您的最佳选择.最后,为了衡量迁移工作,我首先用SSHTOOLS的开源库ssh2j-maverick替换了库,该库几乎与最新的商业版本(版本1.7.1)具有相同的API.


a3.*_*ity 1

当 j2ssh.jar 文件与 SFTP 服务器的当前 SSH 版本不兼容时,会出现此错误(“传输协议线程失败。java.io.IOException:套接字为 EOF\xe2\x80\x9d ”)。

\n\n

您可以从此处尝试使用 Java 安全通道 (JSch) 。

\n\n

礼貌:http://techydiary.com/the-transport-protocol-thread-failed-java-io-ioexception-the-socket-is-eof/

\n