当前位置: 首页 > 知识库问答 >
问题:

HTTPS代理实现(SSLStream)

楚鸿波
2023-03-14

我已经编写了一个充当代理服务器的控制台应用程序。现在我也喜欢实现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吗?浏览器连接如何。我是否也需要包装流,还是可以将所有内容直接写入代理流?我应该使用AuthenticateAsServer并以某种方式从AuthenticateAsServer传递证书吗?

  1. IE向我的代理发出连接请求
  2. 我的代理看到这是一个连接请求,并获取目标的IP:端口(例如,www.hotmail.com:443)
  3. 我的代理创建到www.hotmail的新TCP连接。通讯:443
  4. 我的代理从该目标获取SslStream并调用AuthenticateAsClient-这为我的代理提供了与Hotmail端的安全连接
  5. 然后,我的代理将“HTTP/1.0 200”消息发送回浏览器,表示连接成功
  6. 然后,我的代理从浏览器连接获取SslStream并调用AuthenticateAsServer-为我的代理提供与浏览器端的安全连接

我看到了这一点,但如何在没有假证书的情况下对服务器进行身份验证。我可以像在我的普通流中那样写吗?或者我应该考虑一下什么?

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

共有2个答案

詹正浩
2023-03-14

除了来自EJP的答案之外,代理在成功的CONNECT请求后只需在终端服务器和客户端之间打开一条隧道。但是,客户端需要将套接字升级到HTTPS并继续通过CONNECT请求中使用的相同套接字发送数据。另一方面,代理只需要在终端服务器和客户端之间维护这条隧道,充当一个简单的透明代理,只需将加密数据从一个套接字复制到另一个套接字。

查看此文档以了解有关隧道的更多详细信息

裴嘉良
2023-03-14

IE向我的代理发出连接请求我的代理看到这是一个连接请求并获取目标的ip:端口(例如,www.hotmail.com:443)。我的代理创建到www.hotmail的新TCP连接。通讯:443

到目前为止都是正确的。

我的代理从这个目的地获得一个SslStream并调用AuthentiateAsClient-这使我的代理与hotmail端的事物有一个安全的连接

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

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

对的或者,如果连接失败,则返回相应的HTTP失败响应。

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

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

如何在没有假证书的情况下对服务器进行身份验证?

你根本不必这么做。

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

 类似资料:
  • 本文向大家介绍Python代码实现http/https代理服务器的脚本,包括了Python代码实现http/https代理服务器的脚本的使用技巧和注意事项,需要的朋友参考一下 一个几百行代码做出http/https代理服务器的脚本,启动即可做http https透明代理使用 python proxy.py 8992 使用非阻塞io模式,性能还可以。 可以和浏览器一样保持长连接,代码有点乱,不管那么

  • 本文向大家介绍nginx https反向代理tomcat的2种实现方法,包括了nginx https反向代理tomcat的2种实现方法的使用技巧和注意事项,需要的朋友参考一下 反向代理 在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂拥而入时,会造成服务器忙不过来的局面,可以使用多个服务器来共同分担成千上万的用户请求,这些服务器提供相同的服务,对于用户来说,

  • 我需要代理请求从localhost到HTTPS后端。我使用doc的代码: 但它返回一个错误: 尝试将请求/env/api/my/url/从localhost:4200代理到时发生[HPM]错误https://my-domain (电子版)(https://nodejs.org/api/errors.html#errors_common_system_errors)

  • 部署在公网的服务面临着越来越多的流量劫持、运营商劫持事件,为了能更好的保障信息的安全性和完整性,HTTPS得到了越来越多的重视。基于此原因,本文章尝试从另一个视角,通过使用 Node.js 实现一个简单的 HTTPS 中间人代理的方式,阐述HTTPS是如何保证网络信息的安全,并且分析用户的何种行将会导致 HTTPS 的安全性失效。

  • 我已经阅读了一些网站上的一些线程,但仍然无法使这一工作。 如果有人能在这里提供一些指导,我将不胜感激!

  • 是否可以在 React Native 应用程序中使用 HTTPS Agent? 我现在的代码是: 但是显示以下错误: ExceptionsManager.js:76错误:InternalError Metro遇到错误:在尝试从文件解析模块时,成功找到包。但是,此包本身指定了无法解析的模块字段(。事实上,这些文件都不存在: /mobile/node_modules/https/index.js(.n