2016-11-18 77 views
1

我想通過使用jcraft版本0.1.52的ssh跳轉主機代理連接到SFTP位置。但得到「連接關閉外國主機」在我的代碼異常。我花了好足夠的時間在看文檔,但無法弄清楚的問題是什麼無法使用jcraft JSch連接到SFTP

2016-11-18 14:53:14,091 44977 [main] ERROR c.w.v.r.ftp.JschSftpConnect - 
    - com.jcraft.jsch.JSchException: connection is closed by foreign host 
     at com.jcraft.jsch.Session.connect(Session.java:269) 
     at com.jcraft.jsch.Session.connect(Session.java:183) 
     at com.x.y.ftp.JschSftpConnect.connect(JschSftpConnect.java:77) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

,因爲我能夠連接通過unix命令到SFTP服務器沒有與私鑰沒有問題。

sftp -o UserKnownHostsFile=/dev/null 
    -o StrictHostKeyChecking=no 
    -i /path/to/host/private-key-file 
    -o 'ProxyCommand=ssh 
     -o UserKnownHostsFile=/dev/null 
     -o StrictHostKeyChecking=no 
     -i /path/to/jumphost/private-key-file 
     -l jumphostuser jump.host.com nc sftp.host.com 22' 
  • 下面是我運行
  • 代碼代碼:

    import java.io.BufferedInputStream; 
    import java.io.BufferedOutputStream; 
    import java.io.File; 
    import java.io.FileOutputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import java.net.Socket; 
    import java.nio.file.FileSystems; 
    import java.nio.file.Files; 
    import java.nio.file.Path; 
    import java.util.Properties; 
    
    import org.apache.commons.lang3.exception.ExceptionUtils; 
    
    import com.jcraft.jsch.Channel; 
    import com.jcraft.jsch.ChannelSftp; 
    import com.jcraft.jsch.JSch; 
    import com.jcraft.jsch.Proxy; 
    import com.jcraft.jsch.Session; 
    import com.jcraft.jsch.SocketFactory; 
    
    public class JschSftpConnect { 
    
    
        public static void main(String args[]) { 
         String sftpHostKeyFilePath = "/path/to/host/private-key-file"; 
         String sftpHost="sftp.host.com"; 
         String sftpUser="user"; 
         String proxyHostName="jump.host.com"; 
         String proxyKeyPath ="/path/to/jumphost/private-key-file"; 
         String proxyUserName="jumphostuser"; 
    
         log.debug("Executing JSCH code....."); 
         try { 
    
          JSch jsch = new JSch(); 
    
          Path path = FileSystems.getDefault().getPath(sftpHostKeyFilePath); 
          byte[] filearray = Files.readAllBytes(path); 
    
          jsch.addIdentity("ID", filearray, null, null); 
          Session session = jsch.getSession(sftpUser, sftpHost, 22); 
          Properties props = new Properties(); 
          props.put("StrictHostKeyChecking", "no"); 
          session.setConfig(props); 
    
          String command = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i " 
           + localKeyFileDirectoryName + proxyKey + " -l " + proxyUserName + " " + proxyHostName 
           + " nc %h %p"; 
    
          session.setProxy(new JumpHostProxyCommand(command)); 
          log.debug("Connecting session ......................."); 
          session.connect(); 
          log.debug("Session openend ......................."); 
    
          Channel ch = session.openChannel("sftp"); 
          ch.connect(); 
          log.debug("SFTP channel connected ......................."); 
          ChannelSftp channelSftp = (ChannelSftp) ch; 
          channelSftp.cd("/"); 
    
          log.debug("Working directory is/......................."); 
    
          byte[] buffer = new byte[1024]; 
          BufferedInputStream bis = new BufferedInputStream(channelSftp.get("/some_file_.psv")); 
          File newFile = new File("some_file_.psv"); 
          OutputStream os = new FileOutputStream(newFile); 
          BufferedOutputStream bos = new BufferedOutputStream(os); 
          int readCount; 
          // System.out.println("Getting: " + theLine); 
          while ((readCount = bis.read(buffer)) > 0) { 
           // System.out.println("Writing: "); 
           bos.write(buffer, 0, readCount); 
          } 
          log.debug("File should have been written/......................."); 
    
          while (session != null) { 
           System.out.println("Killing the session"); 
           session.disconnect(); 
           bis.close(); 
           bos.close(); 
           System.exit(0); 
          } 
         } catch (Exception e) { 
          log.error(ExceptionUtils.getStackTrace(e)); 
         } 
        } 
    } 
    
    
    
    class JumpHostProxyCommand implements Proxy { 
    
        String command; 
        Process p = null; 
        InputStream in = null; 
        OutputStream out = null; 
    
        public JumpHostProxyCommand(String command) { 
         this.command = command; 
        } 
    
        public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception { 
    
    
         String cmd = command.replace("%h", host); 
         cmd = cmd.replace("%p", new Integer(port).toString()); 
    
         p = Runtime.getRuntime().exec(cmd); 
         log.debug("Process returned by proxy command {} , {}", command, p); 
         in = p.getInputStream(); 
         log.debug("Input stream returned by proxy {}", in); 
         out = p.getOutputStream(); 
         log.debug("Output stream returned by proxy {}", out); 
        } 
    
        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) { 
          e.printStackTrace(); 
         } 
        } 
    } 
    

    真的很感激,如果有人可以幫助。謝謝!

    +0

    通知connect()方法,而不是'調用Runtime.getRuntime()EXEC(命令);'它應該是'調用Runtime.getRuntime()EXEC(CMD);'太 –

    +0

    塞吉本納2,那是我現在編輯的帖子中的一個錯字。雖然很漂亮! – Techji

    回答

    0

    這裏的方法對我來說工作得很好。

    基本上它是一個隧道到 您的sftp主機。它通過jumphost或隧道主機創建一個到你的sftp主機的隧道,並通過sftpChannel從這個隧道「本地主機」端口(2222)抓取文件。 我已經通過兩個ssh主機測試過它。它工作正常。

    import com.jcraft.jsch.*; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 
    
    import java.io.IOException; 
    import java.nio.file.FileSystems; 
    import java.nio.file.Files; 
    import java.nio.file.Path; 
    import java.nio.file.Paths; 
    import java.util.Properties; 
    
    import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 
    
    public class JschSftpConnect { 
    
        public static final Logger log = LoggerFactory.getLogger(JschSftpConnect.class); 
        public static final com.jcraft.jsch.Logger sshLogger = new com.jcraft.jsch.Logger() { 
         public boolean isEnabled(int level) { 
          return true; 
         } 
    
         public void log(int level, String message) { 
          switch (level) { 
           case 0: 
            log.debug(message); 
            break; 
           case 1: 
            log.info(message); 
            break; 
           case 2: 
            log.warn(message); 
            break; 
           case 3: 
            log.error(message); 
            break; 
           case 4: 
            log.error(message); 
            break; 
           default: 
            break; 
    
          } 
         } 
        }; 
    
        public static void main(final String args[]) { 
         final String tunnelHostKey = "keyfile"; 
         final String tunnelHost = "sshTunnelHost"; 
         final String tunnelHostUser = "tunnelsshuser"; 
    
         final String sftpKey = "sftpKey"; 
         final String sftpHost = "sftpHost"; 
         final String sftpUser = "sftpuser"; 
    
         if (args.length >= 2) { 
          new Thread(new Runnable() { 
           @Override 
           public void run() { 
            try { 
             Session tunnelSesssion = 
               createSession(tunnelHostKey, tunnelHost, tunnelHostUser,22); 
    
             tunnelSesssion.setPortForwardingL 
               (2222,sftpHost,22); 
    
             Session sftpSession = 
               createSession(sftpKey, "localhost", sftpUser,2222); 
    
             ChannelSftp sftpChannel = 
               getChannel(sftpSession); 
    
             if (args.length >= 2) { 
              sftpChannel.cd(args[0]); 
    
              log.debug("Working directory is " + sftpChannel.pwd()); 
              getFileFromSftp(sftpChannel, args[1], args.length == 3 ? args[2] : args[1]); 
             } 
            } catch (Exception e) { 
             log.error(e.getMessage(), e); 
            } 
           } 
          }).start(); 
         } else { 
          log.info("usage: java JschSftpConnect -cp ... <sftp dir> <sftp infile> <optional out file>"); 
          System.exit(-1); 
         } 
        } 
    
        private static Session createSession(
          String keyFile, String host, String user,int port 
          ) throws IOException, JSchException { 
         JSch jsch = new JSch(); 
         JSch.setLogger(sshLogger); 
         Path path = FileSystems.getDefault().getPath(keyFile); 
         byte[] filearray = Files.readAllBytes(path); 
    
         jsch.addIdentity("ID", filearray, null, null); 
         Session session = jsch.getSession(user, host, port); 
         Properties props = new Properties(); 
         props.put("StrictHostKeyChecking", "no"); 
         session.setConfig(props); 
    
         session.setTimeout(1000); 
         session.connect(); 
         if (!session.isConnected()) { 
          throw new IOException("Session not connected"); 
         } 
         return session; 
        } 
    
        private static ChannelSftp getChannel(Session session)throws IOException, JSchException{ 
         Channel ch = session.openChannel("sftp"); 
         log.debug("SFTP channel connected ......................."); 
         ChannelSftp channelSftp = (ChannelSftp) ch; 
         channelSftp.connect(1000); 
         return channelSftp; 
        } 
    
        private static void getFileFromSftp(ChannelSftp channelSftp, String filename, String outFile) throws SftpException, IOException { 
         Path p = Paths.get(outFile != null ? outFile : "output"); 
         try { 
          Files.copy(channelSftp.get(filename), p, REPLACE_EXISTING); 
          log.debug("File '" + filename + "' is written"); 
          System.exit(0); 
         } catch (Exception e) { 
          log.error(e.getMessage(), e); 
         } 
        } 
    } 
    
    +0

    謝謝謝爾蓋。我可以看到你刪除了跳轉主機代理配置。更新後的代碼不適用於我的用例,因爲sftp連接是通過跳轉主機。 – Techji

    +0

    如果您想要創建一個與原始代碼有點不同的隧道。稍後我會更新代碼。 –

    +0

    @Techji我已經更新了答案。你可以通過隧道實現,就像我之前說過的那樣。它工作正常。 –

    相關問題