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

FTP4j fails to use FTPES (TLS session of data connection has not resumed or the session does not match the control connection)

我正在尝试使用 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 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 配置的屏幕截图:

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

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

这通过使攻击者更难 hijack a data connection.

来提高安全性

我不知道,如果 ftp4j 支持重用这个。

替代解决方案是:

  • 使用来自 Apache Commons Net 库的 Java FTP 客户端。虽然它本身不支持重用,但很容易添加支持。参见
  • 由于您拥有 FTP 服务器,您可以禁用重用要求。请参阅 使用 PROT P 选项时需要在数据连接上恢复 TLS 会话(在您的屏幕截图上)。虽然如前所述,但对安全性有一定的影响。

尝试删除此复选框,它对我有帮助。