im writing an HTTP proxy in C#. the proxy should capture both HTTP and HTTPS traffic from the web browser. so far i have implemented the GET and POST requests no problem, but the CONNECT request i am having a little trouble with. there does not appear to be any help whatsoever on the internet regarding the CONNECT request and C#. below are the steps for what i do so far. this example shows what happens when i try to log into my hotmail account, which of course is done securely and thus generates a CONNECT request:

1) my server socket accepts a connection from the web browser

TcpClient tcpBrowser = _proxyServer.AcceptTcpClient()

2) get the stream for the browser

NetworkStream networkStreamBrowser = tcpBrowser.GetStream();

3) read the data from the browser's stream

networkStreamBrowser.Read(buff, 0, buff.Length);

4) i call my own function that parses the above data, to get the host and port number, and the request type. so the data in this case will be:

CONNECT login.live.com:443 HTTP/1.0
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)
Proxy-Connection: Keep-Alive
Content-Length: 0
Host: login.live.com
Pragma: no-cache

and so from this i get the host (login.live.com), the port (443), and the request type (CONNECT)

5) i detect that this is a CONNECT request, and open up an SSL stream to the above server:

TcpClient clDestination = new TcpClient();
clDestination.Connect(host, port);
SslStream sslStream = new SslStream(clDest.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

the ValidateServerCertificate callback fires and i can see at this stage all is good - i have the server certificate.

6) i send an 'ok' message back to the web browser:

string strSSLResponse = "HTTP/1.0 200 Connection established\r\n\r\n";
AsciiEncoding enc = new AsciiEncoding();
byte[] bytSSLResponse = enc.GetBytes(strSSLResponse);
networkStreamBrowser.Write(bytSSLResponse, 0, bytSSLResponse.Length);

7) at this point i expect the web browser to respond by sending the form POST data (my hotmail user name and password that i entered at the begining). i would then simply forward this data on to the server through the SSL stream. however the data that i receive back from the browser is all mangled:

networkStreamBrowser.Read(buff, 0, buff.Length);
//confirm that the data is mangled by converting it to string
StringBuilder sb = new StringBuilder();
char[] chArray = new char[iBytesReadFromBrowser];
Array.Copy(bytesReadFromBrowser, chArray, iBytesReadFromBrowser);
string strMangledDataFromBrowser = sb.ToString();
//strMangledDataFromBrowser in the debugger is something like
"\0\0S\0\0O\0Iúä^Æ;Gy!ÁÚS¤h2lU\\¨)ð¢tÃ\t \0\01ñ¡K÷½ÃaÌ.¦\\ê<\fsawhm(E/ý\0\b\0\0\n\0\0\0"

what i would EXPECT to get from the browser is something like

POST /ppsecure/post.srf?wa=wsignin1.0&rpsnv=10&ct=1241101484&rver=5.5.4177.0&wp=MBI&wreply=http:%2F%2Fmail.live.com%2Fdefault.aspx&lc=2057&id=64855&mkt=en-GB&bk=1241101484 HTTP/1.1\r\n\r\n
//the actual POST data

the reason i would expect to see this is because i have used the fiddler http debugger to view the http requests, and this is what fiddler captures. in addition, the only SSL encryption taking place is between my proxy and the web server - the data between the browser and my proxy should be plain text.

so my question is, why is the data coming back mangled from the web browser ? can you spot anything wrong in my code or my logic ?

any help very much appreciated.

Recommended Answers

I don't see where the certificate from the server is passed on to the browser.

Jump to Post

All 3 Replies

I do apologise for opening an extreamely old thread, but this is exactly the same problem I am experiencing, and if the OP or anyone else has a sample / fix I would very much appreciate the assistance.

I don't see where the certificate from the server is passed on to the browser.

hi ! im the OP. i dont have the code because i dont work for the company any more that my problem was for. but IIRC.....the reason it was mangled is because i was using the NetworkStream.Read method, which is just the underlying stream and therefore is just the encrypted SSL. I used SslStream.Read instead and this gave me the decrypted text. you dont manually pass the certificate anywhere - the AuthenticateasClient/Server methods do all that for you.

i think i posted this on msdn forum too and the guy who responded was very helpful so might be worth checking my posts on msdn (username = unclepauly2).

this gave me my most challenging project to date, it was a right headache. good luck ;)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.20 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.