Как создать простой прокси на C#?

Я загрузил Privoxy несколько недель назад, и 9X_dot-net ради забавы мне было любопытно узнать, как 9X_.cs-file можно сделать простую его версию.

Я понимаю, что 9X_dotnet мне нужно настроить браузер (клиент) для 9X_c# отправки запроса на прокси. Прокси-сервер 9X_c-sharp отправляет запрос в Интернет (допустим, это 9X_c# http-прокси). Прокси-сервер получит ответ 9X_c#-language ... но как он может отправить запрос браузеру 9X_c#-language (клиенту)?

Я искал в Интернете C# и http-прокси, но 9X_dot-net не нашел ничего, что позволило бы мне понять, как 9X_csharp это правильно работает за сценой. (Я считаю, что 9X_dotnet мне не нужен обратный прокси, но я не уверен).

У 9X_c#.net кого-нибудь из вас есть пояснения или информация, которые 9X_.net-framework позволят мне продолжить этот небольшой проект?

Обновить

Это 9X_csharp то, что я понимаю (см. рисунок ниже).

Шаг 1. Я 9X_.net-framework настраиваю клиент (браузер) для отправки 9X_c#.net всех запросов на 127.0.0.1 на порт, который 9X_c# прослушивает прокси. Таким образом, запрос 9X_c#-language не будет отправлен в Интернет напрямую, а 9X_.net будет обработан прокси-сервером.

Шаг 2. Прокси-сервер 9X_c-sharp видит новое соединение, читает заголовок 9X_.net HTTP и видит запрос, который он должен выполнить. Он 9X_.cs-file выполняет запрос.

Шаг 3. Прокси-сервер получает 9X_.net ответ на запрос. Теперь он должен отправить 9X_c-sharp ответ клиенту из Интернета, но как ???

9X_Как создать простой прокси на C#?_.cs-file

Полезная ссылка

Mentalis Proxy: Я 9X_csharp нашел этот проект, который является прокси 9X_dotnet (но мне бы хотелось большего). Я мог бы 9X_.net-framework проверить источник, но мне действительно 9X_.net нужно что-то базовое, чтобы лучше понять 9X_csharp концепцию.

ASP Proxy: Я тоже могу получить здесь некоторую 9X_.cs-file информацию.

Request reflector: это простой пример.

Вот Git Hub Repository with a Simple Http Proxy.

150
0
10
Общее количество ответов: 10

Ответ #1

Ответ на вопрос: Как создать простой прокси на C#?

Я бы не стал использовать HttpListener или 9X_visual-c# что-то в этом роде, так вы столкнетесь с 9X_c#-language множеством проблем.

Что еще важнее, поддержка 9X_dotnet будет огромной болью:

  • Прокси Keep-Alives
  • SSL не будет работать (при правильном использовании будут всплывающие окна)
  • Библиотеки .NET строго следуют RFC, что приводит к сбою некоторых запросов (даже если IE, FF и любой другой браузер в мире будут работать.)

Что вам нужно сделать, это:

  • Прослушивание TCP-порта.
  • Разобрать запрос браузера.
  • Извлечь хост, подключенный к этому хосту на уровне TCP
  • Пересылайте все вперед и назад, если вы не хотите добавлять собственные заголовки и т. д.

Я 9X_proxy написал 2 разных HTTP-прокси в .NET с разными 9X_.cs-file требованиями и могу сказать вам, что это 9X_dotnet лучший способ сделать это.

Mentalis делает 9X_visual-c# это, но их код - "спагетти делегата", хуже, чем 9X_csharp GoTo :)

95
5

  • Не могли бы вы поделиться своим опытом, п ...

Ответ #2

Ответ на вопрос: Как создать простой прокси на C#?

Недавно я написал облегченный прокси на 9X_c#.net C# .net, используя TcpListener и TcpClient.

https://github.com/titanium007/Titanium-Web-Proxy

