Wie eine Verbindung zu FTPS-server mit Daten-Verbindung mit der gleichen TLS-Sitzung?
Umgebung: ich bin mit Sun Java JDK 1.8.0_60 auf 64-bit-Windows-7, mit Spring Integration 4.1.6 (intern angezeigt wird, verwenden Sie Apache Commons Net 3.3 FTPS-Zugang).
Ich bin versucht zu integrieren mit unserer Applikation für einen automatischen download von unserem client der FTPS-server. Habe ich erfolgreich getan, mit SFTP-Server mit Spring-Integration ohne Probleme für die anderen clients ohne Probleme, aber dies ist das erste mal, das ein client benötigt, hat uns die Verwendung von FTPS und bekommen es zu verbinden ist schon sehr rätselhaft. Während in meiner realen Anwendung, die ich bin Konfiguration der Spring Integration mit XML-beans, um zu versuchen zu verstehen, was nicht funktioniert bin ich mit dem folgenden test-code (obwohl ich bin Anonymisierung der tatsächlichen host/username/Passwort):
final DefaultFtpsSessionFactory sessionFactory = new DefaultFtpsSessionFactory();
sessionFactory.setHost("XXXXXXXXX");
sessionFactory.setPort(990);
sessionFactory.setUsername("XXXXXXX");
sessionFactory.setPassword("XXXXXXX");
sessionFactory.setClientMode(2);
sessionFactory.setFileType(2);
sessionFactory.setUseClientMode(true);
sessionFactory.setImplicit(true);
sessionFactory.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
sessionFactory.setProt("P");
sessionFactory.setProtocol("TLSv1.2");
sessionFactory.setProtocols(new String[]{"TLSv1.2"});
sessionFactory.setSessionCreation(true);
sessionFactory.setCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"});
final FtpSession session = sessionFactory.getSession();
//try {
final FTPFile[] ftpFiles = session.list("/");
logger.debug("FtpFiles: {}", (Object[]) ftpFiles);
//} catch (Exception ignored ) {}
session.close();
Mir läuft dieser code mit -Djavax.net.debug=all
alle zu erhalten, wird die TLS-debugging-Informationen gedruckt.
Haupt - "control" - Verbindung mit dem FTPS-server funktioniert gut, aber wenn er versucht, öffnen Sie den data-Anschluss für die Liste (oder eine andere Daten-Verbindung, die ich ausprobiert habe), bekomme ich eine javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
, verursacht durch java.io.EOFException: SSL peer shut down incorrectly
. Wenn ich die Auskommentierung des Schluckens-exceptions catch-block, um die session.list
Befehl, dann kann ich sehen (obwohl die javax.net.die debug-Ausgabe), dass den server gesendet, die folgende Meldung nach der Ablehnung der Datenverbindung SSL-handshake:
main, READ: TLSv1.2 Application Data, length = 129
Padded plaintext after DECRYPTION: len = 105
0000: 34 35 30 20 54 4C 53 20 73 65 73 73 69 6F 6E 20 450 TLS session
0010: 6F 66 20 64 61 74 61 20 63 6F 6E 6E 65 63 74 69 of data connecti
0020: 6F 6E 20 68 61 73 20 6E 6F 74 20 72 65 73 75 6D on has not resum
0030: 65 64 20 6F 72 20 74 68 65 20 73 65 73 73 69 6F ed or the sessio
0040: 6E 20 64 6F 65 73 20 6E 6F 74 20 6D 61 74 63 68 n does not match
0050: 20 74 68 65 20 63 6F 6E 74 72 6F 6C 20 63 6F 6E the control con
0060: 6E 65 63 74 69 6F 6E 0D 0A nection..
Was scheint passiert zu sein (und dies ist meine erste Zeit Umgang mit FTPS, obwohl ich schon behandelt mit reinem FTP vor) ist, dass der Weg, der server sorgt für die Authentifizierung und Verschlüsselung über das control-und Daten-verbindungen ist, dass nach einem "normalen" TLS-Verbindung, um die Kontroll-Verbindung und die Authentifizierung passiert es, jede Datenverbindung benötigt der client eine Verbindung herstellen mit der gleichen TLS-Sitzung. Das macht Sinn für mich, wie es sein soll funktionieren, aber die Apache Commons Net FTPS Umsetzung scheint es nicht zu tun. Es scheint zu versuchen, um eine neue TLS-Sitzung, und damit der server lehnt den Versuch.
Basierend auf diese Frage über die Wiederaufnahme von SSL-Sitzungen, die in JSSE, es scheint, dass Java übernimmt oder erfordert eine andere Sitzung für jeden host/post Kombination. Meine Hypothese ist, dass seit dem FTPS-data-Verbindung auf einem anderen port als die Kontroll-Verbindung, es findet nicht die bestehende session und wird versuchen, eine neue, so schlägt die Verbindung fehl.
Ich sehe im wesentlichen drei Möglichkeiten:
- Der server wird nicht nach dem FTPS-standard, welche die gleichen TLS-Sitzung auf den Daten-port auf den control-port. Ich kann die Verbindung zum server in Ordnung (mit der gleichen host/user/Passwort wie ich versuche, in meinem code) mit FileZilla 3.13.1. Der server identifiziert sich selbst als "FileZilla Server 0.9.53 beta" bei der Anmeldung, so ist dies vielleicht eine Art von proprietären FileZilla Art und Weise, Dinge zu tun, und es ist etwas seltsam ich tun müssen, um zu überzeugen Java zur Nutzung der gleichen TLS-Sitzung.
- Die Apache Commons Net-client nicht wirklich Folgen Sie den FTPS-standard, und erlaubt nur eine Teilmenge, die nicht für die Sicherung der Daten-verbindungen. Dies scheint seltsam, wie es scheint der standard-Weg in Verbindung mit FTPS aus in Java.
- Ich bin völlig fehlt etwas und Fehldiagnose.
Ich würde schätzen, jede Richtung können Sie, wie die Verbindung zu dieser Art von FTPS-server. Danke.
InformationsquelleAutor Peter Cooper Jr. | 2015-09-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
In der Tat einige FTP(S) Server erforderlich ist, dass die TLS/SSL-session wird wiederverwendet für die Daten-Verbindung. Dies ist eine Sicherheitsmaßnahme, durch die der server überprüfen kann, dass die Daten-Verbindung verwendet wird, die von den gleichen client wie die Kontrolle der Verbindung.
Einige Referenzen für gängige FTP-Server:
NoSessionReuseRequired
- Richtlinie)Was Ihnen helfen kann mit der Umsetzung ist, dass Cyberduck FTP(S) - client unterstützt die TLS/SSL-Sitzung wiederzuverwenden, und es verwendet die Apache Commons Net library:
https://trac.cyberduck.io/ticket/5087 - Reuse-Session-key, die auf Daten-Verbindung
Sehen, seine
FTPClient.java
- code (erweitert die Commons-NetFTPSClient
), insbesondere seine überschreiben des_prepareDataSocket_
Methode:Scheint es, dass die
_prepareDataSocket_
Methode wurde Hinzugefügt, um Commons NetFTPSClient
speziell zu ermöglichen, die TLS/SSL session reuse Umsetzung:https://issues.apache.org/jira/browse/NET-426
Eine native Unterstützung für die Wiederverwendung ist noch ausstehend:
https://issues.apache.org/jira/browse/NET-408
Brauchen Sie offensichtlich zu überschreiben, die Spring Integration
DefaultFtpsSessionFactory.createClientInstance()
um die Rückgabe Ihrer benutzerdefiniertenFTPSClient
Umsetzung mit der Sitzung der Wiederverwendung unterstützen.Die oben genannte Lösung funktioniert nicht auf Ihrem eigenen mehr, seit JDK 8u161.
Laut JDK 8u161 Update Release Notes (und die Antwort von @Laurent):
I. e., rufen Sie diese, um das problem zu beheben:
Obwohl dies sollte als workaround nur. Ich weiß nicht, eine richtige Lösung.
Sie sind herzlich willkommen. Hatte ich eigentlich das gleiche problem in der Vergangenheit (nur in C++/OpenSSL, ich weiß es nicht Java), so dass ich wusste, was google.
Weiß nicht, warum, aber das funktioniert mit openjdk version "1.8.0_151" und arbeitet nicht mit openjdk version "1.8.0_161"
eine Menge Dinge wurden verändert w werden.r.t. SSL im JDK 1.8.0_161 finden Sie unter oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html
Es gibt eine separate Frage, die über Probleme in 1.8.0_161: stackoverflow.com/q/49257998/850848
InformationsquelleAutor Martin Prikryl
Können Sie diese SSLSessionReuseFTPSClient Klasse :
Und Mit openJDK 1.8.0_161 :
Müssen wir setzen :
laut
http://www.oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html
Hinzugefügt, TLS-session-hash-und extended-master-secret-Erweiterung unterstützen
Im Falle von Kompatibilitätsproblemen, eine Anwendung kann deaktivieren Sie die Verhandlung dieser Erweiterung durch das setzen der System-Eigenschaft jdk.tls.useExtendedMasterSecret auf false in der JDK
Können Sie mir erklären, wie es funktioniert ? Ich ersetzen FTPSClient von SSLReuseSessionFTPSClient aber es ändert sich nichts
sollte dies funktionieren, setzen Sie die Eigenschaft system ?
SSLSessionReuseFTPSClient ftpsClient = null; try { ftpsClient = new SSLSessionReuseFTPSClient(); ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true)); ...
Vielen Dank für Ihre Antwort, habe ich versucht, dieses : noelshack.com/2019-04-3-1548249527-ftpsclientproblem.png, Aber es endete die gleiche Weise, wie FTPSClient haben. Ich Kann nicht herausfinden, wie es funktioniert.
Ich habe einen Haltepunkt in prepareDataSocket - Methode, aber es scheint, wie mein code nicht hinein gehen.
InformationsquelleAutor Laurent Grousset
Machen Martin Prikryl Vorschlag für mich arbeiten, ich hatte zum speichern der Schlüssel nicht nur unter
socket.getInetAddress().getHostName()
aber auch untersocket.getInetAddress().getHostAddress()
.(Lösung gestohlen hier.)
InformationsquelleAutor NotX