我正在设置一个 FTP 服务器( FileZilla
)netftp codeplex project
System.Net.FtpClient
并使用.SSL
TLS
X509Certificate2
- 我已经
FileZilla Server
从 sourceforge下载了。 - 我已经
System.Net.FtpClient v14.06.17
从 codeplex下载了。
我想我已经隔离了这个问题,但也许有人对根本原因有一些额外的想法。本文底部提供了一种解决方法。
client.GetListing()
调用时发生异常client.GetNameListing()
,但是,上传 ( OpenWrite
) 和下载 ( OpenRead
) 都可以正常工作。我已经测试了许多版本FileZilla
来隔离它开始破坏的版本。
- 0.9.42作品(2013-12-16)
- 0.9.43 坏 (2014-01-02)
- 0.9.46 坏 (2014-08-03)
- 0.9.50 坏 (2015-03-19) - 当前
发生的异常是:
- 外部消息:
A call to SSPI failed, see inner exception.
- 内心讯息:
The message received was unexpected or badly formatted
导致错误的 C# 代码示例:
FtpClient client = new FtpClient();
client.Credentials = new NetworkCredential("blah", "blah123");
client.Host = "127.0.0.1";
client.Port = 21;
client.DataConnectionEncryption = true;
client.EncryptionMode = FtpEncryptionMode.Explicit;
//client.ClientCertificates.Add(cert); // tried both with and without
client.ValidateCertificate += (cli, e) => { e.Accept = true; };
client.Connect();
var list = client.GetNameListing(); // exception on this line
在Codeplex 文档页面上,jptrosclair
写道:
您不使用 pem 证书,而是使用 p12。有关更多信息,请参阅此 Stack Overflow 线程。如果您收到 SPPI 异常以及有关意外或格式错误的消息的内部异常,则您可能使用了错误类型的证书。
链接是指asp.net
,不是FileZilla
。我的猜测是IIS
不支持PEM
并且很可能通过流发送一堆乱码。但是,如果您使用您的服务器支持的证书格式,那么应该没有问题。据我所知,FileZilla
仅支持PEM
格式(或CRT/CER
仍然是PEM
格式)。
此外,这并不能解释为什么OpenRead
会OpenWrite
成功,而是GetListing
会GetNameListing
失败。
无论如何,我仍然测试了多种不同的证书生成工具,包括FileZilla's
内置生成器C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\makecert.exe
、OpenSSL (windows)
. 问题仍然存在。
skovachev
这是来自https://netftp.codeplex.com/discussions/535815的类似讨论的链接。
他的解决方法是在获取列表之前克隆连接。
解决方法:
FileZilla
我已经使用上面列出的所有版本测试了以下内容。修复方法是System.Net.FtpClient
从类中下载源代码codeplex
并在FtpSocketStream.cs
类中编辑以下方法:
public void ActivateEncryption(string targethost, X509CertificateCollection clientCerts)
改变:
m_sslStream.AuthenticateAsClient(targethost, clientCerts, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);
至:
m_sslStream.AuthenticateAsClient(targethost, clientCerts, SslProtocols.Tls | SslProtocols.Ssl3, true);
(基本上只是删除Ssl2
标志)。
我的猜测是在连接到服务器时设置标志FileZilla v0.9.43
时发生了一些变化。Ssl2
奇怪的是,第一次AuthenticateAsClient
调用会成功,第二次会失败。
至于上传和下载是否成功,默认EnableThreadSafeDataConnections
为true,这会导致客户端被克隆并重新连接到服务器。但是,GetListing
不要GetNameListing
克隆连接。ActivateEncryption
在方法中放置断点,AuthenticateAsClient
将被多次调用。也许在SslStream
课堂上发生了一些连接池,并且多个连接池AuthenticateAsClient
导致了问题。值得注意的是,FtpClient.ValidateCertificate
即使AuthenticateAsClient
调用了两次,该事件也只调用了一次。这提供了一些缓存正在发生的证据。