gpt4 book ai didi

c# - 透明代理 - 从端口 80 到 443

转载 作者:可可西里 更新时间:2023-11-01 16:43:40 25 4
gpt4 key购买 nike

我正在尝试开发一个透明的代理,它将来自客户端的不安全的 http 流量作为安全的 https 流量转发到服务器,然后再返回。为了更好地说明我的观点,请看下图。

Rich Picture

假设由于各种原因,客户端将仅使用 HTTP,他们不能将端口 443 用于 HTTPS。由于某些服务器不接受来自端口 80 的流量,我的代理需要将它们重新路由到端口 443。这是一种可能的情况:

  1. 从客户端接收前往 www.google.com 端口 80 的数据
  2. 初始化与https://www.google.com的连接到端口 443(进行握手等)
  3. 加密来自客户端的数据并将它们发送到https://www.google.com到端口 443。
  4. 收到来自 https://www.google.com 的回复,解密它们并将它们发送回客户端的 80 端口。

因为这是一个透明的代理,客户端(在我的例子中有很多)不需要任何额外的配置。网络已经配置好,因此他们的流量通过我的节点。目前,我的节点只是简单地重新路由数据并阻止一些包含病毒的数据。这是使用 WinPcap 完成的访问低网络层,但如果使用原始数据包太难完成(主要是握手),我愿意改变我的方法。

我尝试过的:注意:www.google.com 可以是网络上的任何站点。它仅用作示例。

  1. Iridium 的建议。这不起作用,因为 TcpListener 仅在另一个应用程序使用 TcpClient 连接到它时才接受新连接。由于这是透明代理,因此不起作用。
  2. 改用 HttpListener。但是,这似乎不起作用,因为它只接受到我自己的 IP(不是 www.google.com)的连接。
  3. 像以前一样使用 HttpListener,但这次我将数据包转发到我自己的 IP,以便 HttpListener 接受连接。出于某种原因,这似乎不起作用(通过 wireshark 检查和 TCP SYN 数据包不断重新发送,不知道为什么或如何修复它)。
  4. 使用 SslStream 连接到 https://www.google.com ,然后从客户端接收到的原始数据包中获取内容并将它们写入流中。这不起作用,因为 SslStream 自行处理 TCP 数据包(例如 ACK 或 SYN)。该流只需要 Http 请求。它不起作用的另一个原因是因为我无法从流中读取 TCP 数据包的内容,只能读取 HTTP 响应的内容(因此客户端坐在那里等待 ACK)。
  5. 将 TCP 数据包按原样从客户端转发到端口 443,从服务器转发到端口 80(因为只有 HTTP 请求和响应是用 SSL 加密的,所以不会有什么区别),并使用 HttpRequest 类使所有http 请求和响应(因为类自己处理握手)。这不起作用,因为双方的 ACK 都是错误的。

开发此类代理的最佳方法是什么?

编辑:TcpListener 或 HttpListener 是否可以作为透明代理? (无需在客户端计算机上进行配置)。 HttpListener 究竟在什么时候识别出客户端正在尝试连接?

最佳答案

我真的不明白为什么你需要从SslStream中读取加密数据。如果我没看错你的描述,你应该只需要:

  • 等待客户端连接
  • 当客户端连接时,连接到服务器
  • 将服务器连接的 NetworkStream 包装在 SslStreamAuthenticateAsClient
  • 一旦通过身份验证,并行:
    • 从客户端读取数据并写入SslStream
    • SslStream中读取数据并写入客户端

在此过程中,我没有看到您需要查看来自 SslStream 的加密数据的任何地方。

以下是一个非常基本的示例(虽然完全未经测试):

static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 11180);
var clientConnection = listener.AcceptTcpClient();
// When we get here, the client has connected, initiate the server connection
var serverConnection = new TcpClient("your.server.name", 443);
var serverStream = serverConnection.GetStream();
var secureStream = new SslStream(serverStream);
secureStream.AuthenticateAsClient("your.server.name");
ConnectStreams(clientConnection.GetStream(), secureStream);
}

private static void ConnectStreams(Stream streamA, Stream streamB)
{
ForwardStream(streamA, streamB, new byte[1024]);
ForwardStream(streamB, streamA, new byte[1024]);
}

private static void ForwardStream(Stream source, Stream destination, byte[] buffer)
{
source.BeginRead(buffer, 0, buffer.Length, r => Forward(source, destination, r, buffer), null);
}

private static void Forward(Stream source, Stream destination, IAsyncResult asyncResult, byte[] buffer)
{
var bytesRead = source.EndRead(asyncResult);
if (bytesRead == 0)
{
destination.Close();
return;
}
destination.Write(buffer, 0, bytesRead);
ForwardStream(source, destination, buffer);
}

关于c# - 透明代理 - 从端口 80 到 443,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16069987/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com