PythonのHTTPエージェントを遊ぶ

5668 ワード

0 x 00はじめに
HTTPエージェントはよく知られているはずですが、多くの面で広く応用されています.HTTPエージェントには順方向エージェントと逆方向エージェントの2種類があり,後者は一般的にファイアウォールの後ろのサービスをユーザに提供したり負荷の均衡をとるために用いられ,典型的にはNginx,HAProxyなどがある.本論文では,順方向エージェントについて論じる.
HTTPエージェントの最も一般的な用途は,ネットワーク共有,ネットワーク加速,ネットワーク制限突破などである.また、HTTPエージェントは、Webアプリケーションのデバッグ、Android/IMSアプリで呼び出されるWeb APIの監視と分析にもよく使用されており、現在の有名なソフトウェアには、Fiddler、Charles、Burp Suite、mitmproxyなどがある.HTTPエージェントはまた、サービス側を変更することなく、Webアプリケーションに追加の機能を追加したり、アプリケーションの動作を変更したりするコンテンツ変更を要求/応答するために使用することもできる.
0 x 01 HTTPエージェントとは
HTTPエージェントは本質的にWebアプリケーションであり,他の一般的なWebアプリケーションとは根本的な違いはない.HTTPエージェントがリクエストを受信すると,ヘッダにおけるHostフィールドのホスト名とGet/POSTリクエストアドレスに基づいてターゲットホストを総合的に判断し,新たなHTTPリクエストを確立してリクエストデータを転送し,受信したレスポンスデータをクライアントに転送する.
要求アドレスが絶対アドレスである場合、HTTPエージェントはそのアドレスのHostを使用し、そうでない場合はHeaderの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://192.168.1.2/で行ないます.次に調整してGETリクエスト時に絶対アドレスを持参します
    $ telnet 192.168.1.3
    GET http://httpbin.org/ip HTTP/1.0
    HOST: 192.168.1.2
    
    

    注意ここでは同様にHOSTが192.168.1.2に設定されていますが、実行結果は戻ります.http://httpbin.org/ipページの内容、つまりパブリックIPアドレス情報.
    上記のテスト手順から分かるように、HTTPエージェントは複雑なものではなく、元のリクエストをエージェントサーバに送信すればよい.HTTPエージェントを設定できない場合、少量のHostがHTTPエージェントを歩かなければならない場合、最も簡単な方法はターゲットHostドメイン名のIPをエージェントサーバに指向することであり、hostsファイルを修正することで実現できる.
    0 x 02 PythonプログラムでHTTPエージェントを設定
    urllib 2/urllibエージェント設定
    urllib 2はPythonの標準ライブラリで、機能が強く、使うのが少し面倒です.Python 3ではurllib 2は保持されず、urllibモジュールに移行した.urllib 2では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は、すべてのurllib 2のように構成されたopenerをグローバル環境にインストールする.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エージェント設定
    requestsは現在最も優秀なHTTPライブラリの一つであり、私が普段httpリクエストを構築する際に最も多く使用しているライブラリでもあります.そのAPIのデザインは非常に人間的で、使いやすいです.requestsにエージェントを設定するのは簡単で、proxiesに{'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'}

    セッションのproxiesプロパティを直接設定することで、リクエストのたびにproxiesパラメータを持ち込む手間を省くことができます.
    s = requests.session()
    s.proxies = {'http': '121.193.143.249:80'}
    print(s.get('http://httpbin.org/ip').json())

    0x03 HTTP_PROXY/HTTPS_PROXY環境変数
    urllib 2もRequestsライブラリもHTTP_を認識できますPROXYとHTTPS_PROXY環境変数は、これらの環境変数が検出されると自動的にエージェントの使用を設定します.これは、HTTPエージェントでデバッグする場合に便利です.コードを変更することなく、環境変数に応じてエージェントサーバのipアドレスとポートを任意に調整することができます.*NixのほとんどのソフトウェアもHTTPをサポートしています.PROXY環境変数識別、例えばcurl、wget、axel、aria 2 cなど.
    $ 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はconsoleプログラムで、GUIインタフェースはありませんが、使いやすいです.mitmproxyを使用すると、任意のエージェントを介したHTTPリクエスト/応答パケットをフィルタリング、ブロック、修正することが容易になり、scripting APIを利用して、スクリプトを作成してHTTPデータを自動的にブロックして修正する目的を達成することができます.
    # test.py
    def response(flow):
        flow.response.headers["BOOM"] = "boom!boom!boom!"

    上のスクリプトは、エージェントされたすべてのHttp応答パッケージにBOOMというヘッダを追加します.mitmproxy -s 'test.py'コマンドでmitmproxyを起動し、curl検証の結果、BOOMヘッダが1つ増えたことが分かった.
    $ 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を実現し、社内のウェブサイトに機能を追加し、ユーザー体験を改善し、後で皆さんと共有する機会があります.
    転載先:https://www.cnblogs.com/jackyspy/p/6027385.html