To debug remote AS/400 systems, i need to setup an SSH connection that runs over 2 or more jump hosts to access the target system.I have most parts done (like adjusting the JTopen toolbox ports being used to be able to override them locally).
The only thing is, i can't seem to get JSch to do what carry a local host port trough multiple hosts to the target port on the AS/400.
Example
[local-port 1234] ==> [ssh-jumphost-1] ===> [ssh-jumphost-2] ===> [as400-port 8470]
I tried and toyed with the JSch examples, and can get the ForwardL and Jumphost examples to work, but when combining these (setting up the tunnel, and then set the as/400 port forwarding towards the first host)
I also tried to get this done using SSH (to see if it is possible at all), but no luck there either.
Questions are: 1. Is what i try to do at all feasible ? or is this impossible to achieve ? 2. Is JSch not appropriate for the job ? should another Java SSH2 library be used to have more success ?
If needed, i can post some code as well.
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import eu.javautil.sshtool.config.JumpHost;
import eu.javautil.sshtool.config.JumpHostChain;
import java.util.HashMap;
import java.util.Map;
/**
* Manages SSH Tunnels
*
* @author fhdumay
* @version 1.0.0
*/
public class SSHTunnel {
private final JumpHostChain sshChain;
private final Session[] sessions;
private final JSch jSchInstance;
private boolean tunnelActive = false;
/**
* @param sshChain
*/
public SSHTunnel(JumpHostChain sshChain) {
jSchInstance = new JSch();
jSchInstance.setLogger(new MyLogger());
this.sshChain = sshChain;
sessions = new Session[sshChain.getAdditionalJumpHosts().length + 1];
}
/**
*
* @throws JSchException
*/
public void createTunnel() throws JSchException {
int index = 0;
synchronized (sshChain) {
if (tunnelActive) {
return;
}
Session session;
sessions[index++] = session = createSession(jSchInstance, sshChain.getPrimaryJumpHost(), sshChain.getPrimaryJumpHost().getSSHPortNumber());;
for (JumpHost jh : sshChain.getAdditionalJumpHosts()) {
// Step 1: setup the forwarding FIRST.....
int assignedPort = session.setPortForwardingL(0, jh.getServer().getServerAddress().getPreferredAddress(), jh.getSSHPortNumber());
// Step 2: Create the session for the 'forwarded-to' host
sessions[index++] = session = createSession(jSchInstance, jh, assignedPort);
}
tunnelActive = true;
}
}
/**
*
* @return
*/
public boolean isTunnelActive() {
synchronized (sshChain) {
return tunnelActive;
}
}
/**
*
*/
public void closeTunnel() {
synchronized (sshChain) {
if (!tunnelActive) {
return;
}
for (int i = sessions.length - 1; i >= 0; i--) {
sessions[i].disconnect();
sessions[i] = null;
}
tunnelActive = false;
}
}
private final Map<String, Map<Integer, Integer>> availablePortForwarding = new HashMap<String, Map<Integer, Integer>>();
/**
*
* @param address
* @param portsToForward
* @return
* @throws JSchException
*/
public Map<Integer, Integer> forwardPorts(String address, int[] portsToForward) throws JSchException {
synchronized (sshChain) {
if (!tunnelActive) {
throw new IllegalStateException("Tunnel as not been setup ");
}
Map<Integer, Integer> availableMappings = availablePortForwarding.containsKey(address)
? availablePortForwarding.get(address)
: new HashMap<Integer, Integer>()
;
Map<Integer, Integer> portMap = new HashMap<Integer, Integer>();
Session session = sessions[0]; // The last jump host chain *SHOULD* be able to connect to the target host !
for (int portNo : portsToForward) {
if (availableMappings.containsKey(portNo)) {
portMap.put(portNo, availableMappings.get(portNo));
} else {
int assignedPort = session.setPortForwardingL(0, address, portNo);
portMap.put(portNo, assignedPort);
availableMappings.put(portNo, assignedPort);
}
}
availablePortForwarding.put(address, availableMappings);
return portMap;
}
}
public static class MyLogger implements com.jcraft.jsch.Logger {
static java.util.Hashtable name=new java.util.Hashtable();
static{
name.put(new Integer(DEBUG), "DEBUG: ");
name.put(new Integer(INFO), "INFO: ");
name.put(new Integer(WARN), "WARN: ");
name.put(new Integer(ERROR), "ERROR: ");
name.put(new Integer(FATAL), "FATAL: ");
}
public boolean isEnabled(int level){
return true;
}
public void log(int level, String message){
System.err.print(name.get(new Integer(level)));
System.err.println(message);
}
}
/**
* @param jSchInstance
* @param host
* @param assignedPort
*
* @return
*
* @throws JSchException
*/
private Session createSession(JSch jSchInstance, JumpHost host, int assignedPort) throws JSchException {
String preferredAddress = (host != null ? host.getServer().getServerAddress().getPreferredAddress() : "127.0.0.1");
int port = (host != null ? host.getSSHPortNumber() : assignedPort);
//Credentials credentials = host.getCredentials();
Session s = jSchInstance.getSession("<user>", preferredAddress, port);
s.setConfig("StrictHostKeyChecking", "no");
s.setPassword("<password>");
s.connect();
System.out.println("Created connection: " + host);
return s;
}
}