I am trying to establish an SSH connection through my Java code, but getting below exception .. I tested my connection through Putty/Winscp tools and it works fine. The problem is with my Java code...
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)
Below is my piece of Java code to establish the connection
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);
}
I stumbled across this question and answers while investigating the error in question java.io.IOException: The socket is EOF
. Because changing the code to use some other SSH Java library is not immediately possible in my case and the stated explanation by @a3.14_Infinity was not detailed enough for me, I'd like to add my take on it.
Because this exception is not very helpful, I first tried Wireshark to see what's going on over the wire, but to no avail. So I configured the sshd_config
(OpenSSH 6.9) to log on DEBUG3
level and got the answer in the /var/log/auth.log
file of my test machine. It stated a fatal error while trying to negotiate the key exchange algorithm with the SSH client (the Java SSH library).
Because the SSH server and client could not agree on a mutual key exchange algorithm the OpenSSH server terminates the connection to the client. In consequence, the Java SSH library code throws the exception.
The sshtools.j2ssh
(sshtools : j2ssh-core : 0.2.9) library code is pretty old and discontinued. Starting with OpenSSH 6.7 (released October, 2014) default ciphers and MAC have been altered to remove unsafe algorithms which includes the blowfish-cbc
cipher. And with OpenSSH 6.9 (released June, 2015) the support for the 1024-bit diffie-hellman-group1-sha1
key exchange is disabled by default.
When you still use the prehistoric SSH Tools j2ssh
library (God forbid) connecting to a newer OpenSSH server you will get the described error. The library code only offers the diffie-hellman-group1-sha1
key exchange algorithm to the OpenSSH server which it does not support by default. Thus, a secure connection cannot be established.
If moving to another Java SSH library is not immediately possible (my case) then you can re-enable the disabled diffie-hellman-group1-sha1
key exchange algorithm in the OpenSSH's server config file sshd_config
. For example like this.
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
But let me be clear on this. The diffie-hellman-group1-sha1
key exchange algorithm as well as the blowfish-cbc
cipher are turned off by default because they are insecure. Reenabling them should only be a temporary measure until you can replace this obsolete Java SSH library.
Finally, I like to point out that the suggested Java Secure Channel (JSch) library in other answers is discontinued. So, you might want to consider sshj or even ssh2j-maverick instead.
Edit: I was wrong, the Java Secure Channel JSch library is alive (JSCH 0.1.54 was released on 2016-09-03 on MavenCentral) and certainly worth your consideration. Alternatively, you may want to consider also sshj or ssh2j-maverick.
To keep the migration effort for the sshtools.j2ssh
(sshtools : j2ssh-core : 0.2.9) library minimal I looked at the commercial legacy SSH client library from SSHTOOLS (version 1.7.1). This allowed to keep the existing library integration code with few minor changes regarding library API and exception handling. Thus, if you do not want to restart from scratch then biting the bullet and sticking with SSHTOOLS is probably your best option. Finally, to gauge the migration effort I first replaced the library with SSHTOOLS' open source library ssh2j-maverick which almost has the same API as its latest commercial version (version 1.7.1).