C# HTTPS代理实现(SSLStream)

C# HTTPS代理实现(SSLStream),c#,ssl,https,proxy,C#,Ssl,Https,Proxy,我已经编写了一个充当代理服务器的控制台应用程序。现在我也想实现SSL。不喜欢解密任何流量。就像普通的https代理一样。我不知道该怎么办 var host = text.Remove(0, connectText.Length + 1); var hostIndex = host.IndexOf(" ", StringComparison.Ordinal); var hostEntry = host.Remove(hostIndex).Split(new []{":"}, StringSplit

我已经编写了一个充当代理服务器的控制台应用程序。现在我也想实现SSL。不喜欢解密任何流量。就像普通的https代理一样。我不知道该怎么办

var host = text.Remove(0, connectText.Length + 1);
var hostIndex = host.IndexOf(" ", StringComparison.Ordinal);
var hostEntry = host.Remove(hostIndex).Split(new []{":"}, StringSplitOptions.None);
requestClient.Connect(hostEntry[0], Convert.ToInt32(hostEntry[1]));
requestStream = requestClient.GetStream();
var sslStream = new SslStream(requestStream, false, (x1,x2,x3,x4) => true);
sslStream.AuthenticateAsClient(hostEntry[0]);
const string sslResponse = "HTTP/1.0 200 Connection established\r\n\r\n";
var sslResponseBytes = Encoding.UTF8.GetBytes(sslResponse);
proxyStream.Write(sslResponseBytes, 0, sslResponseBytes.Length);
proxyStream.Flush();
我应该直接将所有内容写入sslStream吗?浏览器连接如何
proxyClient
。我是否也需要包装流,还是可以将所有内容直接写入
proxyStream
?我应该使用AuthenticateTaserver并以某种方式从AuthenticateTasClient传递证书吗

  • IE向我的代理发出连接请求
  • 我的代理看到这是一个连接请求,并获取 目的地(如www.hotmail.com:443)
  • 我的代理创建到www.hotmail.com:443的新TCP连接
  • 我的代理从这个目的地获取一个SslStream并调用AuthenticateTaseClient——这使我的代理与Hotmail端建立了一个安全的连接
  • 然后,我的代理将“HTTP/1.0 200”消息发送回浏览器,表示连接成功
  • 然后,我的代理从浏览器连接获取SslStream并调用AuthenticateAsServer-为我的代理提供与浏览器端的安全连接
  • 我看到了这一点,但如何在没有假证书的情况下验证服务器。我能像在正常的溪流中那样写吗?或者我应该考虑什么?


    static void Main(字符串[]args)
    {
    var tcpServer=newtcplistener(IPAddress.Parse(“127.0.0.1”),8080);
    tcpServer.Start();
    while(true)
    {
    var proxyClient=tcpServer.AcceptTcpClient();
    var requestClient=new TcpClient();
    var proxyStream=proxyClient.GetStream();
    NetworkStream requestStream=null;
    var bytes=新字节[proxyClient.ReceiveBufferSize];
    var hostHeaderAvailable=0;
    整数计数;
    while(proxyStream.DataAvailable)
    {
    count=proxyStream.Read(字节,0,字节.长度);
    如果(hostHeaderAvailable==0)
    {
    var text=Encoding.UTF8.GetString(字节);
    常量字符串connectText=“connect”;
    常量字符串hostText=“主机:”;
    //HTTPS尚未完全实现
    if(text.ToLower().StartsWith(connectText))
    {
    var host=text.Remove(0,connectText.Length+1);
    var hostIndex=host.IndexOf(“,StringComparison.Ordinal);
    var hostEntry=host.Remove(hostIndex.Split)(新[]{:“},StringSplitOptions.None);
    requestClient.Connect(hostEntry[0],Convert.ToInt32(hostEntry[1]);
    requestStream=requestClient.GetStream();
    var sslStream=新的sslStream(requestStream,false,(x1,x2,x3,x4)=>true);
    sslStream.client(hostEntry[0]);
    const string sslResponse=“HTTP/1.0 200已建立连接\r\n\r\n”;
    var sslResponseBytes=Encoding.UTF8.GetBytes(sslResponse);
    proxyStream.Write(sslResponseBytes,0,sslResponseBytes.Length);
    proxyStream.Flush();
    }
    //HTTP工作起来很有魅力
    否则{
    var hostIndex=text.IndexOf(hostText,StringComparison.Ordinal);
    如果(主机索引<0)
    继续;
    var host=text.Remove(0,hostIndex+hostText.Length);
    hostIndex=host.IndexOf(“\n”,StringComparison.Ordinal);
    如果(主机索引<0)
    继续;
    host=host.Remove(hostIndex.Replace(“\r”,”);
    requestClient.Connect(主机,80);
    requestStream=requestClient.GetStream();
    }
    }
    hostHeaderAvailable++;
    if(requestClient.Connected){
    写入(字节,0,计数);
    }
    }
    如果(!requestClient.Connected){
    proxyStream.Close();
    proxyClient.Close();
    继续;
    }
    var超时=0;
    而(!requestStream.DataAvailable){
    如果(超时>12)
    打破
    睡眠(500);
    超时++;
    }
    while(requestStream.DataAvailable)
    {
    count=requestStream.Read(字节,0,字节.长度);
    proxyStream.Write(字节,0,计数);
    }
    proxyStream.Close();
    proxyClient.Close();
    }
    }
    
    IE向我的代理发出连接请求 我的代理看到这是一个连接请求,并获取目的地的ip:端口(例如,www.hotmail.com:443) 我的代理创建到www.hotmail.com:443的新TCP连接

    到目前为止都是正确的

    我的代理从这个目的地获取一个SslStream并调用AuthenticateTaseClient——这使我的代理与hotmail端建立了一个安全的连接

    不可以。您的代理应该使用您已有的纯文本连接

    然后,我的代理将“HTTP/1.0 200”消息发送回浏览器,表示连接成功

    对。或者,如果出现连接故障,则返回相应的HTTP故障响应

    然后,我的代理从浏览器连接获取一个SslStream并调用AuthenticateTaserver-为我的代理提供一个到浏览器端的安全连接

    否。您的代理继续使用到浏览器的明文连接

    如何在没有假证书的情况下认证服务器

    你根本不必这么做

    此时,浏览器和上游服务器已准备好执行SSL握手。但正如您所说,您不想嗅探内容,您自己也不需要成为SSL端点。您现在所要做的就是同时在两个方向上复制字节。端点将进行SSL握手,就像
    static void Main(string[] args)
    {
        var tcpServer = new TcpListener(IPAddress.Parse("127.0.0.1"), 8080);
        tcpServer.Start();
        while (true)
        {
            var proxyClient = tcpServer.AcceptTcpClient();
            var requestClient = new TcpClient();
            var proxyStream = proxyClient.GetStream();
            NetworkStream requestStream = null;
            var bytes = new byte[proxyClient.ReceiveBufferSize];
            var hostHeaderAvailable = 0;
            int count;
    
            while (proxyStream.DataAvailable)
            {
                count = proxyStream.Read(bytes, 0, bytes.Length);
                if (hostHeaderAvailable == 0)
                {
                    var text = Encoding.UTF8.GetString(bytes);
                    const string connectText = "connect";
                    const string hostText = "Host: ";
                    //HTTPS NOT FULLY IMPLEMENTED YET
                    if (text.ToLower().StartsWith(connectText))
                    {
                        var host = text.Remove(0, connectText.Length + 1);
                        var hostIndex = host.IndexOf(" ", StringComparison.Ordinal);
                        var hostEntry = host.Remove(hostIndex).Split(new []{":"}, StringSplitOptions.None);
                        requestClient.Connect(hostEntry[0], Convert.ToInt32(hostEntry[1]));
                        requestStream = requestClient.GetStream();
                        var sslStream = new SslStream(requestStream, false, (x1,x2,x3,x4) => true);
                        sslStream.AuthenticateAsClient(hostEntry[0]);
                        const string sslResponse = "HTTP/1.0 200 Connection established\r\n\r\n";
                        var sslResponseBytes = Encoding.UTF8.GetBytes(sslResponse);
                        proxyStream.Write(sslResponseBytes, 0, sslResponseBytes.Length);
                        proxyStream.Flush();
                    }
                    //HTTP WORKS LIKE A CHARM
                    else {
                        var hostIndex = text.IndexOf(hostText, StringComparison.Ordinal);
                        if (hostIndex < 0)
                            continue;
                        var host = text.Remove(0, hostIndex + hostText.Length);
                        hostIndex = host.IndexOf("\n", StringComparison.Ordinal);
                        if (hostIndex < 0)
                            continue;
                        host = host.Remove(hostIndex).Replace("\r", "");
                        requestClient.Connect(host, 80);
                        requestStream = requestClient.GetStream();
                    }
                }
                hostHeaderAvailable++;
                if (requestClient.Connected) {
                    requestStream.Write(bytes, 0, count);
                }
            }
    
            if (!requestClient.Connected) {
                proxyStream.Close();
                proxyClient.Close();
                continue;
            }
    
            var timeout = 0;
            while (!requestStream.DataAvailable) {
                if (timeout > 12)
                    break;
                Thread.Sleep(500);
                timeout++;
            }
    
            while (requestStream.DataAvailable)
            {
                count = requestStream.Read(bytes, 0, bytes.Length);
                proxyStream.Write(bytes, 0, count);
            }
            proxyStream.Close();
            proxyClient.Close();
        }
    }