Comment faire pour se connecter au serveur FTPS avec la connexion de données à l'aide de la même session TLS?
De l'environnement: je suis à l'aide de Sun Java JDK 1.8.0_60 sur une version 64 bits de Windows 7, l'utilisation de Spring Integration 4.1.6 (qui à l'interne s'affiche à l'utilisation d'Apache Commons Net de 3,3 pour les PTS d'accès).
Je suis d'essayer de l'intégrer à notre demande un téléchargement automatique de notre client FTP server. Je l'ai fait avec tant de succès par SFTP serveurs à l'aide de Spring Integration, sans aucun problème pour d'autres clients sans problèmes, mais c'est la première fois qu'un client nous a conduits à utiliser FTPS, et de le faire pour se connecter a été très surprenant. Alors que dans mon application, je suis à la configuration de Spring Integration à l'aide de XML haricots, pour essayer de comprendre ce qui ne marche pas, je suis en utilisant le test code suivant (même si je suis de préservation de l'anonymat de l'hôte/nom d'utilisateur/mot de passe):
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();
J'exécute ce code avec -Djavax.net.debug=all
pour obtenir toutes les TLS informations de débogage imprimé.
La principale "control" connexion au serveur FTPS fonctionne bien, mais quand il tente d'ouvrir la connexion de données pour la liste (ou de toute autre connexion de données, j'ai essayé), j'obtiens un javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
, causée par java.io.EOFException: SSL peer shut down incorrectly
. Si je décommentez la déglutition-exceptions bloc catch autour de la session.list
commande, alors je peux voir (bien que le javax.net.la sortie de débogage) que le serveur a envoyé le message suivant après avoir rejeté la connexion de données handshake SSL:
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..
Ce qui semble être le cas (et c'est ma première fois avec FTPS, bien que je l'ai traité avec du simple client FTP), c'est que la manière dont le serveur assure l'authentification et le chiffrement à la fois sur le contrôle et les connexions de données est que, après un "normal" connexion TLS pour établir la connexion de contrôle et d'authentification qui s'y passe à chaque connexion de données nécessite le client pour se connecter avec le même session TLS. Pour moi c'est logique que la façon dont il est censé être le travail, mais l'Apache Commons Net FTPS mise en œuvre ne semble pas être le faire. Il semble être en essayant d'établir une nouvelle session TLS, et donc, le serveur rejette la tentative.
Basé sur cette question sur la reprise des sessions SSL dans JSSE, il semble que Java suppose ou implique une session différente pour chaque hôte/post combinaison. Mon hypothèse est que, depuis le FTPS connexion de données est sur un autre port que le port de la connexion de contrôle, il n'est pas de trouver de la session existante et tente d'en établir un nouveau, de sorte que la connexion échoue.
Je vois trois possibilités principales:
- Le serveur n'est pas à la suite de la FTPS standard, en exigeant la même session TLS sur le port de données que sur le port de contrôle. Je peux me connecter au serveur fines (à l'aide de la même host/user/mot de passe que je suis en train de l'utiliser dans mon code) à l'aide de FileZilla 3.13.1. Le serveur s'identifie lui-même comme "FileZilla Server 0.9.53 bêta" lors de la connexion, alors c'est peut-être une sorte de propriété FileZilla façon de faire les choses, et il y a quelque chose de bizarre, j'ai besoin de faire pour convaincre Java à utiliser la même session TLS.
- Apache Commons Net client ne fait pas suivre le FTPS standard, et ne permet qu'un sous-ensemble qui ne permet pas de sécuriser les connexions de données. Cela semble étrange, comme cela semble être le standard de connexion FTP à partir de l'intérieur de Java.
- Je suis complètement à côté de quelque chose et erreurs de diagnostic.
Je te remercie de n'importe quelle direction vous pouvez fournir quant à la façon de se connecter à ce genre de serveur FTPS. Merci.
OriginalL'auteur Peter Cooper Jr. | 2015-09-04
Vous devez vous connecter pour publier un commentaire.
En effet, certains de FTP(S) serveurs ne nécessitent que le TLS/SSL session est réutilisé pour la connexion de données. C'est une mesure de sécurité par laquelle le serveur peut vérifier que la connexion de données est utilisée par le même client que la connexion de contrôle.
Quelques références pour le commun des serveurs FTP:
NoSessionReuseRequired
directive)Ce qui peut vous aider avec la mise en œuvre est que Cyberduck FTP(S) client prend en charge TLS/SSL session de réutilisation et il utilise Apache Commons Net-library:
https://trac.cyberduck.io/ticket/5087 - Réutilisation de la clé de Session de connexion de données
Voir son
FTPClient.java
code (s'étend Communes NetFTPSClient
), en particulier son remplacer_prepareDataSocket_
méthode:Il semble que la
_prepareDataSocket_
méthode a été ajouté aux Communes NetFTPSClient
spécifiquement pour permettre le TLS/SSL réutilisation des sessions de mise en œuvre:https://issues.apache.org/jira/browse/NET-426
Un support natif pour la réutilisation est toujours en attente:
https://issues.apache.org/jira/browse/NET-408
Vous aurez évidemment besoin de redéfinir le Printemps de l'Intégration
DefaultFtpsSessionFactory.createClientInstance()
de retourner votre personnaliséFTPSClient
de mise en œuvre de la réutilisation des sessions de soutien.La solution ci-dessus ne fonctionne pas sur son propre plus depuis le JDK 8u161.
Selon JDK 8u161 mise à Jour des Notes de Version (et le réponse par @Laurent):
I. e., vous pouvez appeler cette fonction pour régler le problème:
Bien que cela devrait être considéré comme une solution de contournement. Je ne sais pas une bonne solution.
Vous êtes les bienvenus. J'ai effectivement eu le même problème dans le passé (juste à C++/OpenSSL, je ne fais pas de Java), je savais donc que pour google.
Je ne sais pas pourquoi, mais c'est de travailler avec openjdk version "1.8.0_151" et de ne pas travailler avec openjdk version "1.8.0_161"
beaucoup de choses ont changé w.r.t. SSL dans le JDK 1.8.0_161, voir oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html
Il y a une autre question à propos des problèmes dans 1.8.0_161: stackoverflow.com/q/49257998/850848
OriginalL'auteur Martin Prikryl
Vous pouvez utiliser cette SSLSessionReuseFTPSClient classe :
Et Avec openJDK 1.8.0_161 :
Nous devons définir :
selon
http://www.oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html
Ajouté session TLS de hachage et de l'étendue de maître secret de support d'extension
En cas de problèmes de compatibilité, une application peut désactiver la négociation de cette extension par le réglage du Système de la Propriété jdk.tls.useExtendedMasterSecret à false dans le JDK
Pouvez-vous m'expliquer comment le faire fonctionner ? - Je remplacer FTPSClient par SSLReuseSessionFTPSClient mais ça ne change rien
cela devrait fonctionner, avez-vous mis le système de la propriété ?
SSLSessionReuseFTPSClient ftpsClient = null; try { ftpsClient = new SSLSessionReuseFTPSClient(); ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true)); ...
Merci pour votre réponse, j'ai essayé ceci : noelshack.com/2019-04-3-1548249527-ftpsclientproblem.png Mais il a fini de la même manière que FTPSClient fait. Je ne Peux pas comprendre comment il fonctionne.
J'ai ajouté un point d'arrêt dans prepareDataSocket méthode, mais il semble que mon code ne va pas dans ce
OriginalL'auteur Laurent Grousset
Pour faire de Martin Prikryl la suggestion de travailler pour moi, j'ai eu pour stocker la clé non seulement en vertu de
socket.getInetAddress().getHostName()
mais aussi en vertu desocket.getInetAddress().getHostAddress()
.(Solution volé ici.)
OriginalL'auteur NotX