【问题标题】:How to use jsch with ProxyCommands for portforwarding如何使用带有代理命令的 jsch 进行端口转发
【发布时间】:2014-03-01 06:44:26
【问题描述】:

我想通过 ssh 连接到代理后面的机器,然后在我的 java 程序中进行端口转发。 (为了能够 ssh 到盒子,我应该先 ssh 到代理机器)。我通常通过在我的 ~/.ssh/config 文件中包含以下条目来做到这一点:

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

然后我运行以下命令进行端口转发,将 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/ 中的示例,但不幸的是它们在这种情况下没有帮助。

谢谢!

【问题讨论】:

    标签: java ssh jsch portforwarding


    【解决方案1】:

    我建议你试试

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

    ,但如果使用本机“ssh”命令很重要,你会找到类 jsch-0.1.50的Session.java的注释中的ProxyCommand,

    /*
    // 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){
        }
      }
    }
    */
    

    【讨论】:

    • 谢谢!我认为它最终会起作用,但我最终只是从 java 执行 shell ssh 命令。不幸的是,对于这种情况,jsch 有点太复杂了,我找不到一个不需要完全传递 dsa_key 并且不要求输入密码的好例子。
    【解决方案2】:

    这可以帮助你。您注意到密钥验证设置为“否”,因此如果您的网络不安全,这是一个安全问题(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 攻击,如果您确定自己是网络,请使用此代码。如果您不验证密钥,专家脚本小子可能会窃取您的凭证。

    【讨论】:

    • 以上代码不完整。 forwardedPort 不会被 sessionB() 调用。
    【解决方案3】:

    我在 JSch 之上编写了一个抽象,它能够“模拟”ProxyCommand 配置:https://github.com/cronn/ssh-proxy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-02
      • 2016-09-17
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2016-01-29
      • 2015-12-21
      相关资源
      最近更新 更多