2011-08-04 38 views
4

我試圖通過代理使用套接字連接到HTTPS服務器。據我所知,當使用HTTP代理時,應該將套接字連接到它,然後與它進行交互,因爲它是真正的服務器。使用HTTP這種方法可行,但HTTPS不適用。爲什麼?如何連接到HTTPS代理?

這是一個簡單的程序,連接到HTTPS服務器

using System; 
using System.Text; 
using System.Net.Sockets; 
using System.Net.Security; 

namespace SslTcpClient 
{ 
    public class SslTcpClient 
    { 
     public static void Main(string[] args) 
     { 
      string host = "encrypted.google.com"; 
      string proxy = "127.0.0.1";//host; 
      int proxyPort = 8888;//443; 

      // Connect socket 
      TcpClient client = new TcpClient(proxy, proxyPort); 

      // Wrap in SSL stream 
      SslStream sslStream = new SslStream(client.GetStream()); 
      sslStream.AuthenticateAsClient(host); 

      // Send request 
      byte[] request = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/ HTTP/1.1\r\nHost: {0}\r\n\r\n", host)); 
      sslStream.Write(request); 
      sslStream.Flush(); 

      // Read response 
      byte[] buffer = new byte[2048]; 
      int bytes; 
      do 
      { 
       bytes = sslStream.Read(buffer, 0, buffer.Length); 
       Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes)); 
      } while (bytes != 0); 

      client.Close(); 
      Console.ReadKey(); 
     } 
    } 
} 

連接成功時proxy = hostproxyPort = 443。但是,當我將它們設置爲127.0.0.1:8888(localhost上的fiddler代理)時,它不起作用。程序掛在sslStream.AuthenticateAsClient(host);爲什麼?提琴手支持HTTPS(瀏覽器可以通過它連接)。

P.S.不,我不能在我的情況下使用HttpWebRequest

+1

看來,我必須先通過代理建立TCP隧道。它可以使用CONNECT方法完成。但是我仍然無法做到這一點。 – Poma

回答

7

自己解決它。這裏的解決方案:

using System; 
using System.Text; 
using System.Net.Sockets; 
using System.Net.Security; 

namespace SslTcpClient 
{ 
    public class SslTcpClient 
    { 
     public static void Main(string[] args) 
     { 
      string host = "encrypted.google.com"; 
      string proxy = "127.0.0.1";//host; 
      int proxyPort = 8888;//443; 

      byte[] buffer = new byte[2048]; 
      int bytes; 

      // Connect socket 
      TcpClient client = new TcpClient(proxy, proxyPort); 
      NetworkStream stream = client.GetStream(); 

      // Establish Tcp tunnel 
      byte[] tunnelRequest = Encoding.UTF8.GetBytes(String.Format("CONNECT {0}:443 HTTP/1.1\r\nHost: {0}\r\n\r\n", host)); 
      stream.Write(tunnelRequest , 0, tunnelRequest.Length); 
      stream.Flush(); 

      // Read response to CONNECT request 
      // There should be loop that reads multiple packets 
      bytes = stream.Read(buffer, 0, buffer.Length); 
      Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes)); 

      // Wrap in SSL stream 
      SslStream sslStream = new SslStream(stream); 
      sslStream.AuthenticateAsClient(host); 

      // Send request 
      byte[] request = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/ HTTP/1.1\r\nHost: {0}\r\n\r\n", host)); 
      sslStream.Write(request, 0, request.Length); 
      sslStream.Flush(); 

      // Read response 
      do 
      { 
       bytes = sslStream.Read(buffer, 0, buffer.Length); 
       Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes)); 
      } while (bytes != 0); 

      client.Close(); 
      Console.ReadKey(); 
     } 
    } 
} 
+0

嗨Poma,如何使用此代碼作爲服務器?我想下載encrypted.google.com頁面併發送到客戶端瀏覽器。 –