Ambiente: sto utilizzando Sun Java JDK 1.8.0_60 su Windows 7 a 64 bit, utilizzando Spring Integration 4.1.6 (che internamente sembra utilizzare Apache Commons Net 3.3 per l'accesso FTPS).Come connettersi al server FTPS con connessione dati utilizzando la stessa sessione TLS?
Sto tentando di integrare con la nostra applicazione un download automatico dal server FTPS del nostro cliente. Ho eseguito così con successo con i server SFTP usando Spring Integration senza problemi per gli altri client senza problemi, ma questa è la prima volta che un client ci richiede di usare FTPS, e collegarlo è stato molto sconcertante. Mentre nella mia reale applicazione sto configurando Spring Integration usando i bean XML, per cercare di capire cosa non funziona sto usando il seguente codice di test (anche se sto anonimizzando l'host/username/password qui):
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();
Sto eseguendo questo codice con -Djavax.net.debug=all
per stampare tutte le informazioni di debug di TLS.
La connessione "di controllo" principale al server FTPS funziona correttamente, ma quando tenta di aprire la connessione dati per l'elenco (o qualsiasi altra connessione dati che ho provato), ottengo un javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
, causato da java.io.EOFException: SSL peer shut down incorrectly
. Se io rimuovere il commento le deglutizione-eccezioni cattura blocco attorno al comando session.list
, allora posso vedere (anche se l'output javax.net.debug) che il server ha inviato il seguente messaggio dopo aver respinto la connessione dati 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..
Quello che sembra stia accadendo (e questa è la mia prima volta che mi occupo di FTPS, anche se ho già avuto a che fare con FTP semplice) è che il modo in cui il server garantisce l'autenticazione e la crittografia sia sul controllo che sulle connessioni dati è che dopo un "normale" Connessione TLS per stabilire la connessione di controllo e l'autenticazione avviene lì, ogni connessione dati richiede al client di connettersi con la stessa sessione TLS. Questo ha senso per me come dovrebbe essere il lavoro, ma l'implementazione FTPS di Net Commons Apache non sembra farlo. Sembra che stia tentando di stabilire una nuova sessione TLS e quindi il server sta respingendo il tentativo.
In base a this question about resuming SSL sessions in JSSE, sembra che Java assuma o richieda una sessione diversa per ciascuna combinazione host/post. La mia ipotesi è che, poiché la connessione dati FTPS è su una porta diversa dalla connessione di controllo, non sta trovando la sessione esistente e sta tentando di stabilirne una nuova, quindi la connessione fallisce.
vedo tre possibilità principali:
- Il server non è seguendo lo standard FTPS nel richiedere la stessa sessione TLS sulla porta dati sulla porta di controllo. Posso connettermi al server (usando lo stesso host/utente/password che sto cercando di usare nel mio codice) usando FileZilla 3.13.1. Il server si identifica come "FileZilla Server 0.9.53 beta" al momento dell'accesso, quindi forse questa è una sorta di metodo proprietario di FileZilla per fare le cose, e c'è qualcosa di strano che devo fare per convincere Java ad usare la stessa sessione TLS.
- Il client Net Commons Apache in realtà non segue lo standard FTPS e consente solo un sottoinsieme che non consente di proteggere le connessioni dati. Ciò sembrerebbe strano, in quanto sembra essere il modo standard per connettersi a FTPS da Java.
- Mi manca completamente qualcosa e una diagnosi errata.
Apprezzerei qualsiasi direzione che è possibile fornire su come connettersi a questo tipo di server FTPS. Grazie.
Fare riferimento a questo collegamento per i dettagli https://stackoverflow.com/questions/46631315/when-using-java-apache-ftpclient-for-ftp-tls-getting-remote-host-closed -connect/48616779 # 48616779 –