0x00 Vorwort
Jeder sollte mit dem HTTP-Proxy vertraut sein, der in vielerlei Hinsicht weit verbreitet ist. HTTP-Proxys werden in Forward-Proxys und Reverse-Proxys unterteilt. Letztere werden im Allgemeinen verwendet, um Benutzern Zugriff auf Dienste hinter der Firewall zu gewähren. Typische Proxys sind Nginx, HAProxy usw. In diesem Artikel werden Forward-Proxys behandelt.
Die häufigsten Verwendungszwecke von HTTP-Proxys sind die gemeinsame Nutzung von Netzwerken, die Netzwerkbeschleunigung und das Durchbrechen von Netzwerkgrenzen usw. Darüber hinaus werden HTTP-Proxys auch häufig zum Debuggen von Webanwendungen, zur Überwachung und Analyse von Web-APIs verwendet, die in Android/IOS-APPs aufgerufen werden. Zu den bekannten Softwareprogrammen gehören derzeit Fiddler, Charles, Burp Suite und mitmproxy. HTTP-Proxy kann auch verwendet werden, um Anforderungs-/Antwortinhalte zu ändern, zusätzliche Funktionen zu Webanwendungen hinzuzufügen oder das Anwendungsverhalten zu ändern, ohne den Server zu ändern.
0x01 Was ist HTTP-Proxy?
HTTP-Proxy ist im Wesentlichen eine Webanwendung und unterscheidet sich nicht grundlegend von anderen gewöhnlichen Webanwendungen. Nach Erhalt der Anfrage ermittelt der HTTP-Proxy umfassend den Zielhost anhand des Hostnamens im Host-Feld im Header und der Get/POST-Anfrageadresse, erstellt eine neue HTTP-Anfrage, leitet die Anfragedaten weiter und leitet die empfangenen Antwortdaten weiter an den Kunden.
Wenn die Anfrageadresse eine absolute Adresse ist, verwendet der HTTP-Proxy den Host in der Adresse, andernfalls wird das HOST-Feld im Header verwendet. Führen Sie einen einfachen Test durch, vorausgesetzt, die Netzwerkumgebung ist wie folgt:
192.168.1.2 Webserver
192.168.1.3 HTTP-Proxyserver
Verwenden Sie Telnet zum Testen
$ telnet 192.168.1.3 GET / HTTP/1.0 HOST: 192.168.1.2
Beachten Sie, dass am Ende zwei aufeinanderfolgende Wagenrückläufe erforderlich sind, was eine Anforderung des HTTP-Protokolls ist. Nach Abschluss können Sie den Seiteninhalt von http://192.168.1.2/ erhalten. Nehmen wir einige Anpassungen vor:
$ telnet 192.168.1.3 GET http://httpbin.org/ip HTTP/1.0 HOST: 192.168.1.2
Beachten Sie, dass der HOST ebenfalls auf 192.168.1.2 eingestellt ist, das laufende Ergebnis jedoch http:/ zurückgibt. /httpbin. Der Inhalt der org/ip-Seite sind die öffentlichen IP-Adressinformationen.
Wie aus dem obigen Testprozess ersichtlich ist, ist der HTTP-Proxy keine sehr komplizierte Sache, solange die ursprüngliche Anfrage an den Proxyserver gesendet wird. Wenn in einem Szenario, in dem eine kleine Anzahl von Hosts einen HTTP-Proxy benötigt, kein HTTP-Proxy festgelegt werden kann, besteht die einfachste Möglichkeit darin, die IP des Zielhostdomänennamens auf den Proxyserver zu verweisen, was durch Ändern der Hosts-Datei erreicht werden kann .
0x02 HTTP-Proxy im Python-Programm festlegen
urllib2/urllib-Proxy-Einstellung
urllib2 ist eine Python-Standardbibliothek mit sehr leistungsstarken Funktionen, die jedoch etwas umständlicher ist verwenden. In Python 3 wird urllib2 nicht mehr beibehalten und in das Modul urllib verschoben. In urllib2 wird ProxyHandler zum Einrichten des Proxyservers verwendet.
proxy_handler = urllib2.ProxyHandler({'http': '121.193.143.249:80'}) opener = urllib2.build_opener(proxy_handler) r = opener.open('http://httpbin.org/ip') print(r.read())
Sie können install_opener auch verwenden, um den konfigurierten Opener in der globalen Umgebung zu installieren, sodass alle urllib2.urlopen automatisch ausgeführt werden Proxy verwenden
urllib2.install_opener(opener) r = urllib2.urlopen('http://httpbin.org/ip') print(r.read())
Verwenden Sie in Python 3 urllib.
proxy_handler = urllib.request.ProxyHandler({'http': 'http://121.193.143.249:80/'}) opener = urllib.request.build_opener(proxy_handler) r = opener.open('http://httpbin.org/ip') print(r.read())
Proxy-Einstellungen für Anfragen
Requests ist derzeit eine der besten HTTP-Bibliotheken und auch die Bibliothek, die ich beim Erstellen von HTTP-Anfragen am häufigsten verwende. Das API-Design ist sehr benutzerfreundlich und einfach zu verwenden. Das Einrichten eines Proxys für Anfragen ist sehr einfach. Sie müssen lediglich einen Parameter in der Form {'http': 'x.x.x.x:8080', 'https': 'x.x.x.x:8080'} festlegen. Unter diesen sind http und https unabhängig voneinander.
In [5]: requests.get('http://httpbin.org/ip', proxies={'http': '121.193.143.249:80'}).json() Out[5]: {'origin': '121.193.143.249'}
Sie können das Proxy-Attribut der Sitzung direkt festlegen, sodass Sie nicht mehr bei jeder Anfrage Proxy-Parameter angeben müssen.
s = requests.session() s.proxies = {'http': '121.193.143.249:80'} print(s.get('http://httpbin.org/ip').json())
0x03 HTTP_PROXY / HTTPS_PROXY-Umgebungsvariablen
Sowohl die urllib2- als auch die Requests-Bibliothek erkennen die Umgebungsvariablen HTTP_PROXY und HTTPS_PROXY und richten den Proxy automatisch ein und verwenden ihn, sobald diese Umgebungsvariablen erkannt werden . Dies ist beim Debuggen mit HTTP-Proxy sehr nützlich, da Sie die IP-Adresse und den Port des Proxyservers entsprechend den Umgebungsvariablen anpassen können, ohne den Code zu ändern. Die meiste Software in *nix unterstützt auch die Erkennung von HTTP_PROXY-Umgebungsvariablen wie Curl, Wget, Axel, Aria2c usw.
$ http_proxy=121.193.143.249:80 python -c 'import requests; print(requests.get("http://httpbin.org/ip").json())' {u'origin': u'121.193.143.249'} $ http_proxy=121.193.143.249:80 curl httpbin.org/ip { "origin": "121.193.143.249" }
In der interaktiven IPython-Umgebung müssen Sie möglicherweise häufig vorübergehend HTTP-Anfragen debuggen. Sie können den HTTP-Proxy einfach hinzufügen/abbrechen, indem Sie os.environ['http_proxy'] festlegen. .
In [245]: os.environ['http_proxy'] = '121.193.143.249:80' In [246]: requests.get("http://httpbin.org/ip").json() Out[246]: {u'origin': u'121.193.143.249'} In [249]: os.environ['http_proxy'] = '' In [250]: requests.get("http://httpbin.org/ip").json() Out[250]: {u'origin': u'x.x.x.x'}
0x04 MITM-Proxy
MITM stammt von Man-in-the-Middle Attack, was sich auf einen Man-In bezieht -the-middle-Angriff, normalerweise auf den Client, um Daten im Netzwerk zwischen Client und Server abzufangen, zu überwachen und zu manipulieren.
mitmproxy ist ein Open-Source-Man-in-the-Middle-Proxy-Artefakt, das in der Python-Sprache entwickelt wurde. Es unterstützt SSL, transparenten Proxy, Reverse-Proxy, Verkehrsaufzeichnung und -wiedergabe sowie benutzerdefinierte Skripte. Die Funktion ähnelt in gewisser Weise Fiddler in Windows, allerdings ist mitmproxy ein Konsolenprogramm ohne GUI-Schnittstelle, das aber recht komfortabel zu bedienen ist. Mit mitmproxy können Sie problemlos alle Proxy-HTTP-Anfrage-/Antwortpakete filtern, abfangen und ändern. Sie können sogar die Skript-API verwenden, um Skripte zu schreiben, um HTTP-Daten automatisch abzufangen und zu ändern.
# test.py def response(flow): flow.response.headers["BOOM"] = "boom!boom!boom!"
上面的脚本会在所有经过代理的Http响应包头里面加上一个名为BOOM的header。用mitmproxy -s 'test.py'命令启动mitmproxy,curl验证结果发现的确多了一个BOOM头。
$ http_proxy=localhost:8080 curl -I 'httpbin.org/get' HTTP/1.1 200 OK Server: nginx Date: Thu, 03 Nov 2016 09:02:04 GMT Content-Type: application/json Content-Length: 186 Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true BOOM: boom!boom!boom! ...
显然mitmproxy脚本能做的事情远不止这些,结合Python强大的功能,可以衍生出很多应用途径。除此之外,mitmproxy还提供了强大的API,在这些API的基础上,完全可以自己定制一个实现了特殊功能的专属代理服务器。
经过性能测试,发现mitmproxy的效率并不是特别高。如果只是用于调试目的那还好,但如果要用到生产环境,有大量并发请求通过代理的时候,性能还是稍微差点。我用twisted实现了一个简单的proxy,用于给公司内部网站增加功能、改善用户体验,以后有机会再和大家分享。