AuthenticateAsClient: System.IO.IOException: 从传输流中收到意外的EOF或0字节。

13

由于 Heartbleed 的影响,我们更新了网关服务器,但这个问题出现了。

由于 POODLE,不再支持 SSLv3。

  • 请注意,这个问题只存在于 Win7+ 系统中;WinXP 系统没有问题(相同的代码,不同的操作系统=问题);尽管 WinXP 不再是有效的操作系统,但我想提一下它的功能。

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

网关服务器是一个传输盒子,上面运行着带有 SSL 的 Apache HTTP Server。它的位置位于 DMZ 外部,并用于访问内部位于 DMZ 中的服务器。网关服务器上运行的软件版本为 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相关的回答对此应用程序的结果没有任何影响。
每次在运行于Win 7+机器上的应用程序中调用AuthenicateAsClient()时,都会发生异常 - 如果在WinXP机器上运行应用程序,则代码可以正常运行而不会出现异常。
欢迎提出任何解决方案的想法。
1个回答

7

1
如果你遇到了这个问题,很有可能在尝试 HttpWebRequest.GetResponse() 时会出现 "System.Net.WebException: The operation has timed out" 异常。需要注意的是,设置 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 可以解决 GetResponse() 超时的问题。 - Bret
2
关于 POODLE 和不再支持 SSLv3,您可以将 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; 更改为 Ssl3 - Bret
2
为了澄清此问题在.NET 4.0+上已不存在--如果您指定SecurityProtocolType.Tls并且正在使用.NET 2.0,则根据所使用的操作系统,可能会发生两种情况。在XP/2003中,此设置可以正常工作--但是,在使用Win7/8/2008+时,使用.Tls会失败--使用Wireshark,您可以看到发生的交互。 .NET 2.0不提供TLS扩展数据包数据的一部分的“ServerName”值--因此,将返回警告消息。在Win7+操作系统版本中,.NET 2.0会抛出异常。在XP/2003中,它被忽略并且可以正常工作。 - Bret
从 .NET 4.0 开始,ServerName已经在数据包中正确提交,不再返回警告消息。 - Bret
关于ServerName问题的更多细节,您可以在这里阅读。 - Bret
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接