Try something like this. It accepts a list of servers to connect. It will tunnel every intermediate connection to the last server. I have not tested more than two servers, but it should work. This answer has been adapted from the overthere project and written in groovy. They only need to import to make it work 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<PortForwarder> 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<Integer> 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<hostCount; i++){ hostname = hosts[i] println "creating connection to ${hostname}" ServerSocket ss = PORT_MANAGER.leaseNewPort(startPort) InetSocketAddress remoteAddress = new InetSocketAddress(hostname, 22) PortForwarder forwarderThread = new PortForwarder(client, remoteAddress, ss) forwarderThread = startForwarder(forwarderThread) session = client.startSession() println "adding port forward from local port ${ss.getLocalPort()} to ${remoteAddress.toString()}" portForwarders.add(forwarderThread) client = getSSHClient(username, pw, "127.0.0.1", ss.getLocalPort()) } session = client.startSession() //shut down the running jboss using the script Command cmd = session.exec("hostname") String response = IOUtils.readFully(cmd.getInputStream()).toString() cmd.join(5, TimeUnit.SECONDS) println "response -> ${response}" portForwarders.each { pf -> pf.close() } session.close() client.disconnect()
Scott
source share