Он правильно поддерживает 9X_visual-c# безопасный HTTP, клиентский компьютер должен 9X_csharp доверять корневому сертификату, используемому 9X_dotnet прокси. Также поддерживает ретрансляцию 9X_dotnet WebSockets. Поддерживаются все функции HTTP 9X_c#.net 1.1, кроме конвейерной обработки. В любом 9X_c#-language случае конвейерная обработка не используется 9X_c#.net большинством современных браузеров. Также 9X_.net поддерживает проверку подлинности Windows 9X_.net (обычная, дайджест).

Вы можете подключить 9X_proxy свое приложение, обратившись к проекту, а 9X_visual-c# затем просмотреть и изменить весь трафик. (Запрос 9X_proxy и ответ).

Что касается производительности, я 9X_c#-language протестировал его на своей машине и работает 9X_.net-framework без каких-либо заметных задержек.

37
0

Ответ #3

Ответ на вопрос: Как создать простой прокси на C#?

Вы можете создать его с помощью класса HttpListener для 9X_dotnet прослушивания входящих запросов и класса 9X_dotnet HttpWebRequest для ретрансляции запросов.

36
3

  • Если вы используете HttpListener, вы просто пишете ответ HttpListener.GetContext(). ...

Ответ #4

Ответ на вопрос: Как создать простой прокси на C#?

Прокси может работать следующим образом.

Шаг 9X_dotnet 1. Настройте клиент для использования proxyHost: proxyPort.

Прокси-сервер 9X_csharp - это TCP-сервер, который прослушивает proxyHost: proxyPort. Браузер 9X_c# открывает соединение с прокси и отправляет 9X_dotnet Http-запрос. Прокси-сервер анализирует этот 9X_dotnet запрос и пытается обнаружить заголовок «Хост». Этот 9X_.cs-file заголовок сообщит прокси, где открыть соединение.

Шаг 9X_.net 2. Прокси-сервер открывает соединение с 9X_csharp адресом, указанным в заголовке «Хост». Затем 9X_c-sharp он отправляет HTTP-запрос на этот удаленный 9X_dotnet сервер. Читает ответ.

Шаг 3. После считывания 9X_.net ответа с удаленного HTTP-сервера прокси-сервер 9X_.net-framework отправляет ответ через ранее открытое TCP-соединение 9X_c-sharp с браузером.

Схематично это будет выглядеть 9X_.net так:

Browser Proxy HTTP server Open TCP connection Send HTTP request -----------> Read HTTP header detect Host header Send request to HTTP -----------> Server <----------- Read response and send <----------- it back to the browser Render content 

20
0

Ответ #5

Ответ на вопрос: Как создать простой прокси на C#?

Если вы просто хотите перехватить трафик, вы 9X_csharp можете использовать ядро ​​Fiddler для создания 9X_.net-2.0 прокси ...

http://fiddler.wikidot.com/fiddlercore

сначала запустите fiddler с пользовательским 9X_dotnet интерфейсом, чтобы увидеть, что он делает, это 9X_.cs-file прокси, который позволяет вам отлаживать 9X_visual-c# трафик http / https. Он написан на C# и 9X_c#-language имеет ядро, которое вы можете встроить в 9X_.net-framework свои собственные приложения.

Имейте в виду, что 9X_proxy FiddlerCore не бесплатен для коммерческих 9X_c# приложений.

14
0

Ответ #6

Ответ на вопрос: Как создать простой прокси на C#?

Согласен с доктором злом если вы используете 9X_c#-language HTTPListener, у вас будет много проблем, вам 9X_csharp придется разбирать запросы и заниматься 9X_proxy заголовками и ...

  1. Используйте прослушиватель TCP для прослушивания запросов браузера
  2. проанализировать только первую строку запроса и получить домен хоста и порт для подключения.
  3. отправить точный необработанный запрос на найденный хост в первой строке запроса браузера.
  4. получать данные с целевого сайта (у меня проблема в этом разделе)
  5. отправлять точные данные, полученные от хоста, в браузер.

вы видите, что вам не нужно 9X_csharp даже знать, что находится в запросе браузера, и 9X_.net анализировать его, только получите адрес 9X_c#-language целевого сайта из первой строки первая строка 9X_.net-2.0 обычно любит это ПОЛУЧИТЬ http://google.com HTTP1.1 или ПОДКЛЮЧИТЕ 9X_.net facebook.com:443 (это для ssl-запросов)

6
0

