无法使用jcraft JSch连接到SFTP

时间:2016-11-18 16:14:04

标签: java ssh sftp jsch

我正在尝试使用jcraft版本0.1.52通过ssh jump-host proxy连接到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' 
  1. 这是我正在运行的代码
  2. 代码:

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

    如果有人可以提供帮助,真的很感激。谢谢!

1 个答案:

答案 0 :(得分:0)

这里的方法对我来说很好。

基本上它是一条隧道 你的sftp主机。它通过jumphost或隧道主机创建一个到sftp主机的隧道,并通过sftpChannel从这个隧道的" localhost"中获取文件。港口(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);
        }
    }
}