The remote server returned an error: (425) Can't open data connection when FTPS enabled

235 Views Asked by At

when I add enableSSL = true to support FTPS , I am getting error The remote server returned an error: (425) Can't open data connection on the line ftpStream.Close(); But without enableSSL = true it works fine.

 at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.FtpWebRequest.RequestCallback(Object obj)
   at System.Net.CommandStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
   at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.FtpWebRequest.RequestCallback(Object obj)
   at System.Net.CommandStream.Abort(Exception e)
   at System.Net.CommandStream.CheckContinuePipeline()
   at System.Net.FtpWebRequest.DataStreamClosed(CloseExState closeState)
   at System.Net.FtpDataStream.System.Net.ICloseEx.CloseEx(CloseExState closeState)
   at System.Net.FtpDataStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()

And this is the code for uploading to ftp server

public bool Upload(string remoteFile, string localFile)
        {
            bool res = false;
            FileStream localFileStream = null;
            try
            {
                /* Create an FTP Request */
                ftpRequest = (FtpWebRequest) WebRequest.Create(string.Format(@"ftp://{0}/{1}", host, remoteFile));
                /* Log in to the FTP Server with the User Name and Password Provided */
                ftpRequest.Credentials = new NetworkCredential(user, pass);
                /* When in doubt, use these options */
                ftpRequest.UseBinary = true;
                ftpRequest.UsePassive = true;
                ftpRequest.KeepAlive = true;
                /* Apply SSL/TLS encryption */
                ftpRequest.EnableSsl = enableSSL;

                /* Specify the Type of FTP Request */
                ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
                /* Establish Return Communication with the FTP Server */
                ftpStream = ftpRequest.GetRequestStream();
                /* Open a File Stream to Read the File for Upload */
                 localFileStream = new FileStream(localFile, FileMode.Open);
                /* Buffer for the Downloaded Data */
                byte[] byteBuffer = new byte[bufferSize];
                int bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
                /* Upload the File by Sending the Buffered Data Until the Transfer is Complete */
                try
                {
                    while (bytesSent != 0)
                    {
                        ftpStream.Write(byteBuffer, 0, bytesSent);
                        bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
                    }
                    res = true;
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                    res = false;
                }

                ftpRequest = null;
                res = true;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "", remoteFile,localFile);
                res = false;
            }
            finally
            {
                if(localFileStream != null)
                    localFileStream.Close();
                if(ftpStream != null)
                    ftpStream.Close();
            }
            return res;
        }

FTP logs with enabledSSL = true

System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [USER xxx]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [331 Please, specify the password.]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [PASS ********]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [230 Login successful.]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [PBSZ 0]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [200 PBSZ=0]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [PROT P]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [200 Protection level set to P]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [OPTS utf8 on]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [202 UTF8 mode is always enabled. No need to send this command]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [PWD]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [257 "/" is current directory.]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [TYPE I]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [200 Type set to I]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [PASV]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [227 Entering Passive Mode (xx,xxx,xxx,xxx,195,127)]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Sending command [STOR xxxx.txt]
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [150 Starting data transfer.]
System.Net Information: 0 : [16696] TlsStream#50631228::.ctor(host=xx.xxx.xxx.xxx, #certs=0, checkCertificateRevocationList=False, sslProtocols=None)
System.Net Information: 0 : [16696] SecureChannel#298900::.ctor(hostname=xx.xxx.xxx.xxx, #clientCertificates=0, encryptionPolicy=RequireEncryption)
System.Net Information: 0 : [16696] SecureChannel#298900 - Left with 0 client certificates to choose from.
System.Net Information: 0 : [16696] Using the cached credential handle.
System.Net Information: 0 : [16696] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = (null), targetName = xx.xxx.xxx.xxx, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [16696] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=559, returned code=ContinueNeeded).
System.Net Information: 0 : [16696] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 90cbfe8:90d48f8, targetName = xx.xxx.xxx.xxx, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [16696] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [16696] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 90cbfe8:90d48f8, targetName = xx.xxx.xxx.xxx, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [16696] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [16696] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 90cbfe8:90d48f8, targetName = xx.xxx.xxx.xxx, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [16696] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=51, returned code=OK).
System.Net Information: 0 : [16696] Remote certificate: [Version]
  V3

[Subject]
  CN=filezilla-server self signed certificate
  Simple Name: filezilla-server self signed certificate
  DNS Name: filezilla-server self signed certificate

[Issuer]
  CN=filezilla-server self signed certificate
  Simple Name: filezilla-server self signed certificate
  DNS Name: filezilla-server self signed certificate

[Serial Number]
  xxxx

[Not Before]
  7/23/2023 2:05:48 PM

[Not After]
  7/23/2024 2:10:48 PM

[Thumbprint]
  xxx

[Signature Algorithm]
  sha256ECDSA(1.2.840.10045.4.3.2)

[Public Key]
 

[Extensions]
* Key Usage(2.5.29.15):
  Digital Signature, Key Encipherment (a0)

