【问题标题】:AuthenticateAsClient: System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport streamAuthenticateAsClient: System.IO.IOException: 从传输流接收到意外的 EOF 或 0 字节
【发布时间】:2014-08-20 21:42:36
【问题描述】:

由于Heartbleed,我们的网关服务器已更新,并且出现了这个问题。

由于POODLE,不再支持 SSLv3。

  • 注意,这个问题只出现在 Win7+ 机器上; WinXP 盒子可以正常工作(相同的代码,不同的操作系统 = 问题);授予 WinXP 不再是有效的操作系统,只是想记下功能。

客户端应用程序 (.NET 2.0) 位于 Windows 7(或 8)机器上。服务器在网关服务器后面的 DMZ 中运行。需要注意的是,我发现这个问题在 .NET 4.0+ 上不再存在 - 但是由于遗留代码,我没有更新的余地。

Gateway Server 是运行带有 SSL 的 Apache HTTP Server 的传递框。它的位置在DMZ之外,用于访问DMZ内的Server。网关服务器上运行的软件版本为 Apache/2.2.25 (Win32)、mod_jk/1.2.39、mod_ssl/2.2.25、OpenSSL/1.0.1g

这是客户端应用程序上使用的代码(添加了大量的日志记录)...注意,“serverName”通常包含诸如“https://some.url.com”之类的值

private bool ConnectAndAuthenicate(string serverName, out TcpClient client, out SslStream sslStream)
{
    client = null;
    sslStream = null;
    try
    {
        client = new TcpClient(serverName, 443); // Create a TCP/IP client; ctor attempts connection
        Log("ConnectAndAuthenicate: Client CONNECTED"));

        sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
        Log("ConnectAndAuthenicate: SSL Stream CREATED"));
    }
    catch (Exception x)
    {
        Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: {0}", x.ToString()));

        if (x is SocketException)
        {
            SocketException s = x as SocketException;
            Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: Socket.ErrorCode: {0}", s.ErrorCode));
        }
        if (client != null) { client.Close(); client = null; }
        if (sslStream != null) { sslStream.Close(); sslStream = null; }
    }

    if (sslStream == null) return false;

    try
    {
        sslStream.ReadTimeout = 10000; // wait 10 seconds for a response ...
        Log("ConnectAndAuthenicate: AuthenticateAsClient CALLED ({0})", serverName));
        sslStream.AuthenticateAsClient(serverName);
        Log("ConnectAndAuthenicate: AuthenticateAsClient COMPLETED SUCCESSFULLY"));
        return true;
    }
    catch (Exception x)
    {
        Log("ConnectAndAuthenicate: EXCEPTION >> AuthenticateAsClient: {0}", x.ToString()));
        client.Close(); client = null;
        sslStream.Close(); sslStream = null;
    }
    return false;
}

注意 - 与 ServicePointManager 相关的 answers posted 绝对不会影响此应用程序的结果。

应用程序在 Win 7+ 机器上运行时,每次调用 AuthenicateAsClient() 时,都会发生异常 - 如果应用程序在 WinXP 机器上运行,代码可以正常工作而不会出现异常。

非常欢迎任何关于解决方案的想法。

【问题讨论】:

    标签: c#-2.0 tcpclient ioexception sslstream


    【解决方案1】:

    在使用SecurityProtocolType 设置ServicePointManager.SecurityProtocol 静态ctor 之后,我发现提到了另一个名为SslPolicy 的枚举——进一步研究发现AuthenicateAsClient has an overload 将SslPolicy 作为参数。

    在上面的代码中改变这一行解决了这个问题:

    sslStream.AuthenticateAsClient(serverName, null, SslPolicy.Tls, false);
    

    【讨论】:

    • 如果您遇到此问题 - 当您尝试 HttpWebRequest.GetResponse() 时,您可能会遇到“System.Net.WebException:操作已超时”异常的可能性很高。它应该需要注意的是设置ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;修复了 GetResponse() 超时。
    • 关于POODLE不再支持SSLv3,您可以将ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;改为Ssl3
    • 澄清this problem is no longer present on .NET 4.0+ - 如果您指定 SecurityProtocolType.Tls 并且正在使用 .NET 2.0,那么根据所使用的操作系统可能会出现两种情况。在 XP/2003 中,此设置工作正常 - 但是,当使用 Win7/8/2008+ 时,使用 .Tls 失败 - 使用 Wireshark,您可以看到发生的交互。 .NET 2.0 不提供作为 TLS 扩展数据包数据一部分的 ServerName 值 - 因此,会返回一条警告消息。在 Win7+ OS 版本中,.NET 2.0 会为此引发异常。在 XP/2003 中,它被忽略并有效。
    • ...从.NET 4.0开始,ServerName在包数据中正确提交,不再返回警告信息。
    • 关于这个ServerName惨败的更多细节,你可以阅读它here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2022-12-16
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    相关资源
    最近更新 更多