¿Cómo conectarse al servidor FTPS con conexión de datos usando la misma sesión TLS?

Entorno: estoy usando Sun Java JDK 1.8.0_60 en Windows 7 de 64 bits, usando Spring Integration 4.1.6 (que internamente parece usar Apache Commons Net 3.3 para acceso FTPS).

Estoy intentando integrar con nuestra aplicación una descarga automática del servidor FTPS de nuestro cliente. Lo hice con éxito con los servidores SFTP usando Spring Integration sin ningún problema para otros clientes sin problemas, pero esta es la primera vez que un cliente nos ha requerido usar FTPS, y lograr que se conecte ha sido muy desconcertante. Mientras estoy en mi aplicación real, estoy configurando Spring Integration usando beans XML, para tratar de entender lo que no funciona, estoy usando el siguiente código de prueba (aunque estoy anonimizando el host / nombre de usuario / contraseña real aquí):

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();

Estoy ejecutando este código con-Djavax.net.debug=all para obtener toda la información de depuración de TLS impresa.

La conexión principal de "control" al servidor FTPS funciona bien, pero cuando intenta abrir la conexión de datos para la lista (o cualquier otra conexión de datos que haya intentado), obtengo unjavax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake, causado porjava.io.EOFException: SSL peer shut down incorrectly. Si descomento las excepciones para tragar, el bloque de captura alrededor delsession.list comando, entonces puedo ver (a través de la salida javax.net.debug) que el servidor envió el siguiente mensaje después de rechazar el protocolo de enlace SSL de conexión de datos:

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..

Lo que parece estar sucediendo (y esta es la primera vez que trato con FTPS, aunque he tratado con FTP simple antes) es que la forma en que el servidor garantiza la autenticación y el cifrado tanto en el control como en las conexiones de datos es que después de un "normal" La conexión TLS para establecer la conexión de control y la autenticación ocurre allí, cada conexión de datos requiere que el cliente se conecte con la misma sesión TLS. Esto tiene sentido para mí como se supone que debe funcionar, pero la implementación de Apache Commons Net FTPS no parece estar haciendo eso. Parece estar tratando de establecer una nueva sesión TLS, por lo que el servidor rechaza el intento.

Residencia enesta pregunta sobre la reanudación de sesiones SSL en JSSE, parece que Java asume o requiere una sesión diferente para cada combinación de host / publicación. Mi hipótesis es que, dado que la conexión de datos FTPS se encuentra en un puerto diferente al de la conexión de control, no encuentra la sesión existente y está tratando de establecer una nueva, por lo que la conexión falla.

Veo tres posibilidades principales:

El servidor no sigue el estándar FTPS al requerir la misma sesión TLS en el puerto de datos que en el puerto de control. Puedo conectarme bien al servidor (usando el mismo host / usuario / contraseña que estoy tratando de usar en mi código) usando FileZilla 3.13.1. El servidor se identifica a sí mismo como "FileZilla Server 0.9.53 beta" al iniciar sesión, por lo que quizás esta sea una forma patentada de FileZilla de hacer las cosas, y hay algo extraño que debo hacer para convencer a Java de que use la misma sesión TLS.El cliente Apache Commons Net no sigue el estándar FTPS, y solo permite algunos subconjuntos que no permiten asegurar las conexiones de datos. Esto parecería extraño, ya que parece ser la forma estándar de conectarse a FTPS desde Java.Me falta algo por completo y diagnostico mal esto.

Agradecería cualquier dirección que pueda proporcionar sobre cómo conectarse a este tipo de servidor FTPS. Gracias.

Respuestas a la pregunta(3)

Su respuesta a la pregunta