首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SslStream.AuthenticateAsServer挂起

SslStream.AuthenticateAsServer挂起
EN

Stack Overflow用户
提问于 2017-03-29 22:50:48
回答 2查看 1.4K关注 0票数 4

使用VS10和.NET Framework4.0,我已经编写了三个c#单元测试来检查不同服务器/客户端协议设置的SslStream行为。

代码语言:javascript
复制
  private void InternalTestSsl(SslProtocols serverProtocols, SslProtocols clientProtocols)
  {
     X509Certificate2 certificate = RetrieveServerCertificate();
     var server = new TcpListener(new IPEndPoint(IPAddress.Any, 20000));
     server.Start();
     try
     {
        // create and execute a task for server operations
        var serverTask = new Task(() =>
        {
           TcpClient connectionToClient = server.AcceptTcpClient();
           var sslStream = new SslStream(connectionToClient.GetStream(), false, (a, b, c, d) => true, (a, b, c, d, e) => certificate);
           sslStream.AuthenticateAsServer(certificate, false, serverProtocols, true);
           Assert.IsTrue(sslStream.IsAuthenticated);
        });
        serverTask.Start();

        // create and execute a task for client operations
        var clientTask = new Task(() =>
        {
           var clientConnection = new TcpClient();
           clientConnection.Connect(new IPEndPoint(IPAddress.Loopback, 20000));
           var sslStream = new SslStream(clientConnection.GetStream(), false, (a, b, c, d) => true, (a, b, c, d, e) => null);
           sslStream.AuthenticateAsClient(Environment.MachineName, null, clientProtocols, true);
           Assert.IsTrue(sslStream.IsAuthenticated);
        });
        clientTask.Start();

        // wait for both server and client task to finish, check results
        if (!serverTask.Wait(TimeSpan.FromSeconds(1)))
        {
           throw new Exception("Server task did not end in time.");
        }
        if (!clientTask.Wait(TimeSpan.FromSeconds(1)))
        {
           throw new Exception("Client task did not end in time.");
        }
     }
     finally
     {
        server.Stop();
     }
  }

  [TestMethod]
  public void TestTlsTls()
  {
     InternalTestSsl(SslProtocols.Tls, SslProtocols.Tls);
  }

  [TestMethod]
  public void TestTlsSsl3()
  {
     InternalTestSsl(SslProtocols.Tls, SslProtocols.Ssl3);
  }

  [TestMethod]
  public void TestSsl3Tls()
  {
     InternalTestSsl(SslProtocols.Ssl3, SslProtocols.Tls);
  }

当服务器和客户端定义要使用的相同协议时,TestTlsTls传递(仅限TLS)。TestTlsSsl3的失败也是完全可以理解的(抛出AuthenticationException是因为服务器希望使用TLS,而客户端希望只播放SSL3)。

我原以为测试"TestSsl3Tls“会因为相同的AuthenticationException而失败,但是我的自定义异常”服务器任务没有及时结束“。被解雇了。在调试时,我发现只有客户端任务接收AuthenticationException,而serverTask仍然处于AuthenticateAsServer的调用中。交换等待命令的结果正好相反:用"TestSsl3Tls“替换”AuthenticationException“,用"TestTlsSsl3”替换"Client没有及时结束“。

这是正常的行为吗,AuthenticationException只被抛出一端,另一端等待(可能是新的身份验证尝试或断开连接)?

EN

回答 2

Stack Overflow用户

发布于 2017-10-29 21:59:13

我不知道你的问题的答案是否正常,但在我看来,这是一个错误,我最近遇到了同样的问题,因为我无法控制客户端安全协议,我的服务器最终总是死机。

我通过处理sslstream解决了这个问题,这会在AuthenticateAsServer中导致异常,从而允许我的服务器继续运行。

以下是代码片段

代码语言:javascript
复制
    // wait for both server and client task to finish, check results
    if (!serverTask.Wait(TimeSpan.FromSeconds(1)))
    {
       sslStream.Dispose(); // this line will cause an exception in the server task (AuthenticateAsServer), which allows the server to continue ...
    }

既然你的问题让我找到了冰冻问题的根源,我想我会分享我的解决方案…

票数 2
EN

Stack Overflow用户

发布于 2021-03-23 03:56:35

尝试:

代码语言:javascript
复制
socket.ReceiveTimeout = //some timeout in millis

我遇到了同样的问题,但提议的dispose解决方案在我的情况下不起作用。我的用例有点不同。我从TcpListener的异步Begin/EndAcceptSocket中获取套接字。当我使用协议不匹配的客户端调用AuthenticateAsServer时,它永远不会返回,处理流也不会使其返回。

我发现我必须设置socket.ReceiveTimeout,如下所示。

代码语言:javascript
复制
IAsyncResult asyncResult;//passed from BeginAcceptSocket callback
TcpListener listener = (TcpListener)asyncResult.AsyncState;
var socket = listener.EndAcceptSocket(asyncResult);
int timeoutInMillis;//set to whatever makes sense for your use case.

socket.ReceiveTimeout = timeoutInMillis; // This line fixed it for me

var stream = new SslStream(new NetworkStream(socket));
stream.AuthenticateAsServer(...); // This line doesn't hang any longer than the timeout.

在套接字上设置接收超时可确保AuthenticateAsServer调用在超时后返回,而不是在协议不匹配的情况下永远挂起。它可能不适用于所有场景,但在我的情况下,我从来没有发送过太多的数据,这应该超过几秒钟。

在所有典型的连接场景中,它只会进行身份验证,我不需要超时,但它消除了它可能永远挂起的边缘情况。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43096996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档