3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Unityで作成したAndroidアプリのhttp/https通信をキャプチャする

Last updated at Posted at 2019-09-08

#概要
Androidアプリの通信がどのように見えるのか気になったので、パケットキャプチャして通信内容を見る方法について調べてみた。思いのほか大変だったので情報をまとめておく。

筆者の環境はPCがWin10でスマホがAndroid8.1。

#1.Unityで適当に通信するアプリを作る

通信するクラスを適当に作成。
テストがしたいだけなので、なんか良い感じのサーバないかな?と思ったらhttpbinなる便利なサイトを発見。使わせて頂きます。圧倒的感謝。使い方その他は以下のサイト様が分かりやすいです。
https://www.softantenna.com/wp/review/httpbin/

WebRequestTest.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class WebRequestTest : MonoBehaviour
{
    public string URL;
    [SerializeField] private Dropdown dropdown;

    public IEnumerator WwwRequestTest(string url)
    {
        WWW www = new WWW(url);
        yield return www;
        Debug.Log(www.text);
    }

    public IEnumerator UnityWebRequestTest(string url)
    {
        using (UnityWebRequest request = UnityWebRequest.Get(this.URL))
        {
            yield return request.SendWebRequest();
            if (request.isNetworkError || request.isHttpError)
            {
                Debug.Log(request.error);
            }
            else
            {
                Debug.Log(request.downloadHandler.text);
            }
        }
    }

    public void HttpWebRequestTest(string url)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            Debug.Log("Proxy.Credentials: " + request.Proxy.Credentials);

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream stream = response.GetResponseStream();
            string webContext = new StreamReader(stream).ReadToEnd();
            Debug.Log(webContext);

        }
        catch (WebException webException)
        {
            var ex = webException as Exception;
            while (ex != null)
            {
                Debug.Log(ex.ToString());
                ex = ex.InnerException;
            }
        }
    }

    public void OnWWWButtonClicked()
    {
        Debug.Log("OnWWWButtonClicked");
        Debug.Log(this.URL);

        StartCoroutine("WwwRequestTest", this.URL);
    }

    public void OnUnityWebRequestButtonClicked()
    {
        Debug.Log("OnUnityWebRequestButtonClicked");
        Debug.Log(this.URL);

        StartCoroutine("UnityWebRequestTest", this.URL);
    }

    public void OnHttpWebRequestButtonClicked()
    {
        Debug.Log("OnHttpWebRequestButtonClicked");
        Debug.Log(this.URL);

        this.HttpWebRequestTest(this.URL);
    }

    public void OnURLChanged()
    {
        var keyMap = new Dictionary<int, string>();
        keyMap.Add(0, "http://httpbin.org/ip");
        keyMap.Add(1, "https://httpbin.org/ip");

        this.URL = keyMap[this.dropdown.value];
    }
}

以上のスクリプトを適当なGameObjectに追加して、適当にボタンとurlを変更するドロップダウンメニューを作成する。

android_http_test.png

エディタ上で動作することを確認したあと、apkをビルドして実機にインストールする。

通信ができているかどうかの確認はDebug.logの出力で確認できる。Android実機で確認する場合のadbコマンドは以下。

adb logcat | findstr -i unity

#2 Fiddler

android_http_test.png

https通信のデータの中身まで見る方法を調べてみたところFiddlerというツールを使えば見れるらしい。Fiddlerの他にも同類のツールはいろいろある様子。

導入方法その他は以下のサイト様の記事が分かりやすい。
https://amimilab.com/2016/08/14/post-183/

Fiddlerで立てたプロキシサーバ経由で通信することで、Fiddler上で通信の中身を全部みれるようになるらしい。
**しかし、上記のサイト様を参考にFiddlerを試してみても、https通信はキャプチャできなかった。**調べてみたところAndroidのca証明書に関する仕様が変わったのが原因らしい。

###Androidの通信まわりの仕様変更
Android7で特別に設定されていない限り、カスタムされたca証明書を無視する仕様になったらしく、Fiddlerが生成したca証明書をAndroid端末にインストールしてもこの証明書は無視されてしまうようだ。アプリ側で使用するca証明書を明示する必要性があるらしい。

android_http_test.png

余談だがAndroid9ではデフォルトでhttp通信ができないようになっているらしいので、Android9以上の端末を使用する場合は注意が必要です。
https://developer.android.com/about/versions/pie/android-9.0-changes-28?hl=ja#apache-p

###カスタムca証明書を利用して通信するように設定する

Android公式のドキュメントを参照するとAndroidManifest.xmlのapplicationの項目に networkSecurityConfigというプロパティ?を記述して、さらに設定ファイルを追加する必要があるらしい。

UnityでapkをビルドするときはAndroidManifest.xmlをUnity先生が勝手に良い感じに作成してくれているが、これを編集する必要があるようだ。これに関しては以下のサイト様が詳しい。
https://blog.wizaman.net/archives/1026

Assets/Plugins/Androidディレクトリ配下にAndroidManifest.xmlを追加するとビルドするときにUnity先生が良い感じにマージしてくれるらしい。雛形のAndroidManifest.xmlの入手方法は、公式によるとapkをビルド後にAndroidManifest.xmlがキャッシュされているらしいのでこれをコピペして使うのが手軽かもしれない。場所はTemp/StagingArea/AndroidManifest.xml

自分はビルドしたapkファイルをapk_toolでデコンパイルして入手した。

Assets/Plugins/Androidディレクトリ配下にAndroidManifest.xmlをコピペしたらこれを編集する。application のところにandroid:networkSecurityConfig="@xml/network_security_config"と記述する。

        <application android:networkSecurityConfig="@xml/network_security_config" >
        </application>    

次にAssets/Plugins/Android/res/xmlディレクトリを作って配下に適当なテキストエディタかなんかでnetwork_security_config.xmlファイルを作成する。内容は以下。

   <network-security-config>
        <base-config>
            <trust-anchors>
                <certificates src="system"/>
                <certificates src="user"/>
                <certificates src="@raw/fiddlerroot"/>
            </trust-anchors>
        </base-config>
    </network-security-config>

ちなみにこのnetwork_security_config.xmlファイルについてググってると<certificates src="user"/>だけでイケるっていう情報があったが自分はだめだった。上記のようにca証明書を直接指定してやったらイケた。

ということで、次にFiddlerがhttp://ipv4.fiddler:8888/で生成してくれるca証明書をdlしてAssets/Plugins/Android/res/raw/ 配下に追加する。このときca証明書はFiddlerRootっていう名前になっていると思うが、AndroidManifestでは大文字は使えないので、リネームする必要があることに注意。自分は適当にfiddlerrootに変更した。

以上を設定できたらUnityでapkをビルドしてAndroid端末にインストールする。あとはFiddler上でhttp/https通信の中身を全部見れるようになる。

3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?