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 this server. However I am not able to implement the same scenario via JSch.
I am not able to have the below code work, which I have written for this purpose. Please let me know if I am doing anything silly here.
public class JschExecutor {
public static void main(String[] args){
JschExecutor t=new JschExecutor();
try{
t.go();
} catch(Exception ex){
ex.printStackTrace();
}
}
public void go() throws Exception{
StringBuilder outputBuffer = new StringBuilder();
String host="xxx.xxx.xxx.xxx"; // The host to be connected finally
String user="user";
String password="passwrd";
int port=22;
String tunnelRemoteHost="xx.xx.xx.xx"; // The host from where the tunnel is created
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");
ProxySOCKS5 proxyTunnel = new ProxySOCKS5(tunnelRemoteHost, 22);
proxyTunnel.setUserPasswd(user, password);
session.setProxy(proxyTunnel);
session.connect(30000);
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand("hostname");
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
BufferedReader ebr = new BufferedReader(new InputStreamReader(in));
channel.connect();
while (true) {
byte[] tmpArray=new byte[1024];
while(in.available()>0){
int i=in.read(tmpArray, 0, 1024);
if(i<0)break;
outputBuffer.append(new String(tmpArray, 0, i)).append("\n");
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
}
ebr.close();
channel.disconnect();
session.disconnect();
System.out.println(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){}
}
}
The above code gives the below exception on the session.connect(30000);
line.
com.jcraft.jsch.JSchException: ProxySOCKS5: com.jcraft.jsch.JSchException: fail in SOCKS5 proxy
at com.jcraft.jsch.ProxySOCKS5.connect(ProxySOCKS5.java:317)
at com.jcraft.jsch.Session.connect(Session.java:231)
at com.ukris.main.JschExecutor.go(JschExecutor.java:50)
at com.ukris.main.JschExecutor.main(JschExecutor.java:19)
Caused by: com.jcraft.jsch.JSchException: fail in SOCKS5 proxy
at com.jcraft.jsch.ProxySOCKS5.connect(ProxySOCKS5.java:200)
... 3 more
Transporting arbitrary data streams over SSH sessions is also known as SSH tunneling. OpenSSH, a popular open-source SSH server, supports three types of tunneling features- local port forwarding, remote port forwarding, and dynamic port forwarding.
2. JSch. JSch is the Java implementation of SSH2 that allows us to connect to an SSH server and use port forwarding, X11 forwarding, and file transfer. Also, it is licensed under the BSD style license and provides us with an easy way to establish an SSH connection with Java.
Set up SSH Tunneling in WindowsLaunch Putty and enter the SSH server IP Address in the Host name (or IP address) field. Under the Connection menu, expand SSH and select Tunnels . Check the Local radio button to setup local, Remote for remote, and Dynamic for dynamic port forwarding.
JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, file transfer, etc., and you can integrate its functionality into your own Java programs. JSch is licensed under BSD style license.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With