JSch multiple tunnels/jumphosts - java

I'm not sure if this is caused by using a private key instead of password for the port forwarding but here's what I'm trying to do
I need to forward local port 3308 all the way to the my SQL DB at 3306.
I can run things like this all together in terminal on my local
ssh -L 3308:localhost:3307 username#jumpbox "ssh -L 3307:mysqlDB:3306 username#server"
Or run the first part on my local and then the second part on the jumpbox. Both works fine and I can connect to my localhost:3308.
The problem comes when I start using JSch. Here is my code
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session session = jsch.getSession("username", "jumpbox");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
int assinged_port = session.setPortForwardingL(3308, "localhost", 3307);
Session mysqlSession = jsch.getSession("username", "server", assinged_port);
mysqlSession.setConfig("StrictHostKeyChecking", "no");
mysqlSession.connect(); // Connection timed out here
mysqlSession.setPortForwardingL(3307, "mysqlDB", 3306);
The first connection is done but the second one timed out.
Exception in thread "main" com.jcraft.jsch.JSchException: java.net.ConnectException: Operation timed out (Connection timed out)
Am I doing something wrong here with JSch or port forwarding?

Your ssh command is making use of an SSH client (another ssh) running on "jump box".
When you want to implement the same using Java, you have two options:
Do the same in Java, i.e. use session to run ssh -L 3307:mysqlDB:3306 username#server on the "jump box".
See Executing a command using JSch.
Though, I do not think you should rely on ssh program for the second jump, for the same reason you use Java/JSch for the first jump (and not ssh program).
Avoid using a separate ssh tool, and instead open the other SSH session locally via yet another forwarded port. You can actually do the same using recent versions of ssh, with -J (jump) switch (supported since OpenSSH 7.3):
ssh -L 3308:mysqlDB:3306 -J username#jumpbox username#server
See also Does OpenSSH support multihop login?
I prefer this approach.
To implement the latter approach:
You have to forward some local port to server:22, so that you can open SSH connection to the server:
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session jumpboxSession = jsch.getSession("username", "jumpbox");
jumpboxSession.connect();
int serverSshPort = jumpboxSession.setPortForwardingL(0, "server", 22);
Session serverSession = jsch.getSession("username", "localhost", serverSshPort);
serverSession.connect();
Then you forward another local port via server to MySQL port:
int mysqlPort = serverSession.setPortForwardingL(0, "mysqlDB", 3306);
Now you should be able to connect to localhost:mysqlPort using MySQL client.
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 a correct (and secure) approach, see:
How to resolve Java UnknownHostKey, while using JSch SFTP library?

Related

Jump to Different server from Bastion using Java JSch [duplicate]

I'm not sure if this is caused by using a private key instead of password for the port forwarding but here's what I'm trying to do
I need to forward local port 3308 all the way to the my SQL DB at 3306.
I can run things like this all together in terminal on my local
ssh -L 3308:localhost:3307 username#jumpbox "ssh -L 3307:mysqlDB:3306 username#server"
Or run the first part on my local and then the second part on the jumpbox. Both works fine and I can connect to my localhost:3308.
The problem comes when I start using JSch. Here is my code
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session session = jsch.getSession("username", "jumpbox");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
int assinged_port = session.setPortForwardingL(3308, "localhost", 3307);
Session mysqlSession = jsch.getSession("username", "server", assinged_port);
mysqlSession.setConfig("StrictHostKeyChecking", "no");
mysqlSession.connect(); // Connection timed out here
mysqlSession.setPortForwardingL(3307, "mysqlDB", 3306);
The first connection is done but the second one timed out.
Exception in thread "main" com.jcraft.jsch.JSchException: java.net.ConnectException: Operation timed out (Connection timed out)
Am I doing something wrong here with JSch or port forwarding?
Your ssh command is making use of an SSH client (another ssh) running on "jump box".
When you want to implement the same using Java, you have two options:
Do the same in Java, i.e. use session to run ssh -L 3307:mysqlDB:3306 username#server on the "jump box".
See Executing a command using JSch.
Though, I do not think you should rely on ssh program for the second jump, for the same reason you use Java/JSch for the first jump (and not ssh program).
Avoid using a separate ssh tool, and instead open the other SSH session locally via yet another forwarded port. You can actually do the same using recent versions of ssh, with -J (jump) switch (supported since OpenSSH 7.3):
ssh -L 3308:mysqlDB:3306 -J username#jumpbox username#server
See also Does OpenSSH support multihop login?
I prefer this approach.
To implement the latter approach:
You have to forward some local port to server:22, so that you can open SSH connection to the server:
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session jumpboxSession = jsch.getSession("username", "jumpbox");
jumpboxSession.connect();
int serverSshPort = jumpboxSession.setPortForwardingL(0, "server", 22);
Session serverSession = jsch.getSession("username", "localhost", serverSshPort);
serverSession.connect();
Then you forward another local port via server to MySQL port:
int mysqlPort = serverSession.setPortForwardingL(0, "mysqlDB", 3306);
Now you should be able to connect to localhost:mysqlPort using MySQL client.
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 a correct (and secure) approach, see:
How to resolve Java UnknownHostKey, while using JSch SFTP library?

