My aim is to connect to a server (host) which is behind a firewall. I am able to access this server by connecting to another server (tunnel) in the network and then SSH to t
a SOCKS
proxy setting on jsch allows you to connect to a running proxy server on the remote side. An sshd
on the remote side would not be considered a SOCKS
proxy. What you will have to do is establish a local port forward to the ssh port on the machine you're tunneling to, then establish a secondary ssh connection to this system using the api.
I've taken your example and slightly rewritten it to accomplish this:
import com.jcraft.jsch.*;
import java.io.*;
public class JschExecutor2 {
public static void main(String[] args){
JschExecutor2 t=new JschExecutor2();
try{
t.go();
} catch(Exception ex){
ex.printStackTrace();
}
}
public void go() throws Exception{
StringBuilder outputBuffer = new StringBuilder();
String host="firstsystem"; // First level target
String user="username";
String password="firstlevelpassword";
String tunnelRemoteHost="secondlevelhost"; // The host of the second target
String secondPassword="targetsystempassword";
int port=22;
JSch jsch=new JSch();
Session session=jsch.getSession(user, host, port);
session.setPassword(password);
localUserInfo lui=new localUserInfo();
session.setUserInfo(lui);
session.setConfig("StrictHostKeyChecking", "no");
// create port from 2233 on local system to port 22 on tunnelRemoteHost
session.setPortForwardingL(2233, tunnelRemoteHost, 22);
session.connect();
session.openChannel("direct-tcpip");
// create a session connected to port 2233 on the local host.
Session secondSession = jsch.getSession(user, "localhost", 2233);
secondSession.setPassword(secondPassword);
secondSession.setUserInfo(lui);
secondSession.setConfig("StrictHostKeyChecking", "no");
secondSession.connect(); // now we're connected to the secondary system
Channel channel=secondSession.openChannel("exec");
((ChannelExec)channel).setCommand("hostname");
channel.setInputStream(null);
InputStream stdout=channel.getInputStream();
channel.connect();
while (true) {
byte[] tmpArray=new byte[1024];
while(stdout.available() > 0){
int i=stdout.read(tmpArray, 0, 1024);
if(i<0)break;
outputBuffer.append(new String(tmpArray, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
}
stdout.close();
channel.disconnect();
secondSession.disconnect();
session.disconnect();
System.out.print(outputBuffer.toString());
}
class localUserInfo implements UserInfo{
String passwd;
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){return true;}
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){return true; }
public boolean promptPassword(String message){return true;}
public void showMessage(String message){}
}
}
What this code does is create a local port forwarding to the ssh port on the target system, then connects through it. The running of the hostname command illustrates that it is, indeed, running on the forwarded-to system.
This is tested and working fine. this works like secure pipes and best for tunneling
String strSshUser = "ssh_user_name"; // SSH loging username
String strSshPassword = "abcd1234"; // SSH login password
String strSshHost = "your.ssh.hostname.com"; // hostname or ip or
// SSH server
int nSshPort = 22; // remote SSH host port number
String strRemoteHost = "your.database.hostname.com"; // hostname or
// ip of
// your
// database
// server
int nLocalPort = 3366; // local port number use to bind SSH tunnel
int nRemotePort = 3306; // remote port number of your database
String strDbUser = "db_user_name"; // database loging username
String strDbPassword = "4321dcba"; // database login password
final JSch jsch = new JSch();
Session session = jsch.getSession(strSshUser, strSshHost, 22);
session.setPassword(strSshPassword);
final Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
session.setPortForwardingL(nLocalPort, strRemoteHost, nRemotePort);