如何将jsch与代理命令一起用于端口转发

时间:2014-02-05 01:34:23

标签: java ssh jsch portforwarding

我想ssh到一个代理后面的机器,然后在我的java程序中执行一个portforwarding。 (为了能够ssh到盒子我应该首先ssh'ed到代理机器)。我通常在〜/ .ssh / config文件中包含以下条目:

ProxyCommand ssh proxyhost.com -t nc %h %p
IdentityFile /home/username/username_dsa_key

然后我运行以下命令来执行portforwarding以将hostmachine.com:54321映射到我的localhost:12345:

ssh -A -L12345:localhost:54321 hostmachine.com

现在我想用Jsch库做这些,但在会话中打开频道后我无法弄清楚如何连接到第二个主机:

        String proxyHost = "proxyhost.com";
        String host = "hostmachine.com";
        int lport = 12345;
        String rhost = "localhost";
        int rport = 54321;

        JSch jsch=new JSch();
        jsch.setKnownHosts("/home/{user}/.ssh/known_hosts");
        jsch.addIdentity("/home/{user}/.ssh/{user}_dsa_key",passphrase);

        Session session1 = jsch.getSession(user,proxyHost,22);
        session1.connect(3000);
        System.out.println(session1.isConnected());
        Channel channel = session1.openChannel("shell");

        ////// Now what? :)


        channel.disconnect();
        session1.disconnect();

有什么想法吗?

p.s:我已经在www.jcraft.com/jsch/examples/上阅读了这些样本,但不幸的是,他们在这种情况下没有帮助。

谢谢!

3 个答案:

答案 0 :(得分:3)

我建议你试试

http://www.jcraft.com/jsch/examples/JumpHosts.java.html

,但如果使用本机“ssh”命令很重要,您将找到该类 Proxy命令在jsch-0.1.50的Session.java的注释中,

/*
// setProxyCommand("ssh -l user2 host2 -o 'ProxyCommand ssh user1@host1 nc host2 22' nc %h %p")
public void setProxyCommand(String command){
  setProxy(new ProxyCommand(command));
}

class ProxyCommand implements Proxy {
  String command;
  Process p = null;
  InputStream in = null;
  OutputStream out = null;
  ProxyCommand(String command){
    this.command = command;
  }
  public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception {
    String _command = command.replace("%h", host);
    _command = _command.replace("%p", new Integer(port).toString());
    p = Runtime.getRuntime().exec(_command);
    in = p.getInputStream();
    out = p.getOutputStream();
  }
  public Socket getSocket() { return null; }
  public InputStream getInputStream() { return in; }
  public OutputStream getOutputStream() { return out; }
  public void close() {
    try{
      if(p!=null){
        p.getErrorStream().close();
        p.getOutputStream().close();
        p.getInputStream().close();
        p.destroy();
        p=null;
      }
    }
    catch(IOException e){
    }
  }
}
*/

答案 1 :(得分:2)

我在JSch上面写了一个能够“模仿”ProxyCommand配置的抽象:https://github.com/cronn-de/ssh-proxy

答案 2 :(得分:0)

这可以为您提供帮助。您会注意到,密钥验证设置为“否”,因此,如果您的网络不安全,则是一个安全问题(MITM攻击)。

 public static void sesionA(){
     try {
        sessionA = jSch.getSession(username, hostA);  
        Properties config = new Properties(); 
        config.put("StrictHostKeyChecking", "no");
        sessionA.setConfig(config);
        sessionA.setPassword(passwordA);
        sessionA.connect();


        if(sessionA.isConnected()) {
            System.out.println("Connected host A!");
            forwardedPort = 2222;
            sessionA.setPortForwardingL(forwardedPort, hostB, 22);      
        }

    } catch (JSchException e) {
        e.printStackTrace();
    }
 }

 public static void sesionB(){


    try {
        sessionB = jSch.getSession(username, "localhost", forwardedPort);

        Properties config = new Properties(); 
        config.put("StrictHostKeyChecking", "no");
        sessionB.setConfig(config);
        sessionB.setPassword(passwordB);
        sessionB.connect();

          if(sessionB.isConnected()) {
             System.out.println("Connected host B!");

             Channel channel = sessionB.openChannel("exec");

您还可以使用JSCH官方示例,并执行以下操作以避免出现有关键和其他内容的提示消息:

 UserInfo ui = new MyUserInfo(){
    public void showMessage(String message){
      JOptionPane.showMessageDialog(null, message);
    }

    @SuppressWarnings("unused")
    public boolean promptYesNo(String message){
        Object[] options={ "yes", "no" };
        int foo = 0;
        return foo==0;     // promptYesNo library method. Return 0 to avoid message
      }  

  };

您必须考虑一下MITM攻击,如果您确定自己是网络,请使用此代码。如果您不验证密钥,专家级的脚本孩子会偷走您的信用凭证。