Comment créer un proxy simple en C #?

J’ai téléchargé Privoxy il y a quelques semaines et pour le plaisir, j’étais curieux de savoir comment une version simple pouvait être réalisée.

Je comprends que je dois configurer le navigateur (client) pour envoyer la demande au proxy. Le proxy envoie la demande au Web (disons que c’est un proxy http). Le proxy recevra la réponse … mais comment le proxy peut-il renvoyer la demande au navigateur (client)?

J’ai cherché sur le Web pour C # et http proxy, mais je n’ai pas trouvé quelque chose qui me laisse comprendre comment cela fonctionne correctement derrière la scène. (Je crois que je ne veux pas un proxy inverse mais je ne suis pas sûr).

Est-ce que l’un d’entre vous a des explications ou des informations qui me permettront de poursuivre ce petit projet?

Mettre à jour

C’est ce que je comprends (voir graphique ci-dessous).

Étape 1 Je configure le client (navigateur) pour toutes les demandes à envoyer à 127.0.0.1 sur le port que le proxy écoute. De cette façon, la demande ne sera pas envoyée directement à Internet mais sera traitée par le proxy.

Etape 2 Le proxy voit une nouvelle connexion, lit l’en-tête HTTP et voit la requête qu’il doit exécuter. Il exécute la demande.

Step3 Le proxy reçoit une réponse de la demande. Maintenant, il doit envoyer la réponse du Web au client mais comment ???

texte alt

Lien utile

Mentalis Proxy : J’ai trouvé ce projet qui est un proxy (mais plus que je voudrais). Je pourrais vérifier la source mais je voulais vraiment quelque chose de fondamental pour mieux comprendre le concept.

ASP Proxy : Je pourrais peut-être obtenir des informations ici aussi.

Réflecteur de demande : Ceci est un exemple simple.

Voici un repository Git Hub avec un simple proxy HTTP .

Vous pouvez en créer un avec la classe HttpListener pour écouter les requêtes entrantes et la classe HttpWebRequest pour relayer les requêtes.

Je n’utiliserais pas HttpListener ou quelque chose comme ça, vous rencontreriez de nombreux problèmes.

Plus important encore, ce sera une énorme peine à supporter:

  • Proxy Keep-Alives
  • SSL ne fonctionnera pas (de manière correcte, vous obtiendrez des popups)
  • Les bibliothèques .NET suivent ssortingctement les RFC, ce qui entraîne l’échec de certaines requêtes (même si IE, FF et tout autre navigateur du monde fonctionnent).

Ce que vous devez faire est:

  • Écouter un port TCP
  • Analyser la requête du navigateur
  • Extract Host se connecte à cet hôte au niveau TCP
  • Transférer tout en arrière sauf si vous souhaitez append des en-têtes personnalisés, etc.

J’ai écrit 2 proxies HTTP différents dans .NET avec différentes exigences et je peux vous dire que c’est la meilleure façon de le faire.

Mentalis fait ça, mais leur code est “délégué spaghetti”, pire que GoTo 🙂

Le proxy peut fonctionner de la manière suivante.

Etape 1, configurez le client pour qu’il utilise proxyHost: proxyPort.

Proxy est un serveur TCP qui écoute sur proxyHost: proxyPort. Le navigateur ouvre la connexion avec le proxy et envoie la requête HTTP. Le proxy parsing cette requête et tente de détecter l’en-tête “Host”. Cet en-tête indiquera au proxy où ouvrir la connexion.

Étape 2: Le proxy ouvre la connexion à l’adresse spécifiée dans l’en-tête “Host”. Ensuite, il envoie une requête HTTP à ce serveur distant. Lit la réponse.

Étape 3: après la lecture de la réponse du serveur HTTP distant, le proxy envoie la réponse via une connexion TCP ouverte antérieure avec le navigateur.

Schématiquement, cela ressemblera à ceci:

 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 

J’ai récemment écrit un proxy léger dans c # .net en utilisant TcpListener et TcpClient .

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

Il prend en charge le protocole HTTP sécurisé de la bonne manière, la machine client doit faire confiance au certificate racine utilisé par le proxy. Prend également en charge le relais WebSockets. Toutes les fonctionnalités de HTTP 1.1 sont sockets en charge, à l’exception du traitement en pipeline. Le pipelining n’est pas utilisé par la plupart des navigateurs modernes. Prend également en charge l’authentification Windows (simple, digérer).

Vous pouvez connecter votre application en référençant le projet, puis voir et modifier tout le trafic. (Demande et réponse).

En ce qui concerne la performance, je l’ai testé sur ma machine et fonctionne sans délai notable.

Si vous cherchez juste à intercepter le trafic, vous pouvez utiliser le kernel de violoniste pour créer un proxy …

http://fiddler.wikidot.com/fiddlercore

lancez d’abord le fiddler avec l’interface utilisateur pour voir ce qu’il fait, c’est un proxy qui vous permet de déboguer le trafic http / https. Il est écrit en c # et possède un kernel que vous pouvez intégrer dans vos propres applications.

Gardez à l’esprit que FiddlerCore n’est pas gratuit pour les applications commerciales.

Les choses sont devenues vraiment faciles avec OWIN et WebAPI. Dans ma recherche d’un serveur proxy C #, je suis également tombé sur ce post http://blog.kloud.com.au/2013/11/24/do-it-yourself-web-api-proxy/ . Ce sera la route que je prend.

D’accord pour dr evil si vous utilisez HTTPListener vous aurez beaucoup de problèmes, vous devrez parsingr les requêtes et vous serez engagé dans les en-têtes et …

  1. Utiliser l’écouteur TCP pour écouter les requêtes du navigateur
  2. parsingr uniquement la première ligne de la requête et obtenir que le domaine hôte et le port se connectent
  3. envoyer la demande brute exacte à l’hôte trouvé sur la première ligne de la requête du navigateur
  4. recevoir les données du site cible (j’ai un problème dans cette section)
  5. envoyer les données exactes reçues de l’hôte au navigateur

vous voyez que vous n’avez même pas besoin de savoir ce que contient la requête du navigateur et de l’parsingr, seulement obtenir l’adresse du site cible à partir de la première ligne, la première ligne aime généralement http://google.com HTTP1.1 ou CONNECT facebook.com: 443 (c’est pour les requêtes ssl)

Socks4 est un protocole très simple à mettre en œuvre. Vous écoutez la connexion initiale, connectez-vous à l’hôte / au port demandé par le client, envoyez le code de réussite au client, puis transférez les stream sortants et entrants entre les sockets.

Si vous allez avec HTTP, vous devrez lire et peut-être définir / supprimer certains en-têtes HTTP, donc c’est un peu plus de travail.

Si je me souviens bien, SSL fonctionnera sur les proxies HTTP et Socks. Pour un proxy HTTP, vous implémentez le verbe CONNECT, qui fonctionne comme les socks4, comme décrit ci-dessus, puis le client ouvre la connexion SSL sur le stream TCP configuré.

Le navigateur est connecté au proxy afin que les données que le proxy reçoit du serveur Web soient simplement envoyées via la même connexion que celle lancée par le navigateur vers le proxy.

J’ai également écrit un proxy inverse simple mais puissant pour asp.net / web api.

Vous pouvez le trouver ici: https://github.com/SharpTools/SharpReverseProxy

Il suffit d’append à votre projet via nuget et vous êtes prêt à partir. Vous pouvez même modifier à la volée la demande, la réponse ou refuser un transfert en raison d’un échec d’authentification.

Jetez un oeil sur le code source, c’est très facile à mettre en œuvre 🙂