2013-02-03 65 views
1

我正在开发类似于CCProxy的代理服务器应用程序。它适用于HTTP,但不适用于HTTPS。它在SslStream对象上调用AuthenticateAsServer()方法时引发异常。 我也不知道我是否提供了适当的证书,我不知道如何创建证书。我只是提供了随我在线下载的代码一起提供的证书。 下面是代码:SslStream.AuthenticateAsServer异常 - 服务器模式SSL必须使用带有关联私钥的证书

private static void DoHttpProcessing(TcpClient client) 
    { 
     Stream clientStream = client.GetStream(); 
     Stream outStream = clientStream; 
     SslStream sslStream = null; 
     StreamReader clientStreamReader = new StreamReader(clientStream); 
     CacheEntry cacheEntry = null; 
     MemoryStream cacheStream = null; 

     if (Server.DumpHeaders || Server.DumpPostData || Server.DumpResponseData) 
     { 
      Monitor.TryEnter(_outputLockObj, TimeSpan.FromMilliseconds(-1.0)); 
     } 

     try 
     { 
      //read the first line HTTP command 
      String httpCmd = clientStreamReader.ReadLine(); 
      if (String.IsNullOrEmpty(httpCmd)) 
      { 
       clientStreamReader.Close(); 
       clientStream.Close(); 
       return; 
      } 
      //break up the line into three components 
      String[] splitBuffer = httpCmd.Split(spaceSplit, 3); 

      String method = splitBuffer[0]; 
      String remoteUri = splitBuffer[1]; 
      Version version = new Version(1, 0); 

      HttpWebRequest webReq; 
      HttpWebResponse response = null; 
      if (splitBuffer[0].ToUpper() == "CONNECT") 
      { 

       remoteUri = "https://" + splitBuffer[1]; 
       while (!String.IsNullOrEmpty(clientStreamReader.ReadLine())) ; 
       StreamWriter connectStreamWriter = new StreamWriter(clientStream); 
       connectStreamWriter.WriteLine("HTTP/1.0 200 Connection established"); 
       connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); 
       connectStreamWriter.WriteLine("Proxy-agent: matt-dot-net"); 
       connectStreamWriter.WriteLine(); 
       connectStreamWriter.Flush(); 

       sslStream = new SslStream(clientStream, false); 

       try 
       { 
      // HERE I RECEIVE EXCEPTION 
        sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true); 


       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.Message); 
        sslStream.Close(); 
        clientStreamReader.Close(); 
        connectStreamWriter.Close(); 
        clientStream.Close(); 
        return; 
       }//further code goes here... 

此外,而不是sslStream.AuthenticateAsServer,如果我用ssStream.AuthenticateAsClient方法,我得到的AuthenticationException与信息“以SSPI调用失败,请参见内部异常。”并且InnerException将消息显示为“收到的消息意外或格式不正确”

当我使用sslstream.AuthenticateAsServer()方法时,我需要为每个新的HTTPS主机创建证书并使用此方法传递它。如果我提供自签名证书,请求成功。但问题是,有多少新的HTTPS请求会手动创建证书并将其分配给AuthenticateAsServer()?

回答

0

对于服务器端证书,大多数证书对应于FQDN(即server1.localhost.local),尽管可以有通配符证书(* .localhost.local)。当您使用AuthenticateAsClient方法时,这可能是以下两种情况之一:1)证书没有用于客户端身份验证的扩展密钥用法,或者2)您没有传递正确的密码来读取证书/私钥。为了快速通过这两个障碍,我会建议创建一个OpenSSL CA,然后生成一个CA和服务器证书。有大量关于如何做到这一点的文档,应该花30分钟时间给以前从未创建过的人......(另外我建议将证书导出到pkcs12扩展中,以便将CA与服务器证书链接在一起)。

+0

感谢您的回答Jladd。我相信AuthenticateAsServer是正确的使用方法。因为我的代理应用程序充当客户端的服务器。部分是因为客户端浏览器提供了错误的证书警告,因为它期望证书具有相同的URL。是否有任何方法可以下载并转发来自服务器的相同证书?或者,请您演示解决此问题的代码? –

+0

您可以在浏览器中下载证书,并在那里添加一个例外说,总是接受这个URL的证书。但是你不能在代码中做到这一点。现在,如果你还想要一个比这更简单的方法,你可以进入你的主机文件并在那里添加一行,使用指向代理服务IP和poof的cert的URL,它会认为域名实际上(注意:那应该只是在测试阶段。)另外,我重新审视了您的代码,并且您将希望摆脱SslProtocols.Ssl2,因为SSL V2非常不安全并且过时 – jladd

+0

在浏览器中添加异常是没有妥善的解决方因为客户端每次都会不断请求新的URL,并且客户端不可能每次都添加异常。对不起,jlAdd,我觉得你的评论的其余部分有真正的解决方案,但我还不能理解做什么作为行动。你能否给我提供一些教程或向我发送代码?感谢您的回复。 –

相关问题