I'm trying to connect to HTTPS server through proxy using sockets. As far as I know when using HTTP proxy one should connect socket to it and then interact with it as it is the real server. With HTTP this approach works, but with HTTPS isn't. Why?
Here's simple program that connects to HTTPS server
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();
}
}
}
It successfully connects when proxy = host
and proxyPort = 443
. But when I set them to 127.0.0.1:8888 (fiddler proxy on localhost) it doesn't work. Program hangs at sslStream.AuthenticateAsClient(host);
Why? Fiddler supports HTTPS (browsers are able to connect through it).
PS No, I can't use HttpWebRequest
in my case.
Managed to solve it myself. Here's the solution:
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();
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.