Ответ #7

Ответ на вопрос: Как создать простой прокси на C#?

С OWIN и WebAPI все стало очень просто. В 9X_c#.net поисках прокси-сервера C# я также наткнулся 9X_csharp на этот пост http://blog.kloud.com.au/2013/11/24/do-it-yourself-web-api-proxy/. Я пойду по этой дороге.

6
0

Ответ #8

Ответ на вопрос: Как создать простой прокси на C#?

Socks4 - очень простой в реализации протокол. Вы 9X_.net-2.0 слушаете начальное соединение, подключаетесь 9X_c-sharp к хосту / порту, который был запрошен клиентом, отправляете 9X_.cs-file код успеха клиенту, а затем перенаправляете 9X_c# исходящие и входящие потоки через сокеты.

Если 9X_c-sharp вы используете HTTP, вам придется прочитать 9X_c#.net и, возможно, установить / удалить некоторые 9X_.net-2.0 заголовки HTTP, так что это немного больше 9X_c#.net работы.

Если я правильно помню, SSL будет 9X_.net работать через прокси HTTP и Socks. Для 9X_.net-2.0 прокси-сервера HTTP вы реализуете команду 9X_c#-language CONNECT, которая работает так же, как socks4, как 9X_c-sharp описано выше, затем клиент открывает SSL-соединение 9X_.net-framework через прокси-поток tcp.

5
0

Ответ #9

Ответ на вопрос: Как создать простой прокси на C#?

Вот пример асинхронной реализации C# на 9X_.net-framework основе HttpListener и HttpClient (я использую его, чтобы иметь 9X_dot-net возможность подключать Chrome на устройствах 9X_c-sharp Android к IIS Express, это единственный 9X_.net способ, который я нашел ... ).

И если вам 9X_.net-2.0 нужна поддержка HTTPS, для этого не потребуется 9X_dotnet больше кода, просто конфигурация сертификата: Httplistener with HTTPS support

