Skip to content

Instantly share code, notes, and snippets.

@alexsandro-xpt
Created July 27, 2012 19:38
Show Gist options
  • Save alexsandro-xpt/3190082 to your computer and use it in GitHub Desktop.
Save alexsandro-xpt/3190082 to your computer and use it in GitHub Desktop.
WTF proxy limit CONNECT verb to SSL
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();
}
}
}
@alexsandro-xpt
Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment