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