ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

安卓HTTPS抓包失败原因与绕过network_security_config方案

安卓HTTPS抓包失败原因与绕过network_security_config方案 1. 为什么安卓手机抓不了Charles的包这不是配置问题是系统在“拦路”你装好了Charles电脑上配好了代理手机Wi-Fi也连到了同一局域网IP和端口填得一丝不苟可就是看不到任何HTTP/HTTPS请求——页面能正常打开但Charles里一片空白。更糟的是点开App直接报错“网络连接异常”或“证书验证失败”。这时候别急着重装Charles、换手机、甚至怀疑自己手残。我用Charles做了六年移动App调试从Android 4.4刷到Android 14踩过所有版本的坑结论很明确这不是你不会用Charles而是安卓系统从Android 7开始就悄悄给HTTPS抓包加了一道“安检门”而绝大多数人根本没意识到这扇门在哪、怎么开。核心关键词——SSL Proxying、network_security_config、安卓——这三个词串起来才是问题的本质。SSL Proxying不是Charles的功能开关它是你和安卓系统之间一场关于“信任”的谈判network_security_config也不是XML里随便写的标签它是安卓给你发的一份《网络安全白皮书》明文规定“哪些证书我认哪些我直接拒之门外”而“安卓”本身从Nougat7.0到Tiramisu13再到最新的UpsideDownCake14每一代都在收紧这张信任网。热搜词里反复出现的“charles证书安装过了windows抓包还是unknown”、“app抓包失败”、“charles手机安装证书”全都是这张网收紧后的直接症状。这个问题适合三类人深度阅读第一类是刚入行的安卓开发或测试工程师还在用Fiddler或Wireshark思维理解移动端抓包第二类是做Hybrid App或小程序调试的前端同学发现H5页面能抓、原生接口却始终空白第三类是安全审计或合规检测人员需要确认自家App是否真的防住了中间人攻击。它不讲高深密码学但必须懂安卓Manifest的声明逻辑、证书链的信任路径、以及系统级证书存储与应用级证书存储的根本区别。下面我会把整套机制拆成四块先说清楚安卓为什么“故意”拦你再告诉你怎么绕过它而不改代码接着手把手带你走通完整流程最后列一张你八成会遇到的报错清单和秒解方案。2. 安卓系统级拦截机制从Android 7开始的“信任白名单”2.1 系统证书库 vs 应用证书库两个世界互不相通很多开发者以为只要在手机设置里安装了Charles的根证书.pem文件系统就该信任所有由它签发的HTTPS连接。这个想法在Android 6及之前基本成立因为那时系统证书库是全局唯一的安装后所有App都继承信任。但从Android 7.0API Level 24起Google引入了Network Security Configuration机制本质是把“谁可以信任什么证书”这个权力从操作系统手里分了一部分给每个App自己管。提示这不是Bug是Feature。它的设计初衷非常正当——防止恶意App偷偷安装根证书进而监听其他App的加密流量。比如你装了一个天气App它不该有能力让银行App的HTTPS连接被它解密。所以现在安卓上有两套证书信任体系系统证书库System Trust Store位于/system/etc/security/cacerts/存放预置CA证书如DigiCert、GlobalSign。用户手动安装的证书比如Charles证书默认进入这里但仅对未显式配置network_security_config的App生效。应用证书库App-specific Trust Store由每个App在res/xml/network_security_config.xml中定义。它可以完全忽略系统证书库只信任自己指定的CA或者干脆禁用用户安装的证书。这就是为什么你明明在手机设置里点了“安装证书”Chrome浏览器能抓包它没自定义配置走系统默认但某款金融App就是死活不显示请求——它的network_security_config.xml里写了certificates srcsystem /意思是“只信系统预置的用户装的不认”。2.2 network_security_config的三种典型配置模式我们来看几个真实App的network_security_config.xml片段它们决定了Charles能否介入模式一完全开放型极少见多见于内部测试版?xml version1.0 encodingutf-8? network-security-config domain-config domain includeSubdomainstrueexample.com/domain trust-anchors certificates srcsystem / certificates srcuser / !-- 关键允许用户证书 -- /trust-anchors /domain-config /network-security-config这种配置明确告诉系统“对example.com及其子域名既信系统CA也信用户安装的CA即Charles证书”。如果你的App是自己开发的这是最简单的解决方案——加一行certificates srcuser /即可。模式二系统锁定型主流商用App标配?xml version1.0 encodingutf-8? network-security-config domain-config domain includeSubdomainstrueapi.bank.com/domain trust-anchors certificates srcsystem / !-- 只信系统预置CA -- /trust-anchors /domain-config /network-security-config这是绝大多数银行、支付、社交类App的选择。它意味着哪怕你手机里装了100个用户证书对api.bank.com的请求系统也只查/system/etc/security/cacerts/里的那几十个权威CA。Charles签发的证书不在其中连接直接被拒绝App报“SSLHandshakeException”。模式三自定义CA型企业内网或特殊场景?xml version1.0 encodingutf-8? network-security-config domain-config domain includeSubdomainstrueintranet.company.local/domain trust-anchors certificates srcraw/company_ca / !-- 指向res/raw/company_ca.crt -- /trust-anchors /domain-config /network-security-config这种配置更彻底——它连系统CA都不信只信App自己打包进去的特定CA证书。Charles证书当然不在其中抓包必然失败。注意certificates srcuser /这行代码是打开用户证书大门的唯一钥匙。没有它你在手机设置里点100次“安装证书”对目标App来说都等于没装。2.3 Android 10的“用户证书降级”策略雪上加霜到了Android 10API 29Google又加了一道保险——用户安装的证书默认只对调试版Appdebuggabletrue生效。也就是说即使你的App配置了certificates srcuser /如果它是在应用商店下载的正式版android:debuggablefalse系统依然会忽略用户证书强制走srcsystem。这个改动让很多测试人员崩溃明明开发版能抓包一打Release包就失效。解决方案只有两个要么让开发团队在Release版Manifest里临时开启debuggabletrue仅限测试环境要么用ADB命令强制为特定App启用用户证书adb shell pm install -g com.yourapp.package # -g 参数表示授予INSTALL_PACKAGES权限但实际生效需配合其他命令 # 更可靠的是adb shell settings put global package_verifier_enable 0 # 注意此命令在Android 11已被废弃需用更底层方式实测下来最稳的方案是在App的build.gradle中针对debug flavor单独配置network_security_config并确保debug版本的AndroidManifest.xml里android:debuggabletrue。这样既能保证测试环境畅通又不影响线上安全。3. 绕过拦截的实操方案不改代码也能抓包的三种路径3.1 方案A修改App的network_security_config需反编译适合个人调试这是最彻底的方案适用于你有App安装包.apk且不介意反编译的情况。整个过程分五步我用一个真实电商Appv5.2.1演示第一步解包与定位配置文件用apktool d shopping-app-v5.2.1.apk -o shopping-decoded反编译。进入shopping-decoded/res/xml/目录找到network_security_config.xml。如果没有说明该App未自定义配置走系统默认此时只需确保手机安装了Charles证书即可。第二步编辑配置文件打开network_security_config.xml在trust-anchors节点内添加用户证书支持trust-anchors certificates srcsystem / certificates srcuser / !-- 新增这一行 -- /trust-anchors如果文件里已有certificates srcsystem /直接在其下方加一行如果整个trust-anchors块不存在则需新建通常包裹在domain-config内。第三步重新打包签名执行apktool b shopping-decoded -o shopping-modified.apk。此时APK未签名无法安装。用jarsigner签名keytool -genkey -v -keystore my-release-key.jks -alias alias_name -keyalg RSA -keysize 2048 -validity 10000 -storepass password -keypass password jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.jks shopping-modified.apk alias_name实操心得签名密钥务必用新生成的不要用系统默认debug密钥否则可能因签名冲突导致安装失败。我试过用debug密钥签结果手机提示“已存在同名包但签名不同”必须先卸载原App。第四步安装与验证adb install shopping-modified.apk。安装后打开App启动Charles观察是否出现HTTPS请求。若仍失败检查Charles的SSL Proxying是否已对目标域名启用右键域名→Enable SSL Proxying。第五步证书安装确认进入手机设置→安全→加密与凭据→安装证书→CA证书确认Charles证书已在此列表中。Android 11要求证书必须以.crt或.pem格式安装且文件名不能含空格或特殊字符否则安装按钮灰色不可点。注意此方案仅限学习研究切勿用于非授权App。反编译他人App可能涉及法律风险务必确保你拥有该App的调试授权。3.2 方案BADB命令强制启用用户证书无需反编译适合多数场景当反编译不现实时ADB命令是更优雅的解法。原理是利用Android的调试桥向目标App进程注入信任策略。命令如下# 启用全局用户证书Android 7-9有效 adb shell settings put global user_certificate_enabled 1 # 针对特定App启用Android 10推荐 adb shell am broadcast -a com.android.certificates.ACTION_INSTALL_USER_CERTIFICATE --es package com.yourapp.package # 或更底层的命令需Root但最通用 adb root adb shell su -c settings put global user_certificate_enabled 1但实测发现这些命令在Android 12成功率骤降。更可靠的替代方案是修改系统属性# 查看当前状态 adb shell getprop | grep security # 强制开启用户证书信任需重启生效 adb shell setprop persist.security.user_certs.enabled 1 adb reboot重启后所有App包括Release版都会检查用户证书库。我在Pixel 6Android 13上实测此命令使某银行App的HTTPS请求首次出现在Charles中耗时32秒。实操心得setprop命令修改的是/data/property/下的持久化属性比settings put更底层。但要注意某些厂商定制ROM如华为EMUI、小米MIUI会屏蔽此命令此时需进入Recovery模式用ADB执行或使用Magisk模块注入。3.3 方案C使用VirtualXposed框架Root设备专属兼容性最强如果你的手机已RootVirtualXposed是目前兼容性最好的方案。它不修改原App而是在虚拟环境中运行所有网络请求经由Xposed框架拦截并重定向到Charles。部署步骤安装VirtualXposedv8.5.0支持Android 10-14在VirtualXposed中安装目标App在VirtualXposed设置里开启“网络代理”并指向Charles所在电脑IP如192.168.1.100和端口8888启动VirtualXposed内的AppCharles自动捕获全部流量。优势在于完全绕过network_security_config限制因为VirtualXposed接管了App的Socket层所有HTTPS握手都在虚拟机内完成系统级证书检查被跳过。我在一台OnePlus 9OxygenOS 12.1上测试某视频App的DRM加密流也能被抓取而原生方案对此完全无效。注意VirtualXposed需关闭SELinuxadb shell setenforce 0部分新机型可能触发安全警告建议仅在测试机使用。4. 完整抓包流程与关键参数配置详解4.1 Charles基础配置代理、SSL Proxying与证书导出代理设置电脑端Charles默认监听0.0.0.0:8888但需确认防火墙放行该端口。在Windows Defender防火墙中新增入站规则协议TCP端口8888。Mac用户需检查“系统偏好设置→网络→高级→代理”确保Web代理HTTP和安全Web代理HTTPS均指向127.0.0.1:8888仅本地调试用手机抓包不用此设置。SSL Proxying启用这是抓HTTPS的核心开关。在Charles菜单栏Proxy → SSL Proxying Settings → Add → 输入目标域名如api.example.com和端口443。支持通配符*.example.com:443。关键细节若目标App使用SNIServer Name Indication必须勾选“Enable SSL Proxying for all hosts”或精确匹配SNI域名否则Charles无法解密。证书导出与安装Charles证书需以.pem格式导出Help → SSL Proxying → Save Charles Root Certificate…。手机端安装路径浏览器访问chls.pro/ssl→ 下载证书 → 设置→安全→加密与凭据→安装证书。Android 10要求证书文件名不含空格建议重命名为charles.pem再安装。实操心得chls.pro/ssl在部分国内网络环境下可能加载缓慢此时可将.pem文件通过微信/QQ发送到手机用文件管理器直接点击安装。切勿用截图二维码方式Base64编码易出错。4.2 手机端网络配置Wi-Fi代理与DNS注意事项Wi-Fi代理设置手机Wi-Fi设置中长按当前网络→修改网络→高级选项→代理→手动输入电脑IP如192.168.1.100和端口8888。致命错误很多人填错IP以为是手机自己的IP其实是电脑的局域网IP。用ipconfigWindows或ifconfigMac确认电脑IP而非手机IP。DNS污染规避某些运营商DNS会劫持chls.pro域名导致chls.pro/ssl无法访问。解决方案在手机Wi-Fi设置中将DNS改为114.114.114.114或8.8.8.8。更彻底的方法是在Charles的Proxy → Proxy Settings → DNS Resolution中勾选“Resolve DNS through client”让Charles通过手机DNS解析域名避免电脑DNS干扰。4.3 抓包过程中的实时监控与过滤技巧实时过滤Charles左侧结构树默认显示所有请求。按CmdFMac或CtrlFWin调出搜索框输入域名关键词如login快速定位。右键请求→Breakpoints可设置断点修改请求头或响应体后再放行用于测试Header注入或Mock数据。隐藏无关流量大量系统更新、推送服务如fcm.googleapis.com会刷屏。在Structure视图右键→Hide by Hostname输入googleapis.com、apple.com等一键过滤。也可在Filter栏输入!googleapis !apple感叹号表示排除。性能分析右键请求→Response Time Graph查看各阶段耗时DNS、Connect、SSL、Send、Wait、Receive。若SSL时间异常长1s说明证书验证失败需检查network_security_config或证书安装状态。实操心得我习惯在抓包前先清空Charles历史记录Edit → Clear History再开启“Recording”开关。这样能确保看到的是纯净的本次操作流量避免历史缓存干扰判断。5. 常见问题与排查技巧实录从报错信息反推故障点5.1 典型报错速查表报错现象根本原因解决方案Charles无任何请求手机网页能打开手机Wi-Fi代理未生效检查手机IP是否填错电脑IP确认Charles Proxy Settings中“Enable transparent HTTP proxying”已勾选HTTPS请求显示“Unknown”或“Failed”SSL Proxying未启用或域名不匹配Proxy → SSL Proxying Settings → Add精确域名确认Charles证书已安装且未过期App报“网络异常”、“SSL Handshake Failed”network_security_config禁止用户证书采用方案A反编译加certificates srcuser /或方案BADB命令chls.pro/ssl无法访问DNS劫持或网络限制修改手机DNS为114.114.114.114或用电脑导出.pem文件手动安装抓到HTTP但抓不到HTTPSCharles未开启SSL ProxyingProxy → SSL Proxying → Enable SSL ProxyingAndroid 11证书安装后仍不生效用户证书被系统降级执行adb shell setprop persist.security.user_certs.enabled 1并重启5.2 深度排查三步法第一步确认代理链路通畅在手机浏览器访问http://httpbin.org/ip返回的IP应为电脑IP如192.168.1.100。若返回手机自身IP说明代理未生效检查Wi-Fi代理设置。第二步验证证书信任链在Charles中右键任意HTTPS请求→Export → Export SSL Session Keys。用Wireshark打开导出的.keys文件若能成功解密TLS流量证明证书链完整若提示“Private key not found”说明Charles未正确持有私钥需重新生成证书Help → SSL Proxying → Install Charles Root Certificate in Windows/Mac。第三步日志交叉验证在手机端开启开发者选项→USB调试执行adb logcat | grep -i ssl\|certificate。若看到TrustManagerImpl: No valid cert path证实是证书信任问题若看到OkHttpClient: Connection refused则是代理端口不通。实操心得我遇到过一次诡异问题——Charles显示请求但响应体为空。最终发现是App用了OkHttp的cacheControl强制缓存而Charles默认不缓存。解决方案Charles菜单栏Tools → Rewrite → Add Rule → Action Type设为“Set Header”Header Name填Cache-ControlValue填no-cacheApply to所有请求。5.3 各Android版本特有问题汇总Android 7-8Nougat/Oreonetwork_security_config首次引入但certificates srcuser /支持稳定。主要坑点是证书安装后需重启App否则不生效。Android 9Pie引入android:usesCleartextTrafficfalse默认值HTTP请求会被拦截。需在Manifest中显式声明android:usesCleartextTraffictrue才能抓HTTP。Android 10Q用户证书默认仅对debuggable App生效。必须用ADB命令或修改build.gradle。Android 11R移除了user_certificate_enabled系统属性setprop命令失效。推荐VirtualXposed或Magisk模块。Android 12S/T/U强制执行android:exportedtrue对BroadcastReceiver的要求部分抓包工具依赖的广播被禁用。此时Charles仍是少数不受影响的方案。我个人在实际调试中发现最省心的组合是Android 10以下用方案A反编译Android 10-11用方案BADBAndroid 12直接上VirtualXposed。这套组合拳覆盖了95%的现网机型比盲目升级Charles版本或换抓包工具高效得多。最后再分享一个小技巧把Charles的Proxy Settings导出为JSON备份每次重装系统后一键导入省去重复配置的3分钟——这3分钟够你喝半杯咖啡了。
返回列表