Created
July 27, 2012 19:38
-
-
Save alexsandro-xpt/3190082 to your computer and use it in GitHub Desktop.
WTF proxy limit CONNECT verb to SSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | |
{ | |
//Browser wants to create a secure tunnel | |
//the user's browser should warn them of the certification errors however. | |
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 | |
{ | |
sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true); | |
} | |
catch (Exception) | |
{ | |
sslStream.Close(); | |
clientStreamReader.Close(); | |
connectStreamWriter.Close(); | |
clientStream.Close(); | |
return; | |
} | |
//HTTPS server created - we can now decrypt the client's traffic | |
clientStream = sslStream; | |
clientStreamReader = new StreamReader(sslStream); | |
outStream = sslStream; | |
//read the new http command. | |
httpCmd = clientStreamReader.ReadLine(); | |
if (String.IsNullOrEmpty(httpCmd)) | |
{ | |
clientStreamReader.Close(); | |
clientStream.Close(); | |
sslStream.Close(); | |
return; | |
} | |
splitBuffer = httpCmd.Split(spaceSplit, 3); | |
method = splitBuffer[0]; | |
remoteUri = remoteUri + splitBuffer[1]; | |
} | |
Console.WriteLine(remoteUri); | |
//construct the web request that we are going to issue on behalf of the client. | |
webReq = (HttpWebRequest)HttpWebRequest.Create(remoteUri); | |
webReq.Method = method; | |
webReq.ProtocolVersion = version; | |
//read the request headers from the client and copy them to our request | |
int contentLen = ReadRequestHeaders(clientStreamReader, webReq); | |
webReq.Proxy = null; | |
webReq.KeepAlive = false; | |
webReq.AllowAutoRedirect = false; | |
webReq.AutomaticDecompression = DecompressionMethods.None; | |
if(Server.DumpHeaders) | |
{ | |
Console.WriteLine(String.Format("{0} {1} HTTP/{2}",webReq.Method,webReq.RequestUri.AbsoluteUri, webReq.ProtocolVersion)); | |
DumpHeaderCollectionToConsole(webReq.Headers); | |
} | |
//using the completed request, check our cache | |
if (method.ToUpper() == "GET") | |
cacheEntry = ProxyCache.GetData(webReq); | |
else if (method.ToUpper() == "POST") | |
{ | |
char[] postBuffer = new char[contentLen]; | |
int bytesRead; | |
int totalBytesRead = 0; | |
StreamWriter sw = new StreamWriter(webReq.GetRequestStream()); | |
while (totalBytesRead < contentLen && (bytesRead = clientStreamReader.ReadBlock(postBuffer, 0, contentLen)) > 0) | |
{ | |
totalBytesRead += bytesRead; | |
sw.Write(postBuffer, 0, bytesRead); | |
if (ProxyServer.Server.DumpPostData) | |
Console.Write(postBuffer, 0, bytesRead); | |
} | |
if (Server.DumpPostData) | |
{ | |
Console.WriteLine(); | |
Console.WriteLine(); | |
} | |
sw.Close(); | |
} | |
if (cacheEntry == null) | |
{ | |
//Console.WriteLine(String.Format("ThreadID: {2} Requesting {0} on behalf of client {1}", webReq.RequestUri, client.Client.RemoteEndPoint.ToString(), Thread.CurrentThread.ManagedThreadId)); | |
webReq.Timeout = 15000; | |
try | |
{ | |
response = (HttpWebResponse)webReq.GetResponse(); | |
} | |
catch (WebException webEx) | |
{ | |
response = webEx.Response as HttpWebResponse; | |
} | |
if (response != null) | |
{ | |
List<Tuple<String,String>> responseHeaders = ProcessResponse(response); | |
StreamWriter myResponseWriter = new StreamWriter(outStream); | |
Stream responseStream = response.GetResponseStream(); | |
try | |
{ | |
//send the response status and response headers | |
WriteResponseStatus(response.StatusCode,response.StatusDescription, myResponseWriter); | |
WriteResponseHeaders(myResponseWriter, responseHeaders); | |
DateTime? expires = null; | |
CacheEntry entry = null; | |
Boolean canCache = (sslStream == null && ProxyCache.CanCache(response.Headers, ref expires)); | |
if (canCache) | |
{ | |
entry = ProxyCache.MakeEntry(webReq, response,responseHeaders, expires); | |
if (response.ContentLength > 0) | |
cacheStream = new MemoryStream(entry.ResponseBytes); | |
} | |
Byte[] buffer; | |
if (response.ContentLength > 0) | |
buffer = new Byte[response.ContentLength]; | |
else | |
buffer = new Byte[BUFFER_SIZE]; | |
int bytesRead; | |
while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) | |
{ | |
if (cacheStream != null) | |
cacheStream.Write(buffer, 0, bytesRead); | |
outStream.Write(buffer, 0, bytesRead); | |
if (Server.DumpResponseData) | |
Console.Write(UTF8Encoding.UTF8.GetString(buffer, 0, bytesRead)); | |
} | |
if (Server.DumpResponseData) | |
{ | |
Console.WriteLine(); | |
Console.WriteLine(); | |
} | |
responseStream.Close(); | |
if (cacheStream != null) | |
{ | |
cacheStream.Flush(); | |
cacheStream.Close(); | |
} | |
outStream.Flush(); | |
if (canCache) | |
ProxyCache.AddData(entry); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine(ex.Message); | |
} | |
finally | |
{ | |
responseStream.Close(); | |
response.Close(); | |
myResponseWriter.Close(); | |
} | |
} | |
} | |
else | |
{ | |
//serve from cache | |
StreamWriter myResponseWriter = new StreamWriter(outStream); | |
try | |
{ | |
WriteResponseStatus(cacheEntry.StatusCode, cacheEntry.StatusDescription, myResponseWriter); | |
WriteResponseHeaders(myResponseWriter, cacheEntry.Headers); | |
if (cacheEntry.ResponseBytes != null) | |
{ | |
outStream.Write(cacheEntry.ResponseBytes, 0, cacheEntry.ResponseBytes.Length); | |
if (ProxyServer.Server.DumpResponseData) | |
Console.Write(UTF8Encoding.UTF8.GetString(cacheEntry.ResponseBytes)); | |
} | |
myResponseWriter.Close(); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine(ex.Message); | |
} | |
finally | |
{ | |
myResponseWriter.Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Veja a linha 20, o verbo CONNECT está amarrado ao SSL onde necessita de um certificado digital, isto condiz com a especificação de um HTTP Proxy Server?