How to view network traffic requested by a specific app?
If you have rooted phone, go for nethogs
(for live monitoring) or iptables
(to get statistics) commandline tools. VPN または Android 統計ベースのアプリを使用することが、非 root 化の唯一の可能な解決策です。 または、logcat
/dumpsys
ベースのソリューションについては、この回答を参照してください。
まず第一に、ネットワーク ストリームの UID または PID の追跡は、ネットワーク関連ではなく OS 関連のパラメータであるため、簡単ではありません。 提案や放棄されたプロジェクトは存在します。
Android では、Linux のすべてのユーザーが UID を持っているように、インストールされたすべてのアプリに固有の UID を割り当てています。 そのため、特定のUIDからネットワークインタフェースに送信されたパケットをキャプチャすることで、使用状況を追跡することができます。
TCPDUMP:
さて、どのようにしてネットワーク トラフィックをキャプチャできるのでしょうか。 ほとんどのネットワークスニッファーは、この目的のためにシステム非依存型ライブラリのlibpcapファミリーを使用しています。 これは、カーネル内のパケットフィルタリングのためにBSD Packet Filter (BPF) をサポートしています。 libpcap
を使用する一般的なユーティリティには、tcpdump
、nmap
、tshark/wireshark
、dumpcap
、nethogs
等があります。 Android アプリのネットワーク ユーティリティなども tcpdump
.
ただし、UID 情報は pcap
が OSI レイヤ 2 で使用する AF_PACKET
/PF_PACKET
チャネルを通じて伝搬されることはありません。 そこで、ここでできることは、アプリケーションによって作成および使用されるネットワーク ソケット (IP とポートの組み合わせ) を利用することです。 netstat -tup
またはss -tup
は、アクティブな/確立された接続を持つすべてのネットワークソケットを表示します。 どちらのツールもAndroidで利用可能です(または静的なバイナリを入手することもできます)。 ソケット対UIDの情報は、/proc/net/{tcp,udp}
から直接読み取ることもできます。 AndroidアプリのNetstat Plusも同じ原理で動作します。 これは、プロセスによって使用されているローカル アドレス (ソケット) を提供します。
どのソケットがアプリ (UID) によって使用されているかがわかると、tcpdump -i wlan0 src <IP> and port <PORT>
はそのプロセスから発信されたすべてのトラフィックをダンプします。
LIMITATIONS:
ただし、このアプローチにはいくつかの問題があります。
- 通常、Android アプリは一度に複数のプロセスを並行して起動します。 そのため、すべてのプロセスからのトラフィックをキャプチャする必要があります。
- アプリケーションは、ソケットを作成および削除し続けます。
- UNIX 系 OS では、ローカル ソケットが複数のプロセスで共有されている可能性があります (まれですが)。 DNS 解決に使用される UDP/53 のようなリモート共有ソケットは、単一のプロセスで追跡できません。
NetHogs は procfs
をトラバースし、上記の制限に対処します (ただし、常に大成功とは限りません):
IPTABLES:
Layer 2 ツールの上記の欠点は iptables LOG
または NFLOG
によって軽減することが可能です。 レイヤ 2 は物理層のすぐ上にあり、パケットがデバイスを離れる前に遭遇する最後のものです。 そのため、OSI レイヤ 3 (ユーザ空間プログラムに近い) で動作する netfilter
/ iptables
と比較して、データリンクレイヤで、ネットスタックの下位レベルで動作する BPF は、一種のステートレス パケット フィルタリング機構と言えます。 そのため、iptables
はTCP/IPスタック(レイヤ4)からも情報を取得することができる。
iptables
はカーネルログに書き込み、 dmesg
または logcat
を使って読み込むことができます。
# iptables -I OUTPUT -m owner --uid-owner <UID> -j LOG --log-level 7 --log-prefix 'SNIFFER: ' --log-uid# dmesg -w | grep SNIFFER
出力はファイルに保存でき、grep
, awk
, printf
などのツールを使ってフォーマットすることが可能です。 Network Log -非常に時代遅れですが- も同様の方法で動作します。 AFWall+ は iptables
に基づくファイアウォールで、アプリがブロックされたときに、アプリのネットワーク活動を記録/通知することができます。
この方法の唯一の欠点は、同じ UID で複数のプロセスが実行されている場合、1 つのプロセスからのトラフィックをスニッフィングするために使用できないことです。 iptables
は PID に基づいてパケットをキャプチャすることはできません。 プロセスはブロック/スニッフィングされる前に開始され、プログラムはブロック/スニッフィングされない新しい PID を持つ子プロセスを簡単に生成できるため、プロセスで iptables
を使用しないことにしました。 また、PIDはソケットがそうであるように素早く作成され、破棄されます。
QTAGUID:
owner
モジュールは、IP パケットが所有者情報を持たないため、受信または転送されるトラフィックでは機能しないでしょう。 アプリごとの受信/送信ネットワーク使用量を測定するために、Android はカーネルに qtaguid
モジュールを組み込むパッチを適用しました。 /proc/net/xt_qtaguid/stats
からは統計情報を読み取ることができます。 シェル スクリプトを使用して、再起動後のライブ データ使用量を取得できます:
ただし、Android 9 以上では qtaguid
は拡張 BPF (Linux カーネルの netfilter
フレームワークも置き換える予定) に置き換えられる予定です。 関連記事
IPTABLES + TCPDUMP:
別の方法として、アプリからの送信トラフィックを NFLOG
グループに入れ、後でそのグループから tcpdump でパケットをキャプチャすることも可能です。 しかし、パケットがルーティングテーブルで落とされたり失われたりした場合などには、まだ偽陽性を示すことがある。 そのため、スニッファーはOSIレイヤー2で動作します。 さらに良い方法は、プロキシ/VPNサーバー、テザリングされたPC、ルーターなどを使用して、外部から監視することです。
OTHER OPTIONS:
- プロセスのネットワークアクティビティに関連する
syscalls
を追跡するためにstrace
などの診断ツールを使用します。 -
iptables
NETFILTER_XT_MATCH_CGROUP
と共に Network classifier cgroup を使って、特定のプロセスからのトラフィックをスニッフィングしてください。 - もし完全に特定のプロセスからのトラフィックをブロックすることが目的であれば、
SELinux
とseccomp
を使用して、それぞれ restrictedpolicies
と suppressingsyscalls
を定義し、プロセスがソケットを作成する能力を制限することが可能である。
これらのほとんどは、Android では直接実行可能なオプションではなく、高度な設定が必要です。
ANDROID の API (NON-ROOT OPTIONS):
NetGuardなどの一部のアプリは、AndroidのVpnService APIを使ってレイヤー3 (TUN interface) でトラフィックをブロックしています。 このアプリでは、「アプリケーションがインターネットにアクセスしたときに通知する」ことができます。 Android では、UIDs
および SOcket_MARKs
(1, 2) を使用して、デバイスから離れる直前にネットワーク ルーティング ポリシー (RPDB) でトラフィックを制御するため、アプリごとのキャプチャと追跡 (1, 2) が VPN API を使用して可能です。
NetLiveなどの一部のアプリはNetworkStatsManagerを使用していますが、リアルタイム使用から遅れ、「十分に迅速に更新しない」、これは「過去のデータを提供するため」のものです。