It seems that FtpWebRequest on Linux does not reuse ssl sessions for FTPS passive data connections and for this reason does not work with the currently recommended ftp server setups.
Expected
An ftp client must reuse the same ssl session that he used for the control connection for the data connection too. That's the current default configuration for most ftps servers.
Problem
On Linux FtpWebClient creates a new ssl session for the data connection and the connection fails.
Test code
```c#
[Fact]
public async Task We_should_be_able_to_list_files_with_ftpwebrequest()
{
ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
// Get the object used to communicate with the server.
var request = (FtpWebRequest)WebRequest.Create("ftp://localhost/");
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.EnableSsl = true;
request.UsePassive = true;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("test", "test");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
var text = reader.ReadToEnd();
Console.WriteLine($"Directory List Complete, status {response.StatusDescription}");
reader.Close();
response.Close();
Assert.NotEmpty(text);
}
Result:
[xUnit.net 00:00:03.4876467] FileTransfer.Tests.FileZillaTests.We_should_be_able_to_list_files_with_ftpwebrequest [FAIL]
Fehler FileTransfer.Tests.FileZillaTests.We_should_be_able_to_list_files_with_ftpwebrequest
Fehlermeldung:
System.Net.WebException : The remote server returned an error: 150 Opening data channel for directory listing of "/"
.
---- System.IO.IOException : Authentication failed because the remote party has closed the transport stream.
Stapelverfolgung:
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.CommandStream.InvokeRequestCallback(Object obj)
at System.Net.CommandStream.Abort(Exception e)
at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
at System.Net.FtpWebRequest.GetResponse()
at FileTransfer.Tests.FileZillaTests.We_should_be_able_to_list_files_with_ftpwebrequest() in /mnt/c/workspace/lib-cs-filetransfer/FileTransfer.Tests/FileZillaTests.cs:line 45
--- End of stack trace from previous location where exception was thrown ---
----- Inner Stack Trace -----
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
at System.Net.TlsStream.AuthenticateAsClient()
at System.Net.FtpControlStream.QueueOrCreateFtpDataStream(Stream& stream)
at System.Net.FtpControlStream.PipelineCallback(PipelineEntry entry, ResponseDescription response, Boolean timeout, Stream& stream)
at System.Net.CommandStream.PostReadCommandProcessing(Stream& stream)
at System.Net.CommandStream.PostSendCommandProcessing(Stream& stream)
at System.Net.CommandStream.ContinueCommandPipeline()
at System.Net.FtpWebRequest.TimedSubmitRequestHelper(Boolean isAsync)
at System.Net.FtpWebRequest.SubmitRequest(Boolean isAsync)
FileZilla FTP server logs:
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> Connected on port 21, sending welcome message...
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> 220-FileZilla Server 0.9.60 beta
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> 220-written by Tim Kosse ([email protected])
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> 220 Please visit https://filezilla-project.org/
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> AUTH TLS
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> 234 Using authentication type TLS
(000015)14.11.2018 23:26:12 - (not logged in) (127.0.0.1)> TLS connection established
(000015)14.11.2018 23:26:13 - (not logged in) (127.0.0.1)> USER test
(000015)14.11.2018 23:26:13 - (not logged in) (127.0.0.1)> 331 Password required for test
(000015)14.11.2018 23:26:13 - (not logged in) (127.0.0.1)> PASS **
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 230 Logged on
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> PBSZ 0
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 200 PBSZ=0
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> PROT P
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 200 Protection level set to P
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> OPTS utf8 on
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 202 UTF8 mode is always enabled. No need to send this command.
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> PWD
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 257 "/" is current directory.
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> TYPE I
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 200 Type set to I
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> PASV
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 227 Entering Passive Mode (127,0,0,1,212,245)
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> LIST
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 150 Opening data channel for directory listing of "/"
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> 450 TLS session of data connection has not resumed or the session does not match the control connection
(000015)14.11.2018 23:26:13 - test (127.0.0.1)> disconnected.
```
Steps to reproduce
Note that we consider FtpWebRequest legacy API. Here's recommended list of replacements: https://github.com/dotnet/platform-compat/blob/master/docs/DE0003.md
That said, if it makes the class entirely unusable, we would be open to taking a contribution. Or if it impacts lots of users, we could eventually investigate too.
Have to say, that I'm not a network specialist, but after reading and testing a day, it seems that the real problem is the SslStream class that seems to be used by most clients. There seems to be no way to control this reuse behavior but it's using it's own cache that will reuse sessions with some magic. For me, it feels like this is the real problem with the result, that most clients do not work on Linux.
FluentFtp
That's what we normally use but it has the same Problem. I reported it as a bug:
CoreFTP
Tested, same problem.
Is it a real Problem?
Most servers have this feature enabled as recommended default:
ProFTPD
As of ProFTPD 1.3.3rc1, mod_tls only accepts SSL/TLS data connections that reuse the SSL session of the control connection, as a security measure.
Can be disabled in config but not recommended: http://www.proftpd.org/docs/contrib/mod_tls.html#TLSOptions
FileZilla Server
Another option you should enable is "Require TLS session resumption on data connection when using PROTP P" as it protects against data connection theft.
https://wiki.filezilla-project.org/FTPS_using_Explicit_TLS_howto_(Server)
vsftpd
require_ssl_reuse (Default: YES)
If set to yes, all SSL data connections are required to exhibit SSL session reuse (which proves that they know the same master secret as the control channel). Although this is a secure default, it may break many FTP clients, so you may want to disable it. For a discussion of the consequences, see http://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html (Added in v2.1.0).
http://vsftpd.beasts.org/vsftpd_conf.html
Notes
Do you know if it is Linux specific, or are there similar problems on Windows?
IMO the primary goal should be to fix better FTP stacks (like the ones you tried and failed too). If there is something we can/should do on our layers (below FTP), we'd love to know.
If it is so impactful, I wonder why we didn't hear about it for last 3 years. Maybe most people don't use FTP protocols anymore ...
Do you know if it is Linux specific, or are there similar problems on Windows?
Only Linux. (Windows tested, works perfectly)
If it is so impactful, I wonder why we didn't hear about it for last 3 years.
Same here, but it seems, that for some time it was simply normal, that most clients can't handle this feature. But today afaik most of them can (e.g. I think it was version 8 in Java world).
Maybe most people don't use FTP protocols anymore ...
Wish I could say the same. At least in the German ecommerce world people love CSV(!) and FTP - and I'm not talking about small companies...
@bartonjs - Is there some OpenSsl magic that would make this scenario work better?
As cluetjen said, the common factor here seems to be SSLStream. According to the SSLStream docs, TLS session resumption is done automatically be the framwork.
The special thing about FTPS is that for securing the entire interaction, it _requires_* resuming the control connection's TLS session for the data connection while keeping the control connection open. This is different from, say, HTTPS, where a failure to resue a TLS session for a parallel connection to the same server is just a performance hit.
*) Because there is no auth mechanism on FTP data connections, the only way to be sure that the client sending the data is the same client that requested a file upload in the first place is by reusing the same TLS session. Otherwise, the first one to connect to the data port can hijack it and, if it is a connection for a file upload, upload what file they want. FTP is a really weird protocol from today's perspective.
Is there some OpenSsl magic that would make this scenario work better?
If you mean some environment variables and the like, I don't think so. OpenSSL does support session resumption, but AFAIK SslStream never makes use of it. I don't have any particular insight as to how it works, or how much work it would take to do.
https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_session_cache_mode.html and https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_session.html make it seem like it's a bit non-trivial (I think currently every SslStream connection gets a distinct SSL_CTX; and I don't know how FTPS data connections are supposed to indicate that they're wanting to reuse from the session pool that the control connection was in).
Are there any plans to make this work? I understand that FtpWebRequest is deprecated, but as mentioned before this is also an issue for third party client libraries, unless they plan on implementing SSL themselves. I'm currently working on a project that has very high security requirements that we currently cannot meet due to this issue.
Are there any plans to make this work?
This is not planned for .NET 3.0. It is a difficult thing to implement completely since it relies on the behaviors of the OS TLS/SSL stack. It isn't something solvable at the .NET layer. It's possible to make it work perhaps just on Linux using the OpenSSL support that @bartonjs mentions. But then there is the question on how to enable/disable that behavior which might involve introducing new APIs.
But then there is the question on how to enable/disable that behavior which might involve introducing new APIs.
I don't quite follow that point. All we are asking for is that SSLStream on Linux be brought to feature parity with SSLStream on Windows, which automatically does session resumption. There is no way to disable that behavior on Windows, there would need to be no way to do so under Linux.
To clarify priority: This is not high on our priority list and will most certainly not happen in 3.0.
If anyone has idea how to fix it, we would welcome a contribution (I'd recommend to start with discussion how to fix it first).
Here are technical notes on feasibility from @bartonjs about SSL session resuing:
Windows seemingly maintains the sessions per-process. OpenSSL has support for it on SSL_CTX, but we make a new one of those for each connection. So we’d need to move to something like a static singleton SSL_CTX and then everywhere we touch it would need to get reassessed.
A quick glance at how we interop with SSL_CTX says that we’d need to look them up by the tuple (SslProtocols, EncryptionPolicy, what cert-and-private-key are being used, ALPN protocols) -- all of the things that get set on an SSL_CTX. All of the ones that are cert-less could probably live forever; the cert-related ones probably need to track when they’ve run out of SSL instances that use the SSL_CTX* and evict it from the cache and clean it up.
If some of the things are also settable on SSL* then moving them to per-connection would reduce the number and complexity of cached SSL_CTX* values. And, of course, then someone would have to actually figure out how to use the SSL resumption features… and then they’d have to figure out how to test it.
Complexity:
My expectation is “major restructuring of the Linux SslStream PAL”. I’d guess somewhere in the 3 to 6 week range for either doing it or determining it can’t be done.
It may turn out to be nearly “impossible” to implement on Linux though.
We should NOT write session ressumption on top of OpenSSL ourselves, nor write our own TLS in managed code -- such approaches are not acceptable and not conformant to our security guidelines.
cc @tmds @Drawaes if they are interested ...
Triage: We don't believe it is feasible to make it happen in .NET Core.
Given that it is "just" about performance on Linux of legacy protocol (FTP), we do not think it is that painful to not have it.
Given that it is "just" about performance on Linux
It's absolutely NOT about performance. It's about the fact, that you cannot establish data connections to any FTP server using any .net core library if the FTP server is configured to require session reuse for security reasons. This is the recommended setting for most FTP servers.
I agree that without fixing this it is not possible to even establish ftps connection
Good point, we missed it in triage. Thanks for clarifying.
Either way, given that it is extremely difficult on Linux and nobody expressed interest to implement it in quite some time, I think it is ok to keep it closed.
If we see even higher business need (customer upvotes are currently at 4), we may reconsider in future.
While it makes me a bit sad, I think it is the right call given other areas which need investment in Networking space.
I wonder if there are nuget packages providing FTPS support for Linux on top of .NET Core. That may be a decent workaround for scenarios which need the support.
@karelz problem is that all ftps nuget packages also suffer from this problem as it quite low level
I assume they all build on top of our FtpWebRequest
- in which case I guess there is room for a new one to be created/founded with proper low-level implementation.
If there is decent non-scary solution, maybe we could adopt it into .NET Core one day. Starting outside sounds like the best next step though.
@karelz problem is not directly in FtpWebRequest
, at least FluentFTP is not using it but in SslStream
netcore Linux implementation, so there is not much can be done externally. If only you did not meant to rewrite SSL/TLS in pure C#
@lafriks we currently rely on the SSL library to "do the right thing" here -- if OpenSSL has a feature you know if we can enable, that'd be great.
@lafriks If only you did not meant to rewrite SSL/TLS in pure C#
We don't have C# implementation - as Cory says above, we rely on OpenSSL.
OpenSsl already provides a Ctx session resumption cache that can be configured on and off, however as Jeremy already stated with the way that things are handled in the OpenSsl PAL it would need significant refactoring.
You would still need a c# side tuple cache to match the session you want to reuse (the only difference to his solution I see is the value in the cache would be a session id rather than the actual Ctx) either that or you would need some sort of "SslStream factory" like was implemented with HttpClient where all Sslstreams from a factory instance could reuse the same Session Ctx for a scenario such as this.
I wonder if there are nuget packages providing FTPS support
As already mentioned, they normally rely on SslStream and so they all have the same problem. I already reported it for FluentFTP, it's a pinned issue there: https://github.com/robinrodricks/FluentFTP/issues/347
Anyway it would be nice if this ticket would be reopened as there is nothing much that can be done outside dotnet core to fix this
We believe that this is as much actionable in CoreFX as outside -- i.e. it needs large amount of work, figuring out how it could work with bleak outlook.
Given that we don't think it is feasible to do it in CoreFX, the best avenue to prove us wrong is to create external nuget package (or fork of CoreFX) demonstrating it is possible, then we can start discussion of flowing it back into CoreFX.
imho it is not ok to close issue for bug only just because it's hard to fix.
Not that I would care for it so much anymore as I have rewritten that microservice to golang as it does not have such problems :)
If you look across our repo, you will notice that we rarely close issue because they are extremely hard to fix. This is one of them (probably the only one I am aware of as of now).
There is no value in keeping the issue opened ... it just creates clutter in repo. That's what we are optimizing for - especially with the plan to merge repos. Our goal is to close issues which neither community nor us plan to work on in foreseeable future (i.e. ever). This one is in that bucket sadly.
We are experiencing this issue too.
After researching this for 2 weeks I came across this issue here which won't be fixed.
I'd like to clarify something...
This thread seems to state that this is Linux related only.
_Yet I'm having the same issues between 2 Windows servers_.
I have a service running on a windows server that can't connect properly to a Filezila server installed on Windows. Same thing with ProFTPD.
Deactivating the following option on the Filezilla server is the only working solution:
Require TLS session resumption on data connection when using PROTP P
If someone could confirm that this also affects Windows I'll start looking for a commercial library since deactivating recommended security settings is not a viable solution.
@mthgr I can confirm that it is indeed also a Windows (Server) issue since a few weeks. More specific since the release of this update:
If the machine running your code has installed this update the problem presents itself. I haven't found a solution so far. If someone did, that would be great, pls share.
Comments above say that Windows is working fine - https://github.com/dotnet/corefx/issues/33506#issuecomment-438878667
If you see Windows issue, please file a new bug as it is likely some unrelated regression or something. Please specify exact .NET Core version. Ideally try latest released (3.0.x currently) as well. Also, it would help to clarify if it is OS regression (fails/passes just based on OS patch being installed)
I will hide the last 2 Windows comments above as they are unrelated to the main issue here -- to avoid confusion.
I think the comment above is wrong (33506). I've been working on this project for a few months now (pre-dating the updates mentioned above) and I've had this issue since day 1 and had to deactivate the mentioned settings on FileZilla to make it work.
For your internal reference, I've been in contact with IPworks to use their commercial library for FTP since we can't make use of any open source project depending on .Net Core at the moment. They told me that they are aware of the issue under windows and they use their own SSL library to circumvent it.
I've upgraded my project to use the latest netcore version 3.0 (still no luck). Also, the patches mentioned in the previous comment are not installed on my customer server yet I get the same error.
Just trying to be helpful here...
I think the confusion comes from the issue people are referring to linked to the FluentFTP project regarding the Linux server issue.
They also have another issue regarding windows server:
https://github.com/robinrodricks/FluentFTP/issues/311
As you can see by the dates it's been there for a while. I guess most people just disable the settings and move on. Unfortunately, this is not an option in our case.
I hope this helps.
Linking https://github.com/dotnet/runtime/issues/22977 for reference.
This may be done primarily for HTTPS perf improvement.
Feasibility on OSX is still not clear.
We are experiencing this issue too.
After researching this for 2 weeks I came across this issue here which won't be fixed.
I'd like to clarify something...
This thread seems to state that this is Linux related only.
_Yet I'm having the same issues between 2 Windows servers_.
I have a service running on a windows server that can't connect properly to a Filezila server installed on Windows. Same thing with ProFTPD.
Deactivating the following option on the Filezilla server is the only working solution:
Require TLS session resumption on data connection when using PROTP PIf someone could confirm that this also affects Windows I'll start looking for a commercial library since deactivating recommended security settings is not a viable solution.
Can confirm that I am experiencing this issue from windows ftp client (mvc under iis) to a FileZilla server on both linux and windows. I've set up a test filezilla server on a windows box and our client can connect and can make the connection repeatedly fail or succeed by toggling the Require TLS session resumption checkbox on FileZilla server.
@wfurt would it make the request feasible on Linux? Maybe we should reopen then ...
possibly. I linked it so it is my radar. As I mentioned, currently there is no API to force session reuse it and that may or may not be issue.
I can also confirm that I am experiencing this issue on both LINUX and Windows platforms. The problem was originally discovered when our application using FluentFTP attempted to connect via FTPS to data monitoring devices using Linux. After setting up a FileZilla Server on a machine running Windows 10 we discovered the same problem. As mentioned previously the test with the FileZilla Server will repeatably fail or succeed by toggling the TLS session resumption checkbox. Also as mentioned previously other open source FTP components built off .NET core that I have tested with (CoreFTP) have the same problem.
Is there any timeline on when this issue may be resolved? If not does anyone who has experienced this issue found a work around?
I think we may be able to investigate past 5.0 - there is not enough time now because of more urgent issues.
I think there are (at least) two separate issues. On Linux, there is currently no resume and #22977 tracks that.
I had prototype but I may not be able to finish that in 5 for the same reason as above.
There are mixed signals about Windows. On Windows, TLS resume is possible but there is no .NET API to force.
If anybody from the community wants to help, it would be great to to create repo with with perhaps multiple clients and set up publicly reachable server for testing. Then run the test on different platforms with different client variations and collect data. Ideally, anybody else would be able to easily reproduce.
Thank you for the response, I'd be willing to help if possible, solving this issue is important to our development team, but can you give me more details on what you mean by multiple clients?
This issue originally complains about FtpWebRequest. Others talked about FluentFTP. Perhaps there is some other client working. I can certainly look at ours but it would be nice to have more variations for comparisons.
I primarily work on SSL now and if for example this does not work on Windows as it used to, I can ask OS team without spending too much time on it. I hope this makes more sense @zachmakki15
Thank you for the clarification, I can assist with that. When we attempted to add an FTP component to our software we tested a couple different .NET FTP components before settling on FluentFTP. The client demos I can create include FluentFTP, CoreFTP, FtpWebRequest, and WinSCP. This may take a couple weeks as I will have to do it in my spare time, I will post an update here when I have made some progress. If anyone else would like to contribute please let me know.
One of our clients switched their ProFTPD to FTPS and now we are unable to get listings from it. We are using FluentFTP and they have require session reuse on.
It surprised us that basically any .NET client on Linux (any decent Docker) is now unable to connect to them.
I have the same problem now on windows too!
As it seems with a windows update this problem propagates to windows hosting on Azure WebSites.
Most helpful comment
It's absolutely NOT about performance. It's about the fact, that you cannot establish data connections to any FTP server using any .net core library if the FTP server is configured to require session reuse for security reasons. This is the recommended setting for most FTP servers.