使用SSHj进行SSH端口转发

我正在尝试创建一个隧道来使用支持SSH的防火墙后面的服务。 我想要一个完整的java解决方案,但我似乎无法让它工作。 我发现这个github剪辑并基于此我创建了以下代码以保持后台线程给我隧道:

// 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(); 

问题是,如果我连接到像’10 .0.3.96’这样的远程SSH服务器,它就不起作用了。 如果我在本地主机上使用本地SSH服务器,它将起作用。 我已经通过不同的配置运气和尝试调试,但我无法掌握SSHj包内发生了什么。

现在它不一定是SSHj解决方案,但这是首选,因为代码的其他部分是完全实现的并使用SSHj,我不想在一个项目中混合两个SSH包。

谢谢你的帮助。

尝试这样的事情。 它接收要连接的服务器列表。 它会将每个中间连接隧道传输到最后一个服务器。 我没有测试超过2台服务器,但它应该工作。 这个答案是从改编项目改编而来的。 您应该只需要导入才能使它在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()