Search code examples
c#httpshttprequestwindows-8.1tcpclient

Http CONNECT request return empty respone


I want to read Https page using TcpClient. I use below code

var client = new TcpClient(url, 443);//"127.0.0.1", 8888);// Fiddler port
client.SendTimeout = 30000;
Stream responseStream = client.GetStream();

// send CONNECT request to server
byte[] tunnelRequest = Encoding.ASCII.GetBytes("CONNECT www.google.com:443 HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:44.0) Gecko/20100101 Firefox/35.0\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: www.google.com:443\r\n\r\n");
responseStream.Write(tunnelRequest, 0, tunnelRequest.Length);
responseStream.Flush();

// read CONNECT response 
string connectResponse = ReadResponse(responseStream);
Console.WriteLine("server connect response :  " + connectResponse);

that send CONNECT request to host (google.com)

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.google.com:443

respone must be somthing like this

HTTP/1.1 200 Connection Established
StartTime: 22:42:38.774
Connection: close

but responseStream return nothing. when I use Fiddler as a proxy

var client = new TcpClient("127.0.0.1", 8888);

it works fine and return 200 response. There is something wrong that Fiddler fixed it?

I use windows 8.1 and test with .Net 2 and 4.5.1.


Solution

  • Base on rfc CONNECT method used when proxy exists.

    Since TLS, in particular, requires end-to-end connectivity to provide authentication and prevent man-in-the-middle attacks, this memo specifies the CONNECT method to establish a tunnel across proxies.

    In case of direct communication :

    var client = new TcpClient("127.0.0.1", 8888);//url, 443);//
    client.SendTimeout = 30000;
    Stream responseStream = client.GetStream();
    
    // Wrap in SSL stream
    SslStream sslStream = new SslStream(responseStream);
    sslStream.AuthenticateAsClient(url);
    
    byte[] byts = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: keep-alive\r\n\r\n");
    sslStream.Write(byts, 0, byts.Length);
    
    var str = ReadResponse(sslStream);