When using Java Apache FTPClient for FTP TLS, getting "remote host closed connection during handshake"

I ran the Java (1.8) program for Windows 10 64x for FTP TLS (org.apache.commons.net.ftp):

FTPSClient ftpClient = new FTPSClient(); System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); // LISTENER ftpClient.addProtocolCommandListener( new PrintCommandListener(new PrintWriter(System.out), true)); ftpClient.connect(server); ftpClient.login(user, pass); // Enter local passive mode ftpClient.enterLocalPassiveMode(); // useEpsvWithIPv4 ftpClient.setUseEPSVwithIPv4(true); // Set protection buffer size ftpClient.execPBSZ(0); // Set data channel protection to private ftpClient.execPROT("P"); System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); ftpClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); System.out.println("Remote system is " + ftpClient.getEnabledCipherSuites()); System.out.println("SSL: " + ftpClient.getEnableSessionCreation()); // PROTOCOLOS String[] Protocols = ftpClient.getEnabledProtocols(); System.out.println("Protocols " + Protocols); // AUTH boolean Auth = ftpClient.getNeedClientAuth(); System.out.println("Auth: " + Auth); ftpClient.getWantClientAuth(); ftpClient.getTrustManager(); ftpClient.feat(); // APPROACH #1: using retrieveFile(String, OutputStream) String remoteFile1 = "/readme.txt"; File downloadFile1 = new File("C:\\readme.txt"); OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1)); ftpClient.retrieveFile(remoteFile1, outputStream1); outputStream1.close(); 

For the first FTP server (Microsoft FTP Service) it works just fine! debugging:

 run: 220 Microsoft FTP Service AUTH TLS 234 AUTH command ok. Expecting TLS Negotiation. USER ******* 331 Password required for demo. PASS ******* 230 User logged in. PBSZ 0 200 PBSZ command successful. PROT P 200 PROT command successful. TYPE I 200 Type set to I. SSL: true SYST 215 Windows_NT Remote system is Windows_NT Protocols [Ljava.lang.String;@3f2a3a5 Auth: false FEAT 211-Extended features supported: LANG EN* UTF8 AUTH TLS;TLS-C;SSL;TLS-P; PBSZ PROT C;P; CCC HOST SIZE MDTM REST STREAM 211 END EPSV 229 Entering Extended Passive Mode (|||1025|) RETR /readme.txt 125 Data connection already open; Transfer starting. 226 Transfer complete. QUIT 221 Goodbye. BUILD SUCCESSFUL (total time: 7 seconds) 

For the second FTP server (FileZilla Server 0.9.59 beta) it goes wrong, debug:

 run: 220-FileZilla Server 0.9.59 beta 220-written by Tim Kosse (tim.kosse@filezilla-project.org) 220 Please visit https://filezilla-project.org/ AUTH TLS 234 Using authentication type TLS USER ******* 331 Password required for xxx PASS ******* 230 Logged on PBSZ 0 200 PBSZ=0 PROT P 200 Protection level set to P TYPE I 200 Type set to I SSL: true SYST 215 UNIX emulated by FileZilla Remote system is UNIX emulated by FileZilla Protocols [Ljava.lang.String;@246ae04d Auth: false FEAT 211-Features: MDTM REST STREAM SIZE MLST type*;size*;modify*; MLSD AUTH SSL AUTH TLS PROT PBSZ UTF8 CLNT MFMT EPSV EPRT 211 End EPSV 229 Entering Extended Passive Mode (|||14393|) RETR /readme.txt 150 Opening data channel for file download from server of "/readme.txt" Error: Remote host closed connection during handshake javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake QUIT at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002) 450 TLS session of data connection has not resumed or the session does not match the control connection at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397) at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:646) at org.apache.commons.net.ftp.FTPClient._retrieveFile(FTPClient.java:1899) at org.apache.commons.net.ftp.FTPClient.retrieveFile(FTPClient.java:1885) at ftps.App_FTP.main(App_FTP.java:96) Caused by: java.io.EOFException: SSL peer shut down incorrectly at sun.security.ssl.InputRecord.read(InputRecord.java:505) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983) ... 7 more BUILD SUCCESSFUL (total time: 5 seconds) 

Using the FileZilla client works fine (upload / download files), but using Java code I can’t do anything, just plug in and plug in. Any suggestion? or any other automated FTP TLS solution?

My ftp object

+3
java ssl apache ftp apache-commons-net
source share
2 answers

I solved this problem using the Cyberduck library. https://github.com/iterate-ch/cyberduck
firstly, why does this Handshake problem arise because some advanced FTP servers allow only one session for connecting and transmitting data.

1) Control session β†’ to connect
2) Data session β†’ data storage / loading / etc

So how to solve it.

Step 1 -:

First you need to check cyberduck relay from GitHub. from here -: https://github.com/iterate-ch/cyberduck

Step 2 -: You will see FTP and the main module in ftp repository mode and the main modules

Step 3 -: Convert this module to maven and create a jar for the same.

Step 4 -: Add this jar to the project, but this jar also requires other dependencies, so add them accordingly to the project build path.

Step 5 -: Code snippet.

 public class TestFTPS { public static void main(String[] args) throws SocketException, IOException { TrustManager[] trustManagers = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { // TODO Auto-generated method stub return null; } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub } } }; SSLContext sslContext = null; try { sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustManagers, new SecureRandom()); } catch (Exception e) { e.printStackTrace(); } SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); Protocol protocol = new FTPTLSProtocol(); FTPClient client = new FTPClient(protocol, sslSocketFactory, sslContext); client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); client.connect(ftphostname, port); client.execAUTH("TLS"); //SSL System.out.println(client.getReplyCode()); if (client.login(username, password)) { client.execPBSZ(0); client.execPROT("P"); String date = "Testing Data Send to provide FTP location"; client.setFileType(FTP.BINARY_FILE_TYPE); client.enterLocalPassiveMode(); InputStream is = new ByteArrayInputStream(date.getBytes()); client.storeFile("test.txt", is); System.out.print(client.getReplyCode()); } } } 

Step 6 -:. After running this code, your file will be successfully transferred to the ftp location.

Note -: add the required jar to your project

Hope this helps you.

+3
source share

The important information is not the exception message itself, but this message is in the log:

450 TLS sessions not resumed or session does not match management connection

Some FTP servers require reusing a TLS session to connect to data.

This is not yet supported by the Apache Commons Net library, but it is not difficult to implement.

How to do this is shown in my answer to:
How to connect to a FTPS server with data connection using the same TLS session?

+2
source share

All Articles