// define http://localhost:5000 and http://127.0.0.1:5000/ to be proxies for http://localhost:53068 using (var server = new ProxyServer("http://localhost:53068", "http://localhost:5000/", "http://127.0.0.1:5000/")) { server.Start(); Console.WriteLine("Press ESC to stop server."); while (true) { var key = Console.ReadKey(true); if (key.Key == ConsoleKey.Escape) break; } server.Stop(); } .... public class ProxyServer : IDisposable { private readonly HttpListener _listener; private readonly int _targetPort; private readonly string _targetHost; private static readonly HttpClient _client = new HttpClient(); public ProxyServer(string targetUrl, params string[] prefixes) : this(new Uri(targetUrl), prefixes) { } public ProxyServer(Uri targetUrl, params string[] prefixes) { if (targetUrl == null) throw new ArgumentNullException(nameof(targetUrl)); if (prefixes == null) throw new ArgumentNullException(nameof(prefixes)); if (prefixes.Length == 0) throw new ArgumentException(null, nameof(prefixes)); RewriteTargetInText = true; RewriteHost = true; RewriteReferer = true; TargetUrl = targetUrl; _targetHost = targetUrl.Host; _targetPort = targetUrl.Port; Prefixes = prefixes; _listener = new HttpListener(); foreach (var prefix in prefixes) { _listener.Prefixes.Add(prefix); } } public Uri TargetUrl { get; } public string[] Prefixes { get; } public bool RewriteTargetInText { get; set; } public bool RewriteHost { get; set; } public bool RewriteReferer { get; set; } // this can have performance impact... public void Start() { _listener.Start(); _listener.BeginGetContext(ProcessRequest, null); } private async void ProcessRequest(IAsyncResult result) { if (!_listener.IsListening) return; var ctx = _listener.EndGetContext(result); _listener.BeginGetContext(ProcessRequest, null); await ProcessRequest(ctx).ConfigureAwait(false); } protected virtual async Task ProcessRequest(HttpListenerContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); var url = TargetUrl.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped); using (var msg = new HttpRequestMessage(new HttpMethod(context.Request.HttpMethod), url + context.Request.RawUrl)) { msg.Version = context.Request.ProtocolVersion; if (context.Request.HasEntityBody) { msg.Content = new StreamContent(context.Request.InputStream); // disposed with msg } string host = null; foreach (string headerName in context.Request.Headers) { var headerValue = context.Request.Headers[headerName]; if (headerName == "Content-Length" && headerValue == "0") // useless plus don't send if we have no entity body continue; bool contentHeader = false; switch (headerName) { // some headers go to content... case "Allow": case "Content-Disposition": case "Content-Encoding": case "Content-Language": case "Content-Length": case "Content-Location": case "Content-MD5": case "Content-Range": case "Content-Type": case "Expires": case "Last-Modified": contentHeader = true; break; case "Referer": if (RewriteReferer && Uri.TryCreate(headerValue, UriKind.Absolute, out var referer)) // if relative, don't handle { var builder = new UriBuilder(referer); builder.Host = TargetUrl.Host; builder.Port = TargetUrl.Port; headerValue = builder.ToString(); } break; case "Host": host = headerValue; if (RewriteHost) { headerValue = TargetUrl.Host + ":" + TargetUrl.Port; } break; } if (contentHeader) { msg.Content.Headers.Add(headerName, headerValue); } else { msg.Headers.Add(headerName, headerValue); } } using (var response = await _client.SendAsync(msg).ConfigureAwait(false)) { using (var os = context.Response.OutputStream) { context.Response.ProtocolVersion = response.Version; context.Response.StatusCode = (int)response.StatusCode; context.Response.StatusDescription = response.ReasonPhrase; foreach (var header in response.Headers) { context.Response.Headers.Add(header.Key, string.Join(", ", header.Value)); } foreach (var header in response.Content.Headers) { if (header.Key == "Content-Length") // this will be set automatically at dispose time continue; context.Response.Headers.Add(header.Key, string.Join(", ", header.Value)); } var ct = context.Response.ContentType; if (RewriteTargetInText && host != null && ct != null && (ct.IndexOf("text/html", StringComparison.OrdinalIgnoreCase) >= 0 || ct.IndexOf("application/json", StringComparison.OrdinalIgnoreCase) >= 0)) { using (var ms = new MemoryStream()) { using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { await stream.CopyToAsync(ms).ConfigureAwait(false); var enc = context.Response.ContentEncoding ?? Encoding.UTF8; var html = enc.GetString(ms.ToArray()); if (TryReplace(html, "//" + _targetHost + ":" + _targetPort + "/", "//" + host + "/", out var replaced)) { var bytes = enc.GetBytes(replaced); using (var ms2 = new MemoryStream(bytes)) { ms2.Position = 0; await ms2.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false); } } else { ms.Position = 0; await ms.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false); } } } } else { using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { await stream.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false); } } } } } } public void Stop() => _listener.Stop(); public override string ToString() => string.Join(", ", Prefixes) + " => " + TargetUrl; public void Dispose() => ((IDisposable)_listener)?.Dispose(); // out-of-the-box replace doesn't tell if something *was* replaced or not private static bool TryReplace(string input, string oldValue, string newValue, out string result) { if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(oldValue)) { result = input; return false; } var oldLen = oldValue.Length; var sb = new StringBuilder(input.Length); bool changed = false; var offset = 0; for (int i = 0; i < input.Length; i++) { var c = input[i]; if (offset > 0) { if (c == oldValue[offset]) { offset++; if (oldLen == offset) { changed = true; sb.Append(newValue); offset = 0; } continue; } for (int j = 0; j < offset; j++) { sb.Append(input[i - offset + j]); } sb.Append(c); offset = 0; } else { if (c == oldValue[0]) { if (oldLen == 1) { changed = true; sb.Append(newValue); } else { offset = 1; } continue; } sb.Append(c); } } if (changed) { result = sb.ToString(); return true; } result = input; return false; } } 

4
1

  • Очень простой! Хороший человек!<p><span cla ...

Ответ #10

Ответ на вопрос: Как создать простой прокси на C#?

Браузер подключен к прокси, поэтому данные, которые 9X_dot-net прокси получает от веб-сервера, просто отправляются 9X_c#.net через то же соединение, которое браузер 9X_.cs-file инициировал для прокси.

2
0