mitmproxyにおけるリクエスト編集の末尾改行文字の仕様
mitmproxyを使っていて「ん?」となる挙動があったので備忘として記録します。
詰まったポイント
mitmproxyではhttp, https通信以外にも生のTCPペイロードをインターセプトして値を編集、それらを送信することができます。
http以外のTCPで通信をするアプリケーションの通信部分のデバッギングに非常に便利なのですが、mitmproxyには一部のユーザーにとって初見殺しに近い仕様が隠されていました。
問題となる仕様
TCPペイロードをインターセプトし、インターセプトしたリクエスト/レスポンスを編集すると末尾の改行文字が削除されるという点です。
TCPペイロード以外にもHTTPなどではインターセプトした際、ヘッダなどをmitmproxy上で自動認識してある程度区分けされた状態でリクエスト/レスポンスの編集を行うことができます。
そのような場合では改行文字などはmitmproxy上で自動で付与されるため、通常であれば問題は発生しません。
TCPペイロードの場合、アプリケーションによっては末尾に改行文字を含ませてリクエスト/レスポンスを送受信することがあります。
しかしながら、mitmproxyには末尾に改行文字が含まれているTCPペイロードを編集して送信する際、元のリクエスト/レスポンスに付与されていたTCPペイロードの改行文字が抜け落ちてしまう事象が存在します。
今回は改行文字が抜け落ちてしまうことで、アプリケーション側の処理がストップしてしまう事象に遭遇しました。
修正自体は簡単なので、以下に修正方法を記載します。
修正方法
修正したバージョン
実行バイナリではなく、pip3でインストールしたバージョンです。
Mitmproxy: 8.1.1
Python: 3.10.4
OpenSSL: OpenSSL 3.0.5 5 Jul 2022
Platform: Linux-5.15.0-47-generic-x86_64-with-glibc2.35
修正箇所
対象: ~/.local/lib/python3.10/site-packages/mitmproxy/tools/console/consoleaddons.py
450 elif flow_part == "tcp-message":
451 message = flow.messages[-1]
452 c = self.master.spawn_editor(message.content or b"")
453 #message.content = c.rstrip(b"\n")
454 message.content = c
453行目でインターセプトしたリクエスト/レスポンスを編集したあとの文字列から末尾改行文字を捨てているため、これをコメントアウトしてrstripしていないデータを返せばOKです。
おわりに
謎の挙動すぎて初めは困惑したけどソース見たら一発でしたね…。
さすがにアレなのでプルリク送ろうと思ったんですが、修正したソースコードの上のほうにこんなことが書いてあり、送るのをやめました。
# Many editors make it hard to save a file without a terminating
# newline on the last line. When editing message bodies, this can
# cause problems. We strip trailing newlines by default, but this
# behavior is configurable.
エディタの挙動にもよるらしく、改行の切り捨てを安易に行うのは全体的に見るとよくなさそうな感じがします。
mitmproxyを使う人間なら自分で直せという雰囲気を感じました。