Java SSH connection

How can I connect to internet server from Java desktop application? I need to access MySQL database and upload/download files. The host that I have (one.com), don't support remote database access, so I've tried with SSH. I don't know anything at all about this. I've tried various codes examples but none of them pass further than connection. I add jsch.jar to my project. Is there something else that I have to add/install or what em I missing?
public static void main(String args[])
{
String user = "user";
String password = "pass";
String host = "00.000.00.000";
int port=22;
String remoteFile="/home/mywebsite.com/test.txt";
try
{
JSch jsch = new JSch();
Session session = (Session) jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Creating SFTP Channel.");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
System.out.println("SFTP Channel created.");
InputStream out= null;
out= sftpChannel.get(remoteFile);
try (BufferedReader br = new BufferedReader(new InputStreamReader(out))) {
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
}
}
catch(JSchException | SftpException | IOException e){System.err.print(e);}
}
I get the error:
com.jcraft.jsch.JSchException: java.net.ConnectException: Connection timed out: connect
BUILD SUCCESSFUL (total time: 24 seconds)
Or what other alternatives I have to achieve a remote connection to my site & database?
P.S. I have tried almost all the example-codes from stackoverflow and all get stuck in the same point ...
Thank you!
Connection timed out indicates that you're trying to connect to a server that isn't accepting SSH connections on port 22, or your host is incorrect. Is host = "00.000.00.000"; the actual IP address you're trying to connect to, or did you change it for your Stack Overflow question?
I'm not going to debug your code, but will tell you how to accomplish this.
The solution is to use SSH "port forwarding", which you should first set up from the command line, to learn how it works, before embedding it in your Java code. You may not need to write any code if a command-line tunnel will suffice.
ssh -L3306:localhost:3306 <databaseHost>
This creates an SSH "tunnel" from your computer's port 3306 to the <databaseHost> and then on to localhost from <databaseHost>. Any connection on your computer to your local port 3306 gets tunnelled across SSH to <databaseHost> and then on to whatever <databaseHost> knows as localHost, i.e. back to itself, on port 3306.
When your Java code connects to the database, it should connect to localhost:3306. Note that the localhost in your database connect string refers to your computer, while the one in the ssh command is from the point of view of the remote server, so they mean different things.
In summary, a packet from your Java code to the remote MySQL server travels the following route:
Connect to my computer port 3306
Intercepted by ssh
Encrypted and transmitted to remote database server
Decrypted by sshd and fed to port 3306 on the same server
Received by MySQL running on the remote host
For return packets, this process is reversed, managed by the local ssh client and the remote sshd daemon.
Note that this can be used for more interesting cases. For example, suppose the remote ssh server and database server are on different systems behind the same firewall. Let's say the ssh host is visible as gateway.xyz.com, while the database host is on an internal LAN at 10.0.0.3 which is not reachable from the Internet, but reachable from the gateway.
ssh -L3306:10.0.0.3:3306 gateway.xyz.com
The packet route is then
Your computer 3306
Received by ssh
Encryption and sent to gateway.xyz.com
Decrypted by sshd forwarded to 10.0.0.3:3306
Received at 10.0.0.3:3306 by MySQL
To be clear, this is something you set up from the command line, before executing your Java code, which should happen in a different session from the ssh command. The tunnel remains available as long as the ssh command is running.

It's possible do connect in a server using SSH through other SSH connection in Java?

I have two servers (Server1 and Server2),
on my network, i can connect only with ssh to Server1, my network can't see Server2...
I want to make a program that connects in Server1, and starts a new connection to Server2 using ssh again.
I have already connected to Server1 using SSH libs in java, but i don't know how to start a new connection using my actual ssh session.
It's like in terminal do a ssh Server2#10.1.10.10
How can i do this?
This should be possible with most Java SSH APIs as its simply a case of performing a port forward to the second host after connecting to the first and then connecting the input/output of a tunnel into a new client instance.
However with the J2SSH Maverick open source API we make this quite easy and do the forwarding setup for you.
The code below demonstrates how you do this, first open a connection to the first server. Then once connected call openRemoteClient and it will return an SshClient object for the second. In the background this uses port forwarding to connect the second client.
The example uses password authentication but you could of course use any type of authentication.
// Create initial connection
SshConnector con = SshConnector.createInstance();
SshClient ssh = con.connect(new SocketTransport("host.external", 22), "ubuntu");
// Authenticate
PasswordAuthentication pwd = new PasswordAuthentication();
pwd.setPassword("xxxxxxx");
ssh.authenticate(pwd);
// Created forwarded connection
SshClient remoteClient = ssh.openRemoteClient("host.internal", 22, "ubuntu");
// Now you have to authenticate the second client
.....

