I try connect to a FTPS server and got this error. My server only open port 21. I try connect with FileZilla with same config and OK but not in java code. Here my code
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;
import java.io.ByteArrayInputStream;
public class FTPsX {
private static final String ftpUrl = "192.168.0.100";
private static final int ftpPort = 21;
private static final String ftpUserName = "root";
private static final String ftpUserPassword = "admin123";
public static void main(String[] args) {
try {
System.setProperty("https.protocols", "TLSv1.2");
FTPSClient ftpsClient = new FTPSClient("TLSv1.2", false);
ftpsClient.addProtocolCommandListener(
new PrintCommandListener(
new PrintWriter(new OutputStreamWriter(System.out, "UTF-8")), true));
ftpsClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
ftpsClient.setUseClientMode(true);
ftpsClient.connect(ftpUrl, ftpPort);
int reply = ftpsClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpsClient.disconnect();
throw new Exception("Failed to connect properly to FTP");
}
ftpsClient.login(ftpUserName, ftpUserPassword);
ftpsClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpsClient.execPBSZ(0);
ftpsClient.execPROT("P");
ftpsClient.enterLocalPassiveMode();
ftpsClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
ftpsClient.storeFile("error_here", new ByteArrayInputStream("test".getBytes()));
ftpsClient.logout();
ftpsClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And this is the error
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1009)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:646)
at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:653)
at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
at FTPsX.main(FTPsX.java:35)
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:990)
... 8 more
I tried set some but not work. The command storeFile can create file with 0 byte and error come.
I already try add -Djdk.tls.useExtendedMasterSecret=false but no luck.
This is the log in FileZilla
09:58:12 Command: AUTH TLS
09:58:12 Response: 234 Security mechanism set to TLS
09:58:12 Status: Initializing TLS...
09:58:12 Trace: TLS Handshake successful
09:58:12 Trace: Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
09:58:12 Status: Verifying certificate...
09:58:12 Status: TLS connection established.
09:58:12 Command: USER root
09:58:12 Response: 331 Need password
09:58:12 Command: PASS ***********
09:58:12 Response: 230 User logged in
09:58:12 Command: OPTS UTF8 ON
09:58:12 Response: 202 The UTF8 option is already enabled
09:58:12 Command: PBSZ 0
09:58:12 Response: 200 PBSZ=0
09:58:12 Command: PROT P
09:58:12 Response: 200 Data protection level set to Private
09:58:12 Status: Logged in
09:58:12 Trace: Measured latency of 141 ms
09:58:12 Status: Retrieving directory listing...
09:58:12 Command: PWD
09:58:12 Response: 257 "/" is current directory
09:58:13 Status: Directory listing of "/" successful
------ File upload -------------
14:03:25 Command: TYPE I
14:03:25 Response: 200 Representation type set to Image
14:03:25 Command: PASV
14:03:25 Response: 227 Entering Passive Mode (192,168,0,100,31,153)
14:03:25 Trace: Binding data connection source IP to control connection source IP 192.168.0.100
14:03:25 Command: STOR test-270.log
14:03:25 Trace: Trying to resume existing TLS session.
14:03:25 Response: 150 Opening data connection
14:03:25 Trace: TLS Handshake successful
14:03:25 Trace: TLS Session resumed
14:03:25 Trace: Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
14:03:25 Response: 226 Data connection completed successfully
14:03:25 Status: File transfer successful, transferred 613,612 bytes in 1 second
I tried add custom FTPSClient as Martin Prikryl suggest:
import org.apache.commons.net.ftp.FTPSClient;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Locale;
public class SSLSessionReuseFTPSClient extends FTPSClient {
public SSLSessionReuseFTPSClient(boolean isImplict) {
super(isImplict);
}
@Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
System.out.println("_prepareDataSocket_");
if (socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket) _socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
method.setAccessible(true);
String hostNameAddr = String
.format("%s:%s", socket.getInetAddress().getHostName(), socket.getPort())
.toLowerCase(Locale.ROOT);
System.out.println("hostNameAddr: " + hostNameAddr);
method.invoke(cache, hostNameAddr, session);
String hostAddressAddr = String
.format("%s:%s", socket.getInetAddress().getHostAddress(), socket.getPort())
.toLowerCase(Locale.ROOT);
System.out.println("hostAddressAddr: " + hostAddressAddr);
method.invoke(cache, hostAddressAddr, session);
} catch (Exception e) {
throw new IOException(e);
}
} else {
throw new IOException("Invalid SSL Session");
}
}
}
}
but still get error
220 Bitvise SSH Server 8.44: free only for personal non-commercial use
FEAT
211-Features:
LANG EN*
UTF8
MDTM
SIZE
REST STREAM
TVFS
AUTH TLS
AUTH SSL
PROT
PBSZ
EPSV
HASH SHA-512;SHA-256;SHA-1*;MD5;CRC32
XCRC "filename" SP EP
XMD5 "filename" SP EP
XSHA "filename" SP EP
XSHA1 "filename" SP EP
XSHA256 "filename" SP EP
XSHA512 "filename" SP EP
211 End
AUTH TLS
234 Security mechanism set to TLS
USER *******
331 Need password
PASS *******
230 User logged in
TYPE I
200 Representation type set to Image
PBSZ 0
200 PBSZ=0
PROT P
200 Data protection level set to Private
TYPE A
200 Representation type set to ASCII Non-print
PASV
227 Entering Passive Mode (192,168,0,100,31,153)
STOR n8yd
150 Opening data connection
_prepareDataSocket_
hostNameAddr: 192.168.0.100:8089
hostAddressAddr: 192.168.0.100:8089
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1009)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:646)
at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:653)
at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
at FTPs.main(FTPs.java:118)
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:990)
... 8 more
Anyone have any suggestion about this ?
Or any workaroud for this like sendCommand("stor","filename","text_file_content") ?
or some how i can send command at low level the same as the FileZilla did ?