SSH port fowarding with SSHj

后端 未结 1 1797
鱼传尺愫
鱼传尺愫 2021-01-07 00:13

I am trying to create a tunnel to use a service behind a firewall, that supports SSH. I wanted a complete solution in java, but I cannot seem to get it to work. I found this

1条回答
  •  离开以前
    2021-01-07 01:17

    Try something like this. It takes in a list of servers to connect to. It will tunnel each intermediate connection to the last server. I have not tested with more than 2 servers, but it should work. This answer was adapted from the overthere project and written in groovy. You should only need imports to get it working in groovyconsole.

    @Grab(group='net.schmizz', module='sshj', version='0.8.1')
    @Grab(group='org.bouncycastle', module='bcprov-jdk16', version='1.46')
    
    //the sequence of hosts that the connections will be made through
    def hosts = ["server1", "server2"]
    //the starting port for local port forwarding
    def startPort = 2222
    //username for connecting to all servers
    def username = 'user'
    def pw = 'pass'
    
    //--------------------------------------------------------------------------//
    
    final TunnelPortManager PORT_MANAGER = new TunnelPortManager()
    
    //list of all active port forwarders
    List portForwarders = []
    
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    
    /**
     *  Established the actual port forwarder 
     */
    class PortForwarder extends Thread implements Closeable {
        private final SSHClient sshClient;
        private final InetSocketAddress remoteAddress;
        private final ServerSocket localSocket;
        private CountDownLatch latch = new CountDownLatch(1);
    
        public PortForwarder(SSHClient sshClient, InetSocketAddress remoteAddress, ServerSocket localSocket) {
            this.sshClient = sshClient;
            this.remoteAddress = remoteAddress;
            this.localSocket = localSocket;
        }
    
        private static String buildName(InetSocketAddress remoteAddress, Integer localPort) {
            return "SSH local port forward thread [${localPort}:${remoteAddress.toString()}]"
        }
    
        @Override
        public void run() {
            LocalPortForwarder.Parameters params = new LocalPortForwarder.Parameters("127.0.0.1", localSocket.getLocalPort(),
                    remoteAddress.getHostName(), remoteAddress.getPort());
            LocalPortForwarder forwarder = sshClient.newLocalPortForwarder(params, localSocket);
            try {
                latch.countDown();
                forwarder.listen();
            } catch (IOException ignore) {/* OK. */}
        }
    
        @Override
        public void close() throws IOException {
            localSocket.close();
            try {
                this.join();
            } catch (InterruptedException e) {/* OK.*/}
        }
    }
    
    /**
     *  Will hand out local ports available for port forwarding
     */
    class TunnelPortManager {
        final int MAX_PORT = 65536
    
        Set portsHandedOut = new HashSet()
    
        ServerSocket leaseNewPort(Integer startFrom) {
            for (int port = startFrom; port < MAX_PORT; port++) {
                if (isLeased(port)) {
                    continue;
                }
    
                ServerSocket socket = tryBind(port);
                if (socket != null) {
                    portsHandedOut.add(port);
                    println "handing out port ${port} for local binding"
                    return socket;
                }
            }
            throw new IllegalStateException("Could not find a single free port in the range [${startFrom}-${MAX_PORT}]...");
        }
    
        synchronized void returnPort(ServerSocket socket) {
            portsHandedOut.remove(socket.getLocalPort());
        }
    
        private boolean isLeased(int port) {
            return portsHandedOut.contains(port);
        }
    
        protected ServerSocket tryBind(int localPort) {
            try {
                ServerSocket ss = new ServerSocket();
                ss.setReuseAddress(true);
                ss.bind(new InetSocketAddress("localhost", localPort));
                return ss;
            } catch (IOException e) {
                return null;
            }
        }
    }
    
    
    PortForwarder startForwarder(PortForwarder forwarderThread) {
        forwarderThread.start();
        try {
            forwarderThread.latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return forwarderThread;
    }
    
    
    SSHClient getSSHClient(username, pw, String hostname, int port=22){
        SSHClient client = new SSHClient()
        client.addHostKeyVerifier(new PromiscuousVerifier())
        client.connect(hostname, port)
        client.authPassword(username, pw)
        return client
    }
    
    int hostCount = hosts.size()
    String hostname = hosts[0]
    
    SSHClient client = getSSHClient(username, pw, hostname)
    println "making initial connection to ${hostname}"
    
    Session session
    
    //create port forwards up until the final
    for (int i=1; i ${response}"
    
    portForwarders.each { pf ->
        pf.close()
    }
    
    session.close()
    client.disconnect()
    

    0 讨论(0)
提交回复
热议问题