証明書や手動プロキシ設定なしでAndroidのHTTPSトラフィックを傍受する方法
すべてのAndroid開発者は、ネットワークデバッガの設定に少なくとも半日は費やした経験があるでしょう。シナリオはいつも同じです。アプリがバックエンドに送信している内容を確認したいのに、代わりにSSLHandshakeExceptionが表示されます。
次に儀式が始まります。まず、自己署名CA証明書を生成します。次に、テストデバイスの信頼された証明書ストアにインストールしようとします。Android 7.0(API 24)以降、システムはデフォルトでユーザー証明書を無視するため、network_security_config.xmlを変更し、デバッグビルド用にtrust-anchorsを設定し、APKを再ビルドする必要があります。プロジェクトにSSLピン留めが構成されている場合、またはシステム証明書の処理がさらに制限されているAndroid 14でテストしている場合は、単純なレスポンスヘッダーのチェックが別のエンジニアリングタスクになります。
Proxymanチームのatlantis-androidライブラリは、この頭痛の種を根本的に解決します:プロキシの設定やデバイスのシステム証明書に触れる必要がなくなります。
Atlantisのコンセプト
Charles、Fiddler、またはProxyman自体のような従来のツールは、通常、Man-in-the-Middle(MitM)方式で動作します。デバイスはすべてのトラフィックをコンピュータのIPアドレスにリダイレクトし、デスクトップアプリケーションがリクエストを傍受、独自の証明書で復号化して転送します。これがまさに、証明書の信頼問題とWi-Fiプロキシ設定が問題になる理由です。
Atlantisは異なるアプローチを取ります。コンパクトなKotlinライブラリで、ネットワーククライアントのインタ셉タとしてアプリのデバッグビルドに直接組み込まれます。インタ셉タは、アプリがリクエストやレスポンスをすでに形成または復号化した時点で、そのパラメータを読み取ります。ライブラリはデータをシリアライズし、GZIPで圧縮し、別のローカルソケット経由でmacOS上のProxymanアプリに直接送信します。
結果として、Android設定への介入、マニフェストの変更、証明書の操作なしで、ネットワークアクティビティの詳細なログを取得できます。
ライブラリの機能
Atlantisは、日常的なネットワークデバッグタスクのほとんどをカバーします:
- OkHttpから直接、通常のHTTPおよびHTTPSリクエストを傍受。
- WebSocketイベントのログ記録:接続開始、メッセージ送信、着信パケット、セッション終了。
- Retrofit 2.9+やApollo Kotlin 3.x/4.xなど、一般的なネットワーククライアントとの完全な互換性。
- Network Service Discovery(mDNS)によるローカルネットワーク上の実行中のProxymanインスタンスの自動検出。
公式のAndroidエミュレータでプロジェクトを実行している場合、ライブラリはネットワーク検出をバイパスしてホストマシンに直接接続できます。
プロジェクトへの統合方法
このライブラリには、Android API 26(Android 8.0)以上、OkHttpバージョン4.xまたは5.x、Kotlinバージョン1.9以上が必要です。
まず、build.gradleファイルにJitPackリポジトリを追加します:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
その後、アプリのbuild.gradleに依存関係を追加します。デバッグコードがリリースビルドに含まれないようにするために、debugImplementationで追加することをお勧めします:
dependencies {
debugImplementation("com.github.ProxymanApp:atlantis-android:v1.0.0")
}
このライブラリは、アーティファクトcom.proxyman:atlantis-androidでMaven Centralからも利用可能です。
クイックスタート
統合は数行のコードで完了します。まず、ApplicationクラスでAtlantisを初期化します:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Atlantis.start(this)
}
}
}
次に、OkHttpClient設定にインタ셉タを追加します:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(Atlantis.getInterceptor())
.build()
Retrofitを使用している場合、このOkHttpClientインスタンスをRetrofitに渡すと、すべてのリクエストが自動的にProxymanウィンドウに表示されます。
WebSocketの操作
アプリでWebSocketを使用している場合、標準のOkHttpインタ셉タでは不十分です。メッセージはすでに開いている接続内で送信されるためです таких случаях библиотека предоставляет специальную обёртку для слушателя:
このような場合、ライブラリはリスナの特別なラッパーを提供します:
val originalListener = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
// обработка открытия
}
override fun onMessage(webSocket: WebSocket, text: String) {
// входящее сообщение
}
}
val wrappedListener = Atlantis.wrapWebSocketListener(originalListener)
okHttpClient.newWebSocket(request, wrappedListener)
これで、デスクトップクライアントで着信フレームと送信フレームをリアルタイムで観察できます。
内部構造
ライブラリのソースコードはミニマリストで、Apache 2.0ライセンスで公開されています。リポジトリには重いサードパーティの依存関係がほぼありません。
アーキテクチャはいくつかの明確なモジュールで構成されています:
- AtlantisInterceptorとAtlantisOkHttpInterceptorがネットワークスタックレベルでデータを傍受します。
- RequestSerializerとResponseSerializerはリクエストボディとバイナリペイロードをパッケージ化し、電話とコンピュータ間の通信チャネルの負荷を軽減します。
- ProxymanDiscoveryServiceは、Android NSD API経由でローカルネットワーク上のProxymanサービスを検出します。
- TCPConnectionはデスクトップアプリケーションへのTCP接続を開き、構造化されたパケットを転送します。
トラフィックの圧縮により、デバッグはアプリのパフォーマンスに実質的に影響を与えません。
注意すべき制限事項
ライブラリを統合する前に、2つの考慮事項があります。
第一に、AtlantisはProxymanデスクトップクライアントに依存しています。あなたのチームがWiresharkやCharles exclusivelyの使用に慣れている場合、このインタ셉タを通じてデータを転送することはできません。
第二に、ライブラリは、インタ셉タを明示的に追加したクライアントからのトラフィックのみを傍受します。アプリのサードパーティSDKが独自のOkHttpClientまたはHttpURLConnectionでネットワーク呼び出しを行う場合、Atlantisはそのリクエストを認識しません。サードパーティバイナリの完全な分析には、従来のMitMプロキシを引き続き使用する必要があります。
試してみる価値はあるか
メインの開発マシンがmacOSで、iOSやバックエンドのデバッグにすでにProxymanを使用している場合、atlantis-androidは多くの時間を節約できます。テスト電話でWi-Fiプロキシを設定したり、証明書をリセットしたり、AndroidManifest.xmlを変更したりする必要がなくなります。デバッグAPKをビルドし、電話でアプリを開くだけで、すべてのネットワーク交換がすぐに画面に表示されます。
関連プロジェクト
