PCAPdroid:不 root 也能抓 Android 出站流量,还能顺手做 TLS 解密
想搞清楚手机里某个 App 到底在网上传什么,最常见的两条路是 root 后装 tcpdump,或者用 adb 连电脑跑抓包。两样都嫌烦。PCAPdroid 的思路不太一样:它用 Android 自带的 VpnService 在本地搭了个 L4 代理,流量先经过自己再出去,全程不需要 root,也没有远程服务器介入。
项目在 https://github.com/emanuele-f/PCAPdroid 开源,GPL-3.0 协议,作者 emanuele-f,目前 star 数约 4.6k。代码主体是 Java/Kotlin 加 C/C++ JNI,核心依赖 nDPI(协议识别)、zdtun(极简 TCP/IP 栈)和 mitmproxy(TLS 解密)。当前最新版 v2.0.0(versionCode 92),minSdk 23,对应 Android 6.0 以上;APK 的最低要求是 Android 5.0+。官方文档在 https://emanuele-f.github.io/PCAPdroid。

PCAPdroid 网络监控链路
功能全景:免费版够用,付费版补拦截
免费能力已经覆盖日常审计场景:按应用维度记录每条出站连接,提取 SNI、DNS 查询、HTTP URL、远端 IP,内置解码器直接看 HTTP 请求和应答,也支持完整 payload 的 hex/文本查看。HTTPS/TLS 可以配合 PCAPdroid-mitm(https://github.com/emanuele-f/PCAPdroid-mitm,基于 mitmproxy)做中间人解密,导出 SSLKEYLOGFILE 后在 Wireshark 里还原明文。抓下来的流量可以写成 .pcap 文件,也可以通过内置 HTTP 服务在局域网内下载,或者实时流给 Wireshark 看。过滤规则能把"正常"连接隐藏掉,只留异常部分。
付费功能有三项:防火墙(按应用、域名、IP 拦截)、恶意软件检测(走第三方黑名单)、PCAPng 格式(把 TLS 主密钥直接嵌进文件,Wireshark 打开就是明文)。从 F-Droid 或 GitHub Release 装的话,需要购买后拿 unlock token 换许可证代码,一个 token 最多生成 3 个许可证。

PCAPdroid 免费与付费功能全景
安装与构建
普通用户直接装 F-Droid 版就行。F-Droid 页面在这里:https://f-droid.org/packages/com.emanuelef.remote_capture/。这个包用的是 F-Droid 官方构建签名,可以复现,建议通过 F-Droid 客户端安装,这样之后更新不会漏。F-Droid 上还有一个官方 Beta 仓库,想提前试新功能可以自己加。
自己编译也不复杂:clone 仓库后先跑 git submodule update --init 拉取 nDPI、zdtun、libpcap 等子模块,然后 Android Studio 打开项目,装好对应版本的 SDK 和 NDK。注意 CMake 版本要和 app/build.gradle 里声明的 3.22.1 对齐,不然会编不过。
高效用法:先过滤,再捕获
第一次打开 PCAPdroid,别急着点播放按钮。先去 Status 页签里把 App Filter 设置好,只把目标应用路由进 VPN。这一步能显著降低流量噪声,而且后面配 mitmproxy 解密时也不用拆其他 App 的 TLS 流量。
捕获开始后,Connections 页会列出每条出站连接,包含应用名、协议、SNI/DNS/URL、状态、时间和流量大小。点进去看单条详情,能看到 IP 统计和明文请求内容。
降噪的核心操作是"隐藏连接":长按一条觉得正常的连接,把它加进 Hidden Connections 列表,这个列表是持久保存的。多积累几轮之后,剩下的就都是值得看的东西。搜索栏支持按 IP、host、协议、应用名或 UID 过滤,Edit Filter 还能按未隐藏、明文、状态等条件过滤。Apps 视图则按应用汇总流量,点某个应用可以直接把它设为过滤条件。
PCAP 导出默认走 HTTP 服务,端口 8080。在 PC 浏览器里访问手机 IP:8080 就能流式下载 PCAP 文件。这里有两个坑:
- 浏览器里的下载进度可能一直显示 0%,这是正常的,不代表卡住。
- 只有点击下载之后的流量才会写入文件,之前捕获的不会包含进去。
另外,如果手机连着公共 Wi-Fi,记得把 dump mode 改成 None,否则局域网内任何人访问 8080 端口都能下载你的流量。
技术架构:VpnService 加 L4 代理
PCAPdroid 不是旁路抓包,是本地代理。启动后,它通过 VpnService 把自己注册成设备的 VPN,所有出站流量被路由到应用内部。zdtun 在这里扮演一个极简 TCP/IP 栈:它用 L4 socket 重新连接远端服务器,同时给原 App 伪造 IP/TCP 头,让 App 以为自己直连了互联网。
这个设计的好处很明显:门槛低,不需要 root,数据全程在设备本地处理,PCAPdroid 不连任何远程 VPN 服务器,这就是项目强调 privacy-friendly 的原因。
代价也摆在这里:
- PCAP 文件记录的是"原始连接"视角,但 L3/L4 头和包大小已经被改写
- 只捕获出站连接,入站流量不经过 VpnService
- 无法还原远端发过来的数据原本拆成了几个包
所以非 root 模式下生成的 PCAP 不适合做逐包、时序或底层协议分析。要 1:1 的真实流量视图,只能在 root 设备上切到 root 抓包模式。root 模式下还能抓到系统里其他 VPN 之外的流量。
无 root 时也抓不到其他 VPN 客户端的流量,这个限制来自 VpnService 本身。
协议识别走 nDPI,TLS 解密走内置的 mitmproxy,离线 GeoIP/ASN 查询用 MaxMind 库,dump 文件或远程接收用 libpcap,整条链路都在设备本地完成。

PCAPdroid 非 root 抓包架构
用之前先记住边界
PCAPdroid 在 Android 平台上属于少有的开箱即用抓包工具。普通用户拿免费版就能看清哪个应用在偷偷上传、连了哪些服务器;安全测试人员可以配合 PCAPdroid-mitm 做 TLS 解密,再把 PCAP 扔给 Wireshark。在 Wireshark 里要显示应用名,需要装官方提供的 lua 脚本。
但有几个边界得提前知道:
- 非 root 模式会改写底层头部,不适合做精细的逐包分析
- 防火墙拦不住 DNS 解析和 Google IPC 通信
- 恶意检测只在抓包运行的时候生效,而且存在误报
- 连接日志受内存限制,多了会被丢弃
这些是设计取舍,不是 bug。清楚了再上手,能省不少排查问题的时间。