SSH port with SSHj

I am trying to create a tunnel to use a service behind a firewall that supports SSH. I wanted to get a complete solution in java, but I can't get it to work. I found this github snip and based on this I created the following code to save the background thread giving me the tunnel:

// property on surrounding class // static final SSHClient sshclient = new SSHClient(); Thread thread = new Thread(new Runnable() { @Override public void run() { try { String host = "10.0.3.96"; sshclient.useCompression(); sshclient.addHostKeyVerifier("30:68:2a:20:21:9f:c8:e8:ac:b4:a7:fc:2d:a7:d0:26"); sshclient.connect(host); sshclient.authPassword("messy", "messy"); if (!sshclient.isAuthenticated()) { throw new RuntimeException(String.format("Unable to authenticate against '%s'", host)); } Forward forward = new Forward(8111); InetSocketAddress addr = new InetSocketAddress("google.com", 80); SocketForwardingConnectListener listener = new SocketForwardingConnectListener(addr); sshclient.getRemotePortForwarder().bind(forward, listener); sshclient.getTransport().setHeartbeatInterval(30); HttpURLConnection con = (HttpURLConnection) new URL("http://localhost:8111").openConnection(); con.setRequestMethod("GET"); BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while( (line = reader.readLine()) != null) { System.out.println(line); } sshclient.getTransport().join(); } catch (IOException e) { e.printStackTrace(); } try { if (sshclient != null && sshclient.isConnected()) { sshclient.disconnect(); } } catch (IOException e) { e.printStackTrace(); } } }); thread.setDaemon(true); thread.start(); 

The problem is that if I connect to a remote SSH server, for example '10 .0.3.96 ', this will not work. If I use a local SSH server on my local host, it will work. I did various configurations with any luck and tried to debug, but I can’t understand what is going on inside the SSHj package.

Now this should not be a SSHj solution, but it would be preferable, since other parts of the code are fully implemented using SSHj, and I do not want to mix two SSH packages in one project.

Thanks for any help.

+2
java ssh port forwarding sshj
source share
1 answer

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() 
+1
source share

All Articles