3

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;
    }
}
  • Please edit your question to include the relevant source code. I assume the local->jumphost1 link is through jsch? How are you creating the jumphost1->jumphost2 link and the jumphost-2->as400 link? – Kenster Feb 04 '16 at 18:28
  • I added some code, as requested. The idea i had in mind was creating ssh session from one jumphost to the next (i used this as an example: http://www.jcraft.com/jsch/examples/JumpHosts.java.html). Once the tunnel is in place, i tried to setup port forwarding either to the first or last jump host, (see: http://www.jcraft.com/jsch/examples/PortForwardingL.java.html) When i then try to connect to the forwarded port from the localhost, i see no response, but i get no error either. If the tunnel isn't there, i expected something like 'connection refused' – Tiger-Lilly Feb 07 '16 at 13:30

0 Answers0