可以使用 FileZilla 或 WinSCP 连接到 FTP,但不能使用 FtpWebRequest 或 FluentFTP 连接到 FTP

Ben*_*bin 6 c# ftp ssl ftpwebrequest fluentftp

我正在尝试在代码中通过 SSL 打开 FTP 连接。我可以使用 WinSCP 的 FileZilla 连接并列出目录。但是当使用 .NET 代码列出目录时FtpWebClient,我收到错误

(425) 无法打开数据连接

由于我能够从同一台计算机使用 FileZilla 进行连接,因此我不确定如何解决此问题。

这是我的代码

public void FtpStuff()
{
   string url = "ftp://my.server.com";

   FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
   request.Credentials = new NetworkCredential("myname", "password");
   request.EnableSsl = true;
   request.Method = WebRequestMethods.Ftp.ListDirectory;
   FtpWebResponse response = (FtpWebResponse)request.GetResponse();
   StreamReader streamReader = new StreamReader(response.GetResponseStream());

   // This is the line that throws the exception
   string line = streamReader.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过FluentFTP。这是我的代码。我得到了例外

无法建立数据连接:不允许操作。

public void FtpStuff()
{
   FtpClient client = new FtpClient();
   client.Host = "my.server.com";
   client.Credentials = new NetworkCredential("myname", "password");
   client.EncryptionMode = FtpEncryptionMode.Explicit;
   client.Connect();

   // This line gives me an exception.
   var files = client.GetListing();
}
Run Code Online (Sandbox Code Playgroud)

这是 FluentFTP 的日志信息。我更改了真实的用户名和IP,但其余数据(包括端口)是真实数据。我的 FTP 服务提供商指定我必须在端口 21 上进行连接。问题似乎是在EPSV发出命令并在新端口上建立连接后发生的。

public void FtpStuff()
{
   string url = "ftp://my.server.com";

   FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
   request.Credentials = new NetworkCredential("myname", "password");
   request.EnableSsl = true;
   request.Method = WebRequestMethods.Ftp.ListDirectory;
   FtpWebResponse response = (FtpWebResponse)request.GetResponse();
   StreamReader streamReader = new StreamReader(response.GetResponseStream());

   // This is the line that throws the exception
   string line = streamReader.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

这是我的 FileZilla 日志。

public void FtpStuff()
{
   FtpClient client = new FtpClient();
   client.Host = "my.server.com";
   client.Credentials = new NetworkCredential("myname", "password");
   client.EncryptionMode = FtpEncryptionMode.Explicit;
   client.Connect();

   // This line gives me an exception.
   var files = client.GetListing();
}
Run Code Online (Sandbox Code Playgroud)

我还可以使用 WinSCP 进行连接。正如评论中所建议的,我确实检查了打开数据连接时是否重用了 TLS/SSL 会话 ID。看来确实如此。

# Connect()
The thread 0x5514 has exited with code 0 (0x0).
The thread 0xc80 has exited with code 0 (0x0).
The thread 0x89d4 has exited with code 0 (0x0).
Status:   Connecting to 123.123.123.123:21
Response: 220 FTP Server Ready
Command:  AUTH TLS
Response: 234 AUTH TLS successful
Status:   FTPS Authentication Successful
Status:   Time to activate encryption: 0h 0m 0s.  Total Seconds: 0.1339995.
Command:  USER me@mysite.com
The thread 0x6ddc has exited with code 0 (0x0).
Response: 331 Password required for me@mysite.com
Status:   Testing connectivity using Socket.Poll()...
Command:  PASS ***
Response: 230-***************************************************************************
Response: NOTICE TO USERS
Response: This computer system is private property. It is for authorized use only.
Response: Users (authorized or unauthorized) have no explicit or implicit
Response: expectation of privacy.
Response: 
Response: Any or all uses of this system and all files on this system may be
Response: intercepted, monitored, recorded, copied, audited and inspected by
Response: using this system, the user consents to such interception, monitoring,
Response: recording, copying, auditing, inspection, and disclosure at the
Response: discretion of such personnel or officials.  Unauthorized or improper use
Response: of this system may result in civil and criminal penalties and
Response: administrative or disciplinary action, as appropriate. By continuing to
Response: use this system you indicate your awareness of and consent to these terms
Response: and conditions of use. LOG OFF IMMEDIATELY if you do not agree to the
Response: conditions stated in this warning.
Response: ****************************************************************************
Response: 230 User me@mysite.com logged in
Command:  PBSZ 0
Response: 200 PBSZ 0 successful
Command:  PROT P
Response: 200 Protection set to Private
Command:  FEAT
Response: 211-Features:
Response: AUTH TLS
Response: CCC
Response: CLNT
Response: EPRT
Response: EPSV
Response: HOST
Response: MDTM
Response: MFF modify;UNIX.group;UNIX.mode;
Response: MFMT
Response: MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;
Response: PBSZ
Response: PROT
Response: REST STREAM
Response: SIZE
Response: SSCN
Response: TVFS
Response: 211 End
Status:   Text encoding: System.Text.ASCIIEncoding
Command:  SYST
Response: 215 UNIX Type: L8

# GetListing(null, Auto)

# GetWorkingDirectory()
Command:  PWD
Response: 257 "/" is the current directory
Command:  TYPE I
Response: 200 Type set to I

# OpenPassiveDataStream(AutoPassive, "MLSD /", 0)
Command:  EPSV
Response: 229 Entering Extended Passive Mode (|||50304|)
Status:   Connecting to 123.123.123.123:50304
Command:  MLSD /
Response: 150 Opening BINARY mode data connection for MLSD
Status:   FTPS Authentication Successful
Status:   Time to activate encryption: 0h 0m 0s.  Total Seconds: 0.1210002.
+---------------------------------------+
-----------------------------------------
Status:   Disposing FtpSocketStream...

# CloseDataStream()
Response: 425 Unable to build data connection: Operation not permitted
Status:   Disposing FtpSocketStream...
Exception thrown: 'FluentFTP.FtpCommandException' in FluentFTP.dll
Run Code Online (Sandbox Code Playgroud)

Mar*_*ryl 11

.NET框架不支持TLS/SSL会话重用。如果您的服务器需要它(它看起来是什么、现在很常见以及对安全性有什么好处),则您不能使用FtpWebRequestFluentFTP。两者都使用 TLS/SSL 的 .NET 实现。

\n

您必须使用使用自己的 TLS/SSL 实现的 FTP 库。

\n

您可以使用我的 WinSCP .NET 程序集尽管与 FluentFTP 相反,它不是本机 .NET 库,但它依赖于外部二进制文件。但这就是让它发挥作用的原因。

\n

一些参考:

\n\n