问题
I am developing a proxy server application similar to CCProxy. Its working fine for HTTP but not HTTPS. Its throwing exception when AuthenticateAsServer() method is called on SslStream object. I also don't know whether I have supplied proper certificate, I don't know how to create a certificate. I just provided the certificate which came with the code that I downloaded online. Here is the code:
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...
Also, instead of sslStream.AuthenticateAsServer, if I use ssStream.AuthenticateAsClient method I get AuthenticationException with message "A call to SSPI failed, see inner exception." and InnerException gives message as "The message received was unexpected or badly formatted"
When I am using sslstream.AuthenticateAsServer() method, I need to create certificate for each new HTTPS host and pass it with this method. If I provide the self signed certificate, the request succeeds. But problem is, for how many new HTTPS requests will I keep creating certificates manually and assign it to AuthenticateAsServer()?
回答1:
For the serverside certificate, most certificates correspond to a FQDN (so server1.localhost.local), although there can be wildcard certs (*.localhost.local). When you use AuthenticateAsClient method, that could be one of two things, 1) The Certificate doesnt have the Extended Key Usage for Client Authentication or 2) you didnt pass the right password for it to read the cert/private key. To get past both these hurdles rather quickly i would suggest creating an OpenSSL CA and then generating a CA and Server Cert. There is tons of documentation on how to do this and should take 30 minutes tops for someone who has never created one before....(Also i would suggest exporting the cert into pkcs12 extension for the CA to be chained in with the Server Cert).
来源:https://stackoverflow.com/questions/14671112/sslstream-authenticateasserver-exception-the-server-mode-ssl-must-use-a-certif