JSch - 使用多个Jumphosts进行端口转发

时间:2016-02-04 17:55:32

标签: java ssh jsch portforwarding

要调试远程AS / 400系统,我需要设置一个运行超过2个或更多跳转主机的SSH连接来访问目标系统。我已完成大部分工作(比如调整JTopen工具箱端口以便能够在本地覆盖它们。

唯一的事情是,我似乎无法让JSch通过多个主机将本地主机端口连接到AS / 400上的目标端口。

示例

[local-port 1234] ==> [ssh-jumphost-1] ===> [ssh-jumphost-2] ===> [as400-port 8470]

我尝试并玩弄了JSch示例,并且可以使ForwardL和Jumphost示例正常工作,但在组合这些时(设置隧道,然后将as / 400端口转发设置为第一个主机)

我也尝试使用SSH完成这项工作(看看是否可行),但也没有运气。

问题是: 1.我尝试做什么都可行?或者这是不可能实现的? 2. JSch不适合这份工作吗?是否应该使用另一个Java SSH2库取得更大成功?

如果需要,我也可以发布一些代码。

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;
    }
}

0 个答案:

没有答案