java - FTP4j 无法使用 FTPES(数据连接的 TLS session 未恢复或 session 与控制连接不匹配)

标签 java ftp filezilla ftps ftp4j

我正在尝试使用 ftp4j 库从带有 TLS 的 FileZilla FTP 服务获取文件列表。

import it.sauronsoftware.ftp4j.FTPClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Arrays;

public class FTP {

    public static void main(String args[]) throws Exception {
        System.setProperty("http.protocols", "TLSv1,TLSv1.1,TLSv1.2"); 
        //tried to avoid closing connection during the handshake

        //load and set certificate
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream("mykeystore.jks"), "root12".toCharArray());

        FTPClient client = new FTPClient();

        SSLContext sslContext = null;
        try {
            javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory
                    .getInstance(javax.net.ssl.KeyManagerFactory
                            .getDefaultAlgorithm());
            tmf.init(keyStore);
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }

        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        client.setSSLSocketFactory(sslSocketFactory);
        client.setSecurity(FTPClient.SECURITY_FTPES);

        client.setCharset("UTF-8");
        client.setPassive(true);
        String[] arg = client.connect("localhost", 21);
        System.out.println(Arrays.toString(arg));

        client.login("admin", "pass"); //OK
        client.noop(); // aka Ping is OK
        String s = client.currentDirectory(); //OK
        client.changeDirectory("/"); //OK
        String[] files = client.listNames(); //Exception here
        System.out.println(Arrays.toString(files));
        client.disconnect(true);
    }
}

我有一个异常(exception)

Exception in thread "main" it.sauronsoftware.ftp4j.FTPException [code=450, message= TLS session of data connection has not resumed or the session does not match the control connection] at it.sauronsoftware.ftp4j.FTPClient.listNames(FTPClient.java:2407) at FTP.main(FTP.java:49)

我尝试使用主动模式,但它也无济于事(在 ping 命令后失败)

Exception in thread "main" it.sauronsoftware.ftp4j.FTPException [code=421, message= Rejected command, requested IP address does not match control connection IP.]

您能回答我哪里做错了吗,或者 ftp4j 库实际上支持 FTPES 和 TLS 吗?

FileZilla 服务器 TLS 配置的屏幕截图:

FileZilla TLS configuration

最佳答案

ftp4j 库支持 FTPS/TLS。否则,您一开始就不会收到错误。

FileZilla FTP服务器是FTP服务器之一,它要求客户端重用来自FTP控制连接的TLS/SSL session 进行数据连接:
https://svn.filezilla-project.org/filezilla?view=revision&revision=6661

这通过使攻击者更难获得 hijack a data connection 来提高安全性.

不过,我不知道 ftp4j 是否支持重用它。

替代解决方案是:

  • 使用 Apache Commons Net 库中的 Java FTP 客户端。虽然它本身不支持重用,但很容易添加支持。参见 How to connect to FTPS server with data connection using same TLS session?
  • 由于您拥有 FTP 服务器,因此可以禁用重用要求。请参阅使用 PROT P 时需要在数据连接上恢复 TLS session 选项(在您的屏幕截图上)。虽然如上所述,但它对安全性有一定影响。

关于java - FTP4j 无法使用 FTPES(数据连接的 TLS session 未恢复或 session 与控制连接不匹配),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47227095/

相关文章:

linux - 如何通过filezilla客户端下载文件?

c# - FTPS (SSL) 的证书验证/安装?

java - 即使显示复选框,单击复选框也无法使用 Selenium webdriver

从 FTP 服务器检索 Java 文件

java - 使用 Java 进行命名实体识别

java - Java从FTP服务器递归下载所有文件夹

linux - 从 Google Compute Engine 连接到 FTP 服务器时,获取 "I won' t open a connection to”

ssis - 将今天的文件从本地目录上传到 SFTP 服务器

Java UI 程序随机卡住

Java内部类和静态嵌套类