通过JSch进行SSH隧道连接

我的目标是连接到防火墙后面的服务器(主机)。 我可以通过连接到网络中的另一个服务器(隧道)然后SSH到此服务器来访问此服务器。 但是我无法通过JSch实现相同的场景。

我无法使用以下代码工作,我为此目的编写了这些代码。 如果我在这里做任何蠢事,请告诉我。

public class JschExecutor { public static void main(String[] args){ JschExecutor t=new JschExecutor(); try{ t.go(); } catch(Exception ex){ ex.printStackTrace(); } } public void go() throws Exception{ StringBuilder outputBuffer = new StringBuilder(); String host="xxx.xxx.xxx.xxx"; // The host to be connected finally String user="user"; String password="passwrd"; int port=22; String tunnelRemoteHost="xx.xx.xx.xx"; // The host from where the tunnel is created JSch jsch=new JSch(); Session session=jsch.getSession(user, host, port); session.setPassword(password); localUserInfo lui=new localUserInfo(); session.setUserInfo(lui); session.setConfig("StrictHostKeyChecking", "no"); ProxySOCKS5 proxyTunnel = new ProxySOCKS5(tunnelRemoteHost, 22); proxyTunnel.setUserPasswd(user, password); session.setProxy(proxyTunnel); session.connect(30000); Channel channel=session.openChannel("exec"); ((ChannelExec)channel).setCommand("hostname"); channel.setInputStream(null); ((ChannelExec)channel).setErrStream(System.err); InputStream in=channel.getInputStream(); BufferedReader ebr = new BufferedReader(new InputStreamReader(in)); channel.connect(); while (true) { byte[] tmpArray=new byte[1024]; while(in.available()>0){ int i=in.read(tmpArray, 0, 1024); if(i<0)break; outputBuffer.append(new String(tmpArray, 0, i)).append("\n"); } if(channel.isClosed()){ System.out.println("exit-status: "+channel.getExitStatus()); break; } } ebr.close(); channel.disconnect(); session.disconnect(); System.out.println(outputBuffer.toString()); } class localUserInfo implements UserInfo{ String passwd; public String getPassword(){ return passwd; } public boolean promptYesNo(String str){return true;} public String getPassphrase(){ return null; } public boolean promptPassphrase(String message){return true; } public boolean promptPassword(String message){return true;} public void showMessage(String message){} } } 

上面的代码在session.connect(30000);上给出了以下例外session.connect(30000); 线。

 com.jcraft.jsch.JSchException: ProxySOCKS5: com.jcraft.jsch.JSchException: fail in SOCKS5 proxy at com.jcraft.jsch.ProxySOCKS5.connect(ProxySOCKS5.java:317) at com.jcraft.jsch.Session.connect(Session.java:231) at com.ukris.main.JschExecutor.go(JschExecutor.java:50) at com.ukris.main.JschExecutor.main(JschExecutor.java:19) Caused by: com.jcraft.jsch.JSchException: fail in SOCKS5 proxy at com.jcraft.jsch.ProxySOCKS5.connect(ProxySOCKS5.java:200) ... 3 more 

jsch上的SOCKS代理设置允许您连接到远程端上正在运行的代理服务器。 远程端的sshd 不会被视为SOCKS代理。 您需要做的是建立一个本地端口转发到您正在隧道连接的机器上的ssh端口,然后使用api建立到该系统的辅助ssh连接。

我已经采取了你的例子,并稍微重写它来完成这个:

 import com.jcraft.jsch.*; import java.io.*; public class JschExecutor2 { public static void main(String[] args){ JschExecutor2 t=new JschExecutor2(); try{ t.go(); } catch(Exception ex){ ex.printStackTrace(); } } public void go() throws Exception{ StringBuilder outputBuffer = new StringBuilder(); String host="firstsystem"; // First level target String user="username"; String password="firstlevelpassword"; String tunnelRemoteHost="secondlevelhost"; // The host of the second target String secondPassword="targetsystempassword"; int port=22; JSch jsch=new JSch(); Session session=jsch.getSession(user, host, port); session.setPassword(password); localUserInfo lui=new localUserInfo(); session.setUserInfo(lui); session.setConfig("StrictHostKeyChecking", "no"); // create port from 2233 on local system to port 22 on tunnelRemoteHost session.setPortForwardingL(2233, tunnelRemoteHost, 22); session.connect(); session.openChannel("direct-tcpip"); // create a session connected to port 2233 on the local host. Session secondSession = jsch.getSession(user, "localhost", 2233); secondSession.setPassword(secondPassword); secondSession.setUserInfo(lui); secondSession.setConfig("StrictHostKeyChecking", "no"); secondSession.connect(); // now we're connected to the secondary system Channel channel=secondSession.openChannel("exec"); ((ChannelExec)channel).setCommand("hostname"); channel.setInputStream(null); InputStream stdout=channel.getInputStream(); channel.connect(); while (true) { byte[] tmpArray=new byte[1024]; while(stdout.available() > 0){ int i=stdout.read(tmpArray, 0, 1024); if(i<0)break; outputBuffer.append(new String(tmpArray, 0, i)); } if(channel.isClosed()){ System.out.println("exit-status: "+channel.getExitStatus()); break; } } stdout.close(); channel.disconnect(); secondSession.disconnect(); session.disconnect(); System.out.print(outputBuffer.toString()); } class localUserInfo implements UserInfo{ String passwd; public String getPassword(){ return passwd; } public boolean promptYesNo(String str){return true;} public String getPassphrase(){ return null; } public boolean promptPassphrase(String message){return true; } public boolean promptPassword(String message){return true;} public void showMessage(String message){} } } 

此代码的作用是创建一个本地端口转发到目标系统上的ssh端口,然后通过它连接。 运行hostname命令说明它确实在转发到的系统上运行。