* Basic Constraints(2.5.29....
System.Net Information: 0 : [16696] SecureChannel#298900 - Remote certificate has errors:
System.Net Information: 0 : [16696] SecureChannel#298900 -  Certificate name mismatch.
System.Net Information: 0 : [16696] SecureChannel#298900 -  A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

System.Net Information: 0 : [16696] SecureChannel#298900 - Remote certificate was verified as valid by the user.
System.Net Information: 0 : [16696] ProcessAuthentication(Protocol=Tls12, Cipher=Aes256 256 bit strength, Hash=Sha384 0 bit strength, Key Exchange=44550 255 bit strength).
System.Net Information: 0 : [16696] FtpControlStream#4997028 - Received response [425 Error while transfering data: ECONNABORTED - Connection aborted]
System.Net Information: 0 : [16696] FtpWebRequest#87667::(Releasing FTP connection#4997028.)
System.Net Information: 0 : [32808] ServicePoint#21194167 - Closed as idle.

FTP logs without enabledSSL = true

System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [USER xxxx]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [331 Please, specify the password.]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [PASS ********]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [230 Login successful.]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [OPTS utf8 on]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [202 UTF8 mode is always enabled. No need to send this command]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [PWD]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [257 "/" is current directory.]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [TYPE I]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [200 Type set to I]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [PASV]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [227 Entering Passive Mode (xx,xxx,xxx,xxx,195,123)]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Sending command [STOR xxxx.txt]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [150 Starting data transfer.]
System.Net Information: 0 : [16696] FtpControlStream#56506964 - Received response [226 Operation successful]
System.Net Information: 0 : [16696] FtpWebRequest#17037307::(Releasing FTP connection#56506964.)
System.Net Information: 0 : [16696] FtpWebRequest#17037307::GetResponse(Method=STOR.)

Also It works fine using FluentFTP

FtpClient client = new FtpClient(host, user, pass);
client.Config.EncryptionMode = FtpEncryptionMode.Explicit;
client.Config.ValidateAnyCertificate = true;
client.Connect();
client.UploadFile("a.txt", "a.txt");
client.Disconnect();

FileZilla logs

  Status:   Connecting to xx.xxx.xxx.xxx:21...
Status: Connection established, waiting for welcome message...
Response:   220-FileZilla Server 1.7.2
Response:   220 Please visit https://filezilla-project.org/
Command:    AUTH TLS
Response:   234 Using authentication type TLS.
Status: Initializing TLS...
Trace:  TLS Handshake successful
Trace:  Protocol: TLS1.3, Key exchange: ECDHE-SECP384R1-ECDSA-SECP256R1-SHA256, Cipher: AES-256-GCM, MAC: AEAD, ALPN: x-filezilla-ftp
Status: TLS connection established.
Command:    USER adlcombined
Response:   331 Please, specify the password.
Command:    PASS ***********
Response:   230 Login successful.
Status: Logged in
Trace:  Measured latency of 252 ms
Status: Starting upload of C:\kamil\kamil.txt
Command:    CWD /
Response:   250 CWD command successful
Command:    TYPE A
Response:   200 Type set to A
Command:    PASV
Response:   227 Entering Passive Mode (xx,xxx,xxx,xxx,195,106)
Trace:  Binding data connection source IP to control connection source IP fff.ff.ff.f
Trace:  Trying to resume existing TLS session.
Command:    STOR kamil.txt
Response:   150 About to start data transfer.
Trace:  TLS Handshake successful
Trace:  TLS Session resumed
Trace:  Protocol: TLS1.3, Key exchange: unknown, Cipher: AES-256-GCM, MAC: AEAD, ALPN: ftp-data
Response:   226 Operation successful
Status: File transfer successful, transferred 11 bytes in 1 second
Status: Retrieving directory listing of "/"...
Command:    TYPE I
Response:   200 Type set to I
Command:    PASV
Response:   227 Entering Passive Mode (xx,xxx,xxx,xxx,195,104)
Trace:  Binding data connection source IP to control connection source IP fff.ff.ff.f
Trace:  Trying to resume existing TLS session.
Command:    MLSD
Response:   150 About to start data transfer.
Trace:  TLS Handshake successful
Trace:  TLS Session resumed
Trace:  Protocol: TLS1.3, Key exchange: unknown, Cipher: AES-256-GCM, MAC: AEAD, ALPN: ftp-data
Response:   226 Operation successful
Status: Directory listing of "/" successful
2

There are 2 best solutions below

0
Kamil Ibadov On

It works using FluentFTP

FtpClient client = new FtpClient(host, user, pass);
client.Config.EncryptionMode = FtpEncryptionMode.Explicit;
client.Config.ValidateAnyCertificate = true;
client.Connect();
client.UploadFile("a.txt", "a.txt");
client.Disconnect();
1
Robin Lindner On

Using the WebClient for FTP is absolutely not recommended. It is de facto deprecated.

Microsoft also strongly advises against using the WebClient for new developments. See Microsoft Docs for System.Net.WebClient

Third-party libraries such as FluentFTP also have broader support for various handshake procedures and more granular settings, so I recommend using FluentFTP for your use case.