JSch - Port forwarding using multiple Jumphosts [duplicate]

I'm not sure if this is caused by using a private key instead of password for the port forwarding but here's what I'm trying to do
I need to forward local port 3308 all the way to the my SQL DB at 3306.
I can run things like this all together in terminal on my local
ssh -L 3308:localhost:3307 username#jumpbox "ssh -L 3307:mysqlDB:3306 username#server"
Or run the first part on my local and then the second part on the jumpbox. Both works fine and I can connect to my localhost:3308.
The problem comes when I start using JSch. Here is my code
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session session = jsch.getSession("username", "jumpbox");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
int assinged_port = session.setPortForwardingL(3308, "localhost", 3307);
Session mysqlSession = jsch.getSession("username", "server", assinged_port);
mysqlSession.setConfig("StrictHostKeyChecking", "no");
mysqlSession.connect(); // Connection timed out here
mysqlSession.setPortForwardingL(3307, "mysqlDB", 3306);
The first connection is done but the second one timed out.
Exception in thread "main" com.jcraft.jsch.JSchException: java.net.ConnectException: Operation timed out (Connection timed out)
Am I doing something wrong here with JSch or port forwarding?
Your ssh command is making use of an SSH client (another ssh) running on "jump box".
When you want to implement the same using Java, you have two options:
Do the same in Java, i.e. use session to run ssh -L 3307:mysqlDB:3306 username#server on the "jump box".
See Executing a command using JSch.
Though, I do not think you should rely on ssh program for the second jump, for the same reason you use Java/JSch for the first jump (and not ssh program).
Avoid using a separate ssh tool, and instead open the other SSH session locally via yet another forwarded port. You can actually do the same using recent versions of ssh, with -J (jump) switch (supported since OpenSSH 7.3):
ssh -L 3308:mysqlDB:3306 -J username#jumpbox username#server
See also Does OpenSSH support multihop login?
I prefer this approach.
To implement the latter approach:
You have to forward some local port to server:22, so that you can open SSH connection to the server:
JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");
Session jumpboxSession = jsch.getSession("username", "jumpbox");
jumpboxSession.connect();
int serverSshPort = jumpboxSession.setPortForwardingL(0, "server", 22);
Session serverSession = jsch.getSession("username", "localhost", serverSshPort);
serverSession.connect();
Then you forward another local port via server to MySQL port:
int mysqlPort = serverSession.setPortForwardingL(0, "mysqlDB", 3306);
Now you should be able to connect to localhost:mysqlPort using MySQL client.
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 a correct (and secure) approach, see:
How to resolve Java UnknownHostKey, while using JSch SFTP library?

How to connect to an FTP server from an existing connection to Unix server?

Currently I am using Reflection for Unix and OpenVMS. I connect to a Unix server. Once connected, I establish a new FTP connection to the target server. Here is how the console window look like:
login: xxx
Password : xxx
// Now I'm connected to UNIX
// Next I am connecting to that FTP
ftpLogin#hostName :/whatever/.../ $ ftp someftp.example.com
Conencted
Name: myLogin
Password:
XXX
Login OK
I tried to replicate the same steps programmatically, but got confused with this "double connection" thing. I was able to connect to Unix only, but then I don't know how to proceed.
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
Now that I am connected to Unix, how do I proceed with this step ftpLogin#hostName :/whatever/.../ $ ftp someftp.example.com?
I think I might only need to send a command, something like
sftpChannel.setCommand("ftpLogin#hostName :/whatever/.../ $ ftp someftp.example.com ?")
How can I connect to a separate FTP from an existing "session/connection"?
You typically use the local port forwarding for this.
In JSch, after you connect, call the setPortForwardingL:
int ftpPort = session.setPortForwardingL(0, "someftp.example.com", 21);
And then connect a local FTP client (e.g. the FTPClient from Apache Commons) to the localhost:ftpPort:
FTPClient ftp = new FTPClient();
ftp.connect("localhost", ftpPort);
ftp.login("myLogin", password);

Categories

Resources