0x00 はじめに
HTTP プロキシは、さまざまな面で非常に幅広い用途に使用できます。 HTTP プロキシは、フォワード プロキシとリバース プロキシに分けられ、後者は通常、ユーザーにファイアウォールの背後にあるサービスへのアクセスを提供するため、または Nginx や HAProxy などの目的で使用されます。この記事では、フォワード プロキシについて説明します。
HTTP プロキシの最も一般的な用途は、ネットワーク共有、ネットワークの高速化、ネットワーク制限の突破などです。さらに、HTTP プロキシは、Web アプリケーションのデバッグ、Android/IOS APP で呼び出される Web API の監視、分析にも一般的に使用されており、現在、よく知られているソフトウェアには、Fiddler、Charles、Burp Suite、mitmproxy などがあります。 HTTP プロキシを使用すると、サーバーを変更せずにリクエスト/レスポンスのコンテンツを変更したり、Web アプリケーションに機能を追加したり、アプリケーションの動作を変更したりすることもできます。
0x01 HTTP プロキシとは
HTTP プロキシは本質的に Web アプリケーションであり、他の通常の Web アプリケーションと基本的には変わりません。 HTTPプロキシはリクエストを受信すると、ヘッダーのHostフィールドのホスト名とGet/POSTリクエストのアドレスから総合的に対象ホストを判断し、新たなHTTPリクエストを確立し、リクエストデータを転送し、受信したレスポンスデータを転送します。クライアントに。
リクエスト アドレスが絶対アドレスの場合、HTTP プロキシはアドレスのホストを使用します。それ以外の場合は、ヘッダーの HOST フィールドが使用されます。ネットワーク環境が次のとおりであると仮定して、簡単なテストを実行します。
192.168.1.2 Web服务器 192.168.1.3 HTTP代理服务器
Telnet を使用してテストします
$ telnet 192.168.1.3 GET / HTTP/1.0 HOST: 192.168.1.2
最後に 2 つの連続したキャリッジ リターンが必要であることに注意してください。これは HTTP プロトコルの要件です。 。完了すると、http://www.php.cn/ のページコンテンツを受信できるようになります。 GET リクエストを行うときに絶対アドレスを使用してみましょう
$ telnet 192.168.1.3 GET http://www.php.cn/ HTTP/1.0 HOST: 192.168.1.2
HOST も 192.168.1.2 に設定されていますが、実行結果は http://www.php.cn のコンテンツを返すことに注意してください。 / ページ、つまりパブリック IP アドレス情報です。
上記のテストプロセスからわかるように、元のリクエストがプロキシサーバーに送信される限り、HTTP プロキシはそれほど複雑なものではありません。少数のホストが HTTP プロキシを必要とするシナリオで HTTP プロキシを設定できない場合、最も簡単な方法は、ターゲット ホスト ドメイン名の IP をプロキシ サーバーにポイントすることです。これは、hosts ファイルを変更することで実現できます。 。
0x02 PythonプログラムでHTTPプロキシを設定する
urllib2/urllibプロキシ設定
urllib2
は非常に強力な機能を備えたPythonの標準ライブラリですが、使い方が少し面倒です。 Python 3 では、urllib2 は保持されなくなり、urllib モジュールに移動されました。 urllib2 では、ProxyHandler を使用してプロキシ サーバーを設定します。
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())
また、install_opener を使用して、構成済みのオープナーをグローバル環境にインストールし、すべての urllib2.urlopen が自動的にプロキシを使用するようにすることもできます。
urllib2.install_opener(opener) r = urllib2.urlopen('http://httpbin.org/ip') print(r.read())
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())
リクエストのプロキシ設定
requests は現在最高の HTTP ライブラリの 1 つであり、http リクエストを構築するときに私が最もよく使用するライブラリでもあります。その API 設計は非常にユーザーフレンドリーで使いやすいです。リクエストのプロキシの設定は非常に簡単です。プロキシのパラメータを {'http': 'x.x.x.x:8080', 'https': 'x.x.x.x:8080'} の形式で設定するだけです。このうち http と https は互いに独立しています。
In [5]: requests.get('http://httpbin.org/ip', proxies={'http': '121.193.143.249:80'}).json() Out[5]: {'origin': '121.193.143.249'}
セッションのプロキシ属性を直接設定できるため、リクエストごとにプロキシ パラメータを持ち込む手間が省けます。
s = requests.session() s.proxies = {'http': '121.193.143.249:80'} print(s.get('http://httpbin.org/ip').json())
0x03 HTTP_PROXY / HTTPS_PROXY 環境変数
urllib2 ライブラリと Requests ライブラリの両方が HTTP_PROXY および HTTPS_PROXY 環境変数を認識すると、プロキシが使用するように自動的に設定されます。これは、コードを変更せずに環境変数に従ってプロキシ サーバーの IP アドレスとポートを調整できるため、HTTP プロキシを使用してデバッグする場合に非常に便利です。 *nix のほとんどのソフトウェアは、curl、wget、axel、aria2c などの HTTP_PROXY 環境変数認識もサポートしています。
$ 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" }
IPython インタラクティブ環境では、HTTP リクエストを一時的にデバッグする必要がある場合があります。os.environ['http_proxy'] を設定するだけで HTTP プロキシを追加/キャンセルできます。
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 は Man-in-the-Middle Attack に由来しており、一般的にネットワーク内のデータを傍受、監視、改ざんする中間者攻撃を指します。クライアントとサーバーの間。
mitmproxy は、Python 言語で開発されたオープンソースの中間者プロキシ アーティファクトで、SSL、透過プロキシ、リバース プロキシ、トラフィックの記録と再生、カスタム スクリプトなどをサポートします。この機能は Windows の Fiddler に似ていますが、mitmproxy は GUI インターフェイスを持たないコンソール プログラムですが、非常に便利に使用できます。 mitmproxy を使用すると、プロキシ HTTP 要求/応答パケットを簡単にフィルタリング、インターセプト、および変更できます。また、そのスクリプト API を使用して、HTTP データを自動的にインターセプトおよび変更するスクリプトを作成することもできます。
りー上面的脚本会在所有经过代理的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,用于给公司内部网站增加功能、改善用户体验,以后有机会再和大家分享。
更多Python程序中设置HTTP代理相关文章请关注PHP中文网!