読者です 読者をやめる 読者になる 読者になる

カスタムmitmproxy入門

f:id:vasilyjp:20160711100702j:plain VASILYのiOSエンジニアにこらすです!

今回はプロキシツールmitmproxyカスタムスクリプト機能について説明したいと思います。 モバイル開発をする際にAPIリクエストのデバッグツールとして mitmproxy はとても役に立ちます!

カスタムスクリプトを使うと何ができるか

カスタムスクリプトを書くと、mitmproxyの動作をプログラムでカスタマイズすることができます。 モバイルデバイスのリクエストやレスポンスを書き換えたり、通信を遅延させたりできます。

どうやってスクリプトを書くか

mitmproxyはPythonで実装されているので、カスタムスクリプトもpythonで実装することになります。 mitmproxyにはいろいろなイベントがありますが、各イベントをオーバーライドするメソッドを書くことができます。 例えば、script_name.py というPythonファイルにオーバーライドしたい処理を書いたなら、mitmproxyの-sオプションでそのファイルを指定するとカスタムスクリプトが動くようになります。

$ mitmproxy -s script_name.py

イベントをオーバーライドするメソッドについて

mitmproxyのイベントには4つの種類があります。

  • ライフタイムイベント(スクリプト開始、終了)

  • ネトワーク接続系イベント(クライアントのconnect、disconnect)

  • TCP系イベント

  • HTTPイベント

今回は、APIのデバッグ時によく使うHTTPイベントに注目します。

HTTPイベントメソッドオーバーライド

request(context, flow)

クライアントがリクエストをする直前にこのメソッドが実行されます。 このタイミングでリクエスト情報をチェックできますし、編集もできます!

response(context, flow)

このメソッドはサーバーから受け取ったレスポンスを編集することができます。

responseheaders(context, flow)

このメソッドはサーバーからレスポンスヘッダを受け取った直後に実行されます。 response(context, flow)より前にresponseheaders(context, flow)が実行されることが保証されているので、レスポンスボディを受け取る前にレスポンスヘッダを書き換えることができます。

error(context, flow)

エラーが発生した場合にこのメソッドに入ります。

mitmproxyのインラインスクリプトの実例

オーバーライドするための基礎を勉強したので今からちゃんとmitmproxyスクリプトを書いてみましょう!

ヘッダを書き換える

# リクエストヘッダを編集
def request(context, flow):
    flow.request.headers["language"] = "jp"

# レスポンスヘッダも同じです
def response(context, flow):
    flow.response.headers["language"] = "jp"

URLのパスが /users のリクエストだけ強制的に451エラーにする

def response(context, flow):
    if "/users" in flow.request.url:
        flow.response.status_code = 451 

60秒レスポンスが返ってこない状況をシミュレートする

import time

def response(context, flow):
    time.sleep(60)

URLのパスが /users のリクエストのレスポンスのボディを置き換える

def response(context, flow):
    if "/users" in flow.request.url:
        flow.response.content = b""    # bytesタイプのascii文字列

まとめ

今回はmitmproxyのカスタムスクリプトについて説明しました。 このたった4つのスクリプトを覚えるだけでも、APIの問題を解決できるようになると思います。 もっと詳しい情報や他のカスタムスクリプトについては、mitmproxyの公式サイトGitHubを参照してください。

ありがとうございました!

ー にこらす