Umgebung: Ich verwende Sun Java JDK 1.8.0_60 unter 64-Bit-Windows 7 mit Spring Integration 4.1.6 (das intern scheinbar Apache Commons Net 3.3 für FTPS-Zugriff verwendet).
Ich versuche, mit unserer Anwendung einen automatischen Download vom FTP-Server unseres Kunden zu integrieren. Ich habe es erfolgreich mit SFTP-Servern mit Spring Integration ohne Probleme für andere Clients ohne Probleme gemacht, aber dies ist das erste Mal, dass ein Client uns FTPS verwendet hat, und es ist sehr verwirrend, es zu verbinden. Während ich in meiner realen Anwendung Spring Integration mit XML-Beans konfiguriere, versuche ich zu verstehen, was nicht funktioniert. Ich verwende den folgenden Testcode (obwohl ich den tatsächlichen Host / Benutzername / Passwort hier anonymisiere):
%Vor% Ich führe diesen Code mit -Djavax.net.debug=all
aus, um alle TLS-Debuginformationen auszudrucken.
Die "control" Hauptverbindung zum FTPS-Server funktioniert gut, aber wenn ich versuche, die Datenverbindung für die Liste (oder irgendeine andere Datenverbindung, die ich ausprobiert habe) zu öffnen, bekomme ich javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
, verursacht durch% Code%. Wenn ich den Schluck-Ausnahmen-Fangblock um den java.io.EOFException: SSL peer shut down incorrectly
-Befehl auskommentiere, kann ich sehen (obwohl die javax.net.debug-Ausgabe), dass der Server die folgende Nachricht gesendet hat, nachdem er den Datenverbindungs-SSL-Handshake zurückgewiesen hat:
Was anscheinend geschieht (und dies ist mein erstes Mal, dass ich mit FTPS zu tun habe, obwohl ich mich vorher mit einfachem FTP beschäftigt habe), ist die Art, wie der Server Authentifizierung und Verschlüsselung sowohl über die Kontroll- als auch die Datenverbindungen gewährleistet Eine "normale" TLS-Verbindung zum Herstellen der Steuerverbindung und Authentifizierung findet dort statt. Jede Datenverbindung erfordert, dass sich der Client mit derselben TLS-Sitzung verbindet. Das macht für mich Sinn, wie es funktionieren soll, aber die Apache Commons Net FTPS-Implementierung scheint das nicht zu tun. Es scheint zu versuchen, eine neue TLS-Sitzung einzurichten, und daher lehnt der Server den Versuch ab.
Basierend auf der Frage zur Wiederaufnahme von SSL-Sitzungen in JSSE scheint es so zu sein, dass Java für jede Sitzung eine andere Sitzung voraussetzt oder erfordert Host / Post-Kombination. Meine Hypothese ist, dass, da die FTPS-Datenverbindung auf einem anderen Port als die Steuerverbindung ist, sie die vorhandene Sitzung nicht findet und versucht, eine neue einzurichten, so dass die Verbindung fehlschlägt.
Ich sehe drei Hauptmöglichkeiten:
Ich würde mich über jede mögliche Richtung freuen, wie Sie sich mit dieser Art von FTPS-Server verbinden können. Danke.
Tatsächlich erfordern einige FTP (S) -Server, dass die TLS / SSL-Sitzung für die Datenverbindung wiederverwendet wird. Dies ist eine Sicherheitsmaßnahme, mit der der Server überprüfen kann, ob die Datenverbindung von demselben Client wie die Steuerverbindung verwendet wird.
Einige Referenzen für gängige FTP-Server:
Was Ihnen bei der Implementierung helfen kann, ist, dass der Cyberduck FTP (S) -Client die Wiederverwendung von TLS / SSL-Sitzungen unterstützt und Apache Commons Net-Bibliothek verwendet:
Ссылка - Sitzungsschlüssel für Datenverbindung erneut verwenden
Siehe FTPClient.java
code (erweitert Commons Net FTPSClient
), insbesondere dessen override von _prepareDataSocket_
Methode :
%Vor%
Es scheint, dass die _prepareDataSocket_
-Methode speziell zu Commons Net FTPSClient
hinzugefügt wurde, um die Implementierung der TLS / SSL-Sitzung wiederverwenden zu können:
Ссылка
Eine native Unterstützung für die Wiederverwendung steht noch aus:
Ссылка
Sie müssen die Spring Integration DefaultFtpsSessionFactory.createClientInstance()
natürlich überschreiben, um Ihre benutzerdefinierte FTPSClient
Implementierung mit der Unterstützung für die Sitzungswiederverwendung zurückzugeben.
Die obige Lösung funktioniert seit JDK 8u161 nicht mehr.
Laut Release-Informationen zum JDK 8u161-Update (und dem Antwort von @Laurent ):
TLS-Sitzungshash und erweiterte Master-Secret-Erweiterung wurde hinzugefügt
...
Im Falle von Kompatibilitätsproblemen kann eine Anwendung die Aushandlung dieser Erweiterung deaktivieren, indem sie die Systemeigenschaft
setztjdk.tls.useExtendedMasterSecret
auffalse
im JDK
Das heißt, Sie können dies aufrufen, um das Problem zu beheben:
%Vor%Dies sollte jedoch nur als Problemumgehung betrachtet werden. Ich kenne keine richtige Lösung.
Sie können diese SSLSessionReuseFTPSClient-Klasse verwenden:
%Vor%Und mit openJDK 1.8.0_161:
Wir müssen festlegen:
%Vor%nach Ссылка
TLS-Sitzungshash und erweiterte Master-Secret-Erweiterung wurde hinzugefügt
Im Falle von Kompatibilitätsproblemen kann eine Anwendung die Aushandlung dieser Erweiterung deaktivieren, indem sie die Systemeigenschaft jdk.tls.useExtendedMasterSecret im JDK auf false setzt
Tags und Links java ftp filezilla ftps apache-commons-net