2013-02-03 64 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,我覺得你的評論的其餘部分有真正的解決方案,但我還不能理解做什麼作爲行動。你能否給我提供一些教程或向我發送代碼?感謝您的回覆。 –

相關問題