HTTPS代理实现(SSLStream) [英] HTTPS Proxy Implementation (SSLStream)

查看:197
本文介绍了HTTPS代理实现(SSLStream)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've written a console application that acts as a proxy server. Now I like to implement SSL as well. Do not like to decrypt any traffic. Just like a normal https proxy. I'm not sure how I should go on.

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 ?我应该使用AuthenticateAsServer并以某种方式从AuthenticateAsClient传递证书吗?

Should I directly write everything into sslStream? What about the browser connection proxyClient. Did I need to wrap the stream as well or can I just write everything directly into proxyStream? Should I use AuthenticateAsServer and pass somehow the certificate from AuthenticateAsClient?


  1. IE向我的代理发出CONNECT请求

  2. 我的代理人看到它是一个CONNECT请求并且获取IP:端口
    目的地(例如,www.hotmail.com:443)

  3. 我的代理创建了一个新的TCP连接到www.hotmail.com:443

  4. 我的代理从这个目的地获取一个SslStream并调用AuthenticateAsClient - 这为我的代理提供了与Hotmail方面的安全连接

  5. 我的代理然后将HTTP / 1.0 200消息发送回浏览器以说CONNECT成功

  6. 我的代理然后从中获取一个SslStream浏览器连接和调用AuthenticateAsServer - 为我的代理提供与浏览器端的安全连接

  1. IE issues a CONNECT request to my proxy
  2. my proxy sees that it's a CONNECT request and gets the IP: port of the destination (eg, www.hotmail.com:443)
  3. my proxy creates a new TCP connection to www.hotmail.com:443
  4. my proxy gets a SslStream from this destination and calls AuthenticateAsClient - this gives my proxy a secure connection to the Hotmail side of things
  5. my proxy then sends an "HTTP/1.0 200" message back to the browser to say that the CONNECT was successful
  6. my proxy then gets a SslStream from the browser connection and calls AuthenticateAsServer - gives my proxy a secure connection to the browser side of things

我看到了这一点,但AuthenticateAsServer如何没有假证书。我可以像在正常的流中那样写或者我应该考虑一下吗?

I saw this, but how AuthenticateAsServer without a fake certificate. Can I just write that like in my normal streams or should i consider something?

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();
    }
}


推荐答案


IE向我的代理发出CONNECT请求
我的代理看到它的CONNECT请求并获取目的地的ip:端口(例如,www.hotmail.com:443)
我的代理创建了一个新的TCP连接到www.hotmail.com:443

IE issues a CONNECT request to my proxy My proxy sees that its a CONNECT request and gets the ip:port of the destination (eg, www.hotmail.com:443) My proxy creates a new TCP connection to www.hotmail.com:443

到目前为止一切正确。


我的代理从此目的地获取一个SslStream并调用AuthenticateAsClient - 这使我的代理与Hotmail方面的安全连接

My proxy gets an SslStream from this destination and calls AuthenticateAsClient - this gives my proxy a secure connection to the hotmail side of things

没有。您的代理应使用您已有的纯文本连接。

No. Your proxy should use the plain-text connection you already have.


我的代理然后发送HTTP / 1.0 200消息返回浏览器说CONNECT成功。

My proxy then sends an "HTTP/1.0 200" message back to the browser to say that the CONNECT was successful.

正确。否则,如果连接失败,则发回适当的HTTP失败响应。

Correct. Or else if you got a connection failure you send back an appropriate HTTP failure response.


我的代理然后从浏览器连接获取SslStream调用AuthenticateAsServer - 为我的代理提供与浏览器端的安全连接

My proxy then gets an SslStream from the browser connection and calls AuthenticateAsServer - gives my proxy a secure connection to the browser side of things

否。您的代理继续使用与浏览器的纯文本连接。

No. Your proxy continues to use the plaintext connection to the browser.


AuthenticateAsServer如何没有假证书?

how AuthenticateAsServer without fake certificate?

您根本不需要这样做。

此时浏览器和上游服务器已准备就绪执行SSL握手。但正如您所说,您不想嗅探内容,您无需自己成为SSL端点。您现在要做的就是同时复制两个方向的字节。端点将进行SSL握手,就像你不在那里一样。

At this point the browser and the upstream server are ready to execute the SSL handshake. But as you said you don't want to sniff the contents, you have no need to be an SSL endpoint yourself. All you have to do now is copy bytes in both directions simultaneously. The endpoints will SSL-handshake just as though you weren't there.

这篇关于HTTPS代理实现(SSLStream)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