0

I am trying to connect a remote server using JSch but I am getting "Auth fail" exception. Below is my code:

String user = "user.name";
String host = "hostip";
try
{
    JSch jsch = new JSch();
    Session session = jsch.getSession(user, host);
    session.setConfig("StrictHostKeyChecking", "no");
    System.out.println("Establishing Connection...");
    session.connect();
    int assinged_port=session.setPortForwardingL(lport, rhost, rport);
    System.out.println("localhost:"+assinged_port+" -> "+rhost+":"+rport);
}
catch(Exception e){System.err.print(e);}

However when I try to ssh from iTerm using the command ssh user.name@hostip I can successfully access the remote server using public key authentication.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Sanjay Bhatia
  • 47
  • 2
  • 11

3 Answers3

3

Your OpenSSH ssh command automatically uses the private key you have configured for OpenSSH in your .ssh folder.

JSch won't automatically use OpenSSH keys. You have to explicitly tell it what key to use.
See Can we use JSch for SSH key-based communication?

Also note that JSch does not support all key formats that OpenSSH do.
See "Invalid privatekey" when using JSch


Obligatory warning: Do not use StrictHostKeyChecking=no to blindly accept all host keys. That is a security flaw. You lose a protection against MITM attacks. For the correct (and secure) approach, see: How to resolve Java UnknownHostKey, while using JSch SFTP library?


Others might be getting the same error for very different reasons. For example when connecting to a modern server that is JSch is no longer compatible with:
Public key authentication fails with JSch but work with OpenSSH with the same key

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
1

As @martin prikryl says: JSch won't automatically use OpenSSH keys.

File file = new File(SystemUtils.getUserHome() + "/.ssh/id_rsa");
String knownHosts = SystemUtils.getUserHome() + "/.ssh/known_hosts";
jsch.setKnownHosts(knownHosts);
jsch.addIdentity(file.getPath());

SystemUtils belongs to Apache Commons Lang3 or you can use:

new File(System.getProperty("user.home"))
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Samt
  • 109
  • 8
-1

Use SSHJ instead:

import net.schmizz.sshj.DefaultConfig;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class SSHJExample {

    public static void main(String[] args) {
        SSHClient ssh = new SSHClient();
        try {
            // Use a PromiscuousVerifier to trust any host key
            HostKeyVerifier promiscuousVerifier = new PromiscuousVerifier();

            // Configure the SSH client with the PromiscuousVerifier
            ssh.addHostKeyVerifier(promiscuousVerifier);

            // Connect to the remote server
            ssh.connect("host");
          // Specify the private key for authentication
            KeyProvider keyProvider = ssh.loadKeys("/path/to/your/private_key");
// or ssh.loadKeys("/path/to/your/private_key","passphrase");

            // Authenticate using the private key
            ssh.authPublickey("user", keyProvider);

            // Create a session
            Session session = ssh.startSession();

            try {
                // Execute a command on the remote server
                Session.Command command = session.exec("ls -la");

                // Wait for the command to complete
                command.join(5, TimeUnit.SECONDS);

                // Get the command output
                String output = IOUtils.readFully(command.getInputStream()).toString();

                System.out.println("Command output:");
                System.out.println(output);
            } finally {
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ssh.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

       
    }
}

Dependency:

<dependency>
            <groupId>com.hierynomus</groupId>
            <artifactId>sshj</artifactId>
            <version>0.35.0</version>
        </dependency>

A safer solution for the HostsVerifier would be:

Add the host key to the known hosts file: You can manually add the host key of the remote server to the known hosts file on the machine running the code. The known hosts file is typically located at ~/.ssh/known_hosts for the user executing the code. Once the host key is added to the known hosts file, SSHJ will be able to verify it during subsequent connections.

Use a secure host key verifier: Instead of trusting any host key or modifying the known hosts file manually, you can implement a custom HostKeyVerifier that matches the expected host key fingerprint and use it to verify the host key. This approach provides a more secure way to verify the host key. Here's an example:

// Load the known hosts file for host key verification
            OpenSSHKnownHosts sshKnownHosts = new OpenSSHKnownHosts();

            // Set the known hosts file path
            sshKnownHosts.load("~/.ssh/known_hosts"); // Replace with the actual path

            // Configure the SSH client with the known hosts verifier
            ssh.addHostKeyVerifier(sshKnownHosts);
Brian Brix
  • 449
  • 4
  • 12
  • Please do not suggest anyone to use `PromiscuousVerifier` without explaining the security consequences. – Martin Prikryl Jun 17 '23 at 15:45
  • Agreed Martin Prikryl, The PromiscuousVerifier is a simple implementation of the HostKeyVerifier interface that trusts any host key. Be cautious when using this approach, as it disables host key verification and exposes your code to potential security risks. I have edited the answer to include a better alternative. – Brian Brix Jun 18 '23 at 16:11
  • Good, but why don't you edit the original code to be correct right away? – Martin Prikryl Jun 18 '23 at 17:25
  • Let the developer choose what to use. The explanation is clear enough. – Brian Brix Jun 18 '23 at 19:44