当前位置: 首页 > news >正文

iOS HTTPS抓包全链路指南:从Charles配置到SSL Pinning绕过

1. 为什么iOS HTTPS抓包比安卓难得多?——从SSL Pinning到系统证书信任链的硬门槛

很多人第一次在Mac上打开Charles,连上iPhone,点开App发现一片空白:没有请求、没有响应、全是unknown。不是Charles坏了,也不是手机没连上Wi-Fi,而是iOS从2017年iOS 10.3开始,把HTTPS流量的“可调试性”变成了一个需要主动解锁的权限开关。这背后是一整套安全机制的叠加:TLS协议本身的加密特性、iOS对证书颁发机构(CA)的严格白名单管理、以及越来越多App内置的SSL Pinning(证书固定)逻辑。简单说,Charles要看到HTTPS内容,必须先让iOS相信它发的证书是“自己人”,而这个“自己人”的身份认证,不是点几下就能完成的——它需要你手动安装证书、手动开启完全信任、手动关闭App的证书校验逻辑,三步缺一不可。

核心关键词就藏在这句话里:Charles、iOS HTTPS抓包、Mac代理配置、手机代理设置、SSL Pinning绕过、根证书信任配置。这不是一个“装个软件就能用”的功能,而是一次对iOS底层网络信任模型的实操解构。适合谁?适合做iOS客户端测试的QA工程师、负责接口联调的前端/后端开发、需要分析竞品App网络行为的产品经理,以及所有想真正看懂自己App和服务器之间“说了什么”的技术同学。它解决的不是“能不能抓到包”,而是“能不能看清加密层下的真实请求路径、参数结构、响应体格式、Header字段含义”。没有这一步,你看到的只是TCP连接建立与断开,而不是业务逻辑的完整流转。

我第一次在项目里用Charles定位一个登录态失效问题,卡了整整两天。App在模拟器里一切正常,真机上却总在第三步跳转时返回401。抓不到HTTPS流量,就只能靠猜:是Token没传?是Header写错了?还是服务端做了设备指纹校验?直到我把证书信任链理清楚,才发现在iOS 15.4之后,系统默认不信任用户安装的根证书,哪怕你双击安装了,它也只停留在“已安装”状态,而非“已信任”。这个细节,官方文档没写,Charles官网教程只提了一句“前往设置→通用→关于本机→证书信任设置”,但没告诉你——那个开关在iOS 14之后被移到了“设置→通用→VPN与设备管理→证书信任设置”里,而且必须手动滑动开启。这种“看似简单、实则致命”的细节,正是本文要帮你踩平的全部坑。

2. Mac端Charles配置:不只是监听端口,关键是代理策略与SSL Proxying的精准控制

Charles本身是个跨平台工具,但Mac版有其不可替代的优势:它能直接读取macOS钥匙串中的证书信息,能无缝集成Safari开发者工具,更重要的是,它对macOS网络栈的兼容性远高于Windows虚拟机或Linux Wine环境。所以,我们不讲Windows或Linux方案,只聚焦Mac原生配置。这不是“下载→安装→打开”三步走,而是一套需要理解每一步意图的代理策略配置。

2.1 安装与基础监听设置:别急着配手机,先让Charles“活”起来

首先确认你使用的是Charles 4.6.2或更高版本(截至2024年Q2最新稳定版)。低版本对iOS 16+的TLS 1.3支持不完整,会导致部分HTTPS请求无法解密。安装完成后,首次启动会提示你输入许可证——可以先跳过试用,但务必注意:免费版有30分钟自动断连限制,对于长时间调试Session或复现偶发问题极不友好。建议团队统一采购正版授权,单台Mac约$50/年,远低于一次线上Bug排查所耗工时。

打开Charles后,默认监听端口是8888。这个数字不是随便定的:它避开了系统常用端口(80/443/3000/8080),又足够靠前便于记忆。你可以在Proxy → Proxy Settings中修改,但除非你本地有其他服务占用了8888,否则不建议改。重点在于勾选两项:

  • Enable transparent HTTP proxying:启用透明HTTP代理,这是所有HTTP明文流量的基础。
  • Enable SSL proxying:这是HTTPS解密的核心开关,但此时它还不能工作——因为iOS还没信任Charles的根证书。

提示:不要在Proxy Settings里勾选“Use external proxy server”,那是给Charles自身再套一层代理用的,普通调试场景完全不需要,反而容易引发环路或超时。

2.2 SSL Proxying规则配置:为什么全局代理会失败?——按域名精确匹配才是王道

很多新手习惯在Proxy → SSL Proxying Settings里直接点击“Enable SSL Proxying”,然后在下方列表里点“Add”,填入**,以为这样就能抓全所有HTTPS流量。结果是:大部分App依然显示unknown,只有少数几个网站(如apple.com)能解密。原因很简单:*通配符在SSL Proxying中代表“所有域名”,但iOS App发起的HTTPS请求,其SNI(Server Name Indication)扩展字段往往携带的是IP地址或内网域名(如api.internal.company),而Charles的SSL Proxying规则是基于SNI字段匹配的,不是基于DNS解析后的IP。更关键的是,现代App普遍采用多域名架构:主域名走CDN,图片走OSS,埋点走独立统计域名,登录走OAuth专用域。用*只会让Charles对所有SNI尝试解密,而一旦目标服务器不支持TLS重协商或拒绝非标准Client Hello,连接就会直接中断。

正确的做法是按需添加、逐个验证。例如,你要调试微信读书的书架刷新逻辑,先用Wireshark或nmap粗略扫一下它可能访问的域名:

# 在Mac终端执行(需提前安装nmap) nmap -sS -p 443 --script ssl-cert bookdou.com

实际中更高效的方式是:先用Charles开启HTTP代理(不启SSL),在iOS Safari里打开该App的Web版,观察哪些域名在HTTP列表里频繁出现,再将这些域名逐条加入SSL Proxying列表。格式必须是:

  • Location:bookdou.com(不能带https://,不能带端口)
  • Port:443(HTTPS默认端口,除非App明确指定其他端口如8443)

每加一条,保存后重启Charles代理(Proxy → Stop Proxying → Start Proxying),再在手机上触发一次对应操作。你会发现,加了bookdou.com后,书架API的GET /v2/shelf请求终于显示为绿色(已解密),而img.bookdou.com仍为灰色(未解密),这时再补上这一条。这个过程不是机械劳动,而是对App网络架构的一次逆向梳理。

2.3 隐藏但关键的三项进阶配置:Throttling、Breakpoints与Sequence

很多用户以为抓到包就结束了,其实Charles真正的价值在后续分析。这里有三个常被忽略、但每天都在救我命的功能:

① Network Throttling(网络限速)
位置:Proxy → Network Conditions
作用:模拟2G/3G/4G弱网环境。iOS Simulator自带的Network Link Conditioner只能影响模拟器,对真机无效;而Charles的Throttling是代理层实现的,对所有经由它的流量生效。我曾用它复现一个“图片加载失败但无错误提示”的Bug:在4G模式下一切正常,在3G模式下,App因超时未收到图片CDN的302重定向,直接fallback到默认图,而日志里没有任何timeout记录。这个现象在正常网速下根本无法触发。

② Breakpoints(断点调试)
位置:Proxy → Breakpoint Settings
作用:在请求发出前或响应返回后暂停,允许你手动修改Request Header、Body,或篡改Response Status Code、JSON内容。比如你想测试“服务器返回503时App是否展示维护页”,只需设置Breakpoint匹配/api/maintenance,当响应到达时,把200 OK改成503 Service Unavailable,再点击“Execute”发送出去。这比改服务端代码快十倍。

② Sequence(请求序列化)
位置:右键某条请求 →Sequence
作用:将一组关联请求(如登录→获取Token→调用受保护接口)保存为可重复执行的脚本。特别适合回归测试:每次发版前,用Sequence一键重放10个核心业务流,对比响应体哈希值是否一致。比写Postman脚本轻量,比人工点击可靠。

3. iOS端代理配置:从Wi-Fi设置到证书信任,每一步都决定成败

Mac端配置再完美,只要iOS端漏掉一个环节,整个HTTPS抓包链路就彻底断裂。这不是“设置→Wi-Fi→详情→代理→手动”这么简单,而是一场涉及系统级证书信任、App沙盒隔离、以及iOS隐私策略的精密操作。尤其要注意:iOS 15.2之后,苹果彻底移除了“设置→通用→关于本机→证书信任设置”入口,新路径必须牢记。

3.1 Wi-Fi代理设置:为什么“手动”比“自动”更可靠?

进入iPhone设置 → Wi-Fi,点击当前连接的网络右侧的ⓘ图标,下滑找到HTTP代理。这里有两个选项:

  • 自动:需填写一个PAC(Proxy Auto-Config)文件URL,如http://192.168.1.100:8080/proxy.pac。这种方式适合企业内网批量部署,但要求你额外搭建一个Web服务来托管PAC文件,对个人调试纯属增加复杂度。
  • 手动:这才是我们的选择。填写:
    • 服务器:填Mac的局域网IP(不是127.0.0.1!),通过Mac终端执行ifconfig | grep "inet " | grep -v 127.0.0.1获取,通常是192.168.x.x10.0.x.x
    • 端口:填Charles中设置的代理端口(默认8888)。
    • 认证:保持关闭。除非你主动在Charles中设置了Proxy Authentication(不推荐,会增加调试干扰)。

注意:Mac和iPhone必须在同一局域网下。如果你用的是MacBook的个人热点,iPhone连热点时,Mac的IP会变成192.168.2.1,此时需在Charles中确认监听地址是否包含该网段(Proxy → Proxy Settings → Local IP Address → 勾选“Allow remote connections”并确认IP正确)。

填完后,回到Wi-Fi列表,你会看到当前网络名称右侧多了一个小蓝点,表示代理已启用。此时打开Safari访问任意HTTPS网站(如baidu.com),如果Charles里出现绿色的baidu.com请求,说明HTTP代理通了;如果仍是灰色,检查Mac防火墙是否阻止了8888端口(系统偏好设置→安全性与隐私→防火墙→防火墙选项→勾选“Charles Proxy”)。

3.2 根证书安装与完全信任:iOS 14+之后的“双重认证”陷阱

这是整个流程中最容易卡住的环节。步骤看似简单,实则暗藏两重关卡:

第一重:安装证书
在iPhone Safari中访问chls.pro/ssl(Charles官方证书下载地址)。页面会提示“已下载描述文件”,点击右上角“安装”→输入锁屏密码→“安装”→“完成”。此时证书已存入系统,但并未启用

第二重:开启完全信任(iOS 14+专属难点)
路径已变更多次,当前(iOS 16.6)正确路径是:
设置 → 已下载的描述文件 → 点击“Charles Proxy CA” → 安装 → 输入密码 → 完成
然后必须再进:设置 → 通用 → VPN与设备管理 → 证书信任设置 → 找到“Charles Proxy CA” → 右侧开关滑动开启

为什么需要两步?因为iOS将“证书安装”和“证书信任”拆分为两个独立权限。第一步只是把证书放进钥匙串,第二步才是授予它“作为根证书签发其他证书”的权力。如果你只做完第一步,Charles生成的中间证书(用于代理bookdou.com)会被iOS视为“不受信任”,导致TLS握手失败,App直接报错“无法连接到服务器”。

提示:开启信任后,系统会弹出警告“启用此根证书可能会使您的设备面临安全风险”。这是正常提示,点击“继续”即可。它不是Bug,而是iOS对用户主动降低安全等级的强制确认。

3.3 绕过SSL Pinning:当App拒绝信任Charles证书时的终极方案

即使你完成了以上所有步骤,仍有大量App(如银行类、支付类、社交类)显示SSL handshake failedUnknown。这不是配置错误,而是App代码里写了SSL Pinning——它不信任任何系统证书,只认自己预埋在Bundle里的公钥哈希。此时,Charles的根证书再可信也没用。

解决方案分三级,按侵入性递增:

① 最轻量:使用支持Pinning绕过的Charles插件
Charles官方市场提供SSL Kill Switch 2插件(需单独下载),它通过动态注入方式hook iOS底层Security框架,拦截SecTrustEvaluate调用并返回true。安装后,在Charles菜单栏出现Tools → SSL Kill Switch,勾选启用即可。优点:无需越狱、无需重签名、对App零修改。缺点:仅支持ARM64设备(iPhone 5s及以后),且部分加固App(如腾讯御安全)会检测此类hook并闪退。

② 中等:重签名App + 替换Info.plist
适用于你有App的IPA包(非App Store下载版)。用codesign工具重签名,并在Info.plist中添加:

<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

这会强制App允许所有HTTP/HTTPS请求,绕过ATS(App Transport Security)限制。但注意:这只能解决ATS,不能解决代码层的SSL Pinning。需配合Frida脚本进一步hook。

③ 终极:Frida动态Hook(需越狱或支持Jailbreak-free的设备)
编写Frida脚本,hook常见的Pin方法:

  • NSURLSessionDelegateurlSession:didReceiveChallenge:completionHandler:
  • AFSecurityPolicyevaluateServerTrust:forDomain:
  • 自定义TrustEvaluator类的isValidCertificate:方法
    脚本核心逻辑是:当检测到Charles证书时,直接返回YES。这是最通用的方案,但要求你熟悉Objective-C/Swift运行时,且需在越狱设备或支持frida-ios-dump的非越狱设备上运行。

我日常用的是方案①+方案③组合:先用SSL Kill Switch 2快速验证,若失败,则用Frida针对性hook。记住:没有银弹,每个App的防护强度不同,你的调试策略也必须分层应对。

4. 实战排错链路:从“一片灰色”到“满屏绿色”的完整诊断手册

当Charles里全是灰色unknown,而你确信Mac和iPhone都配好了,别急着重装软件。请按以下顺序,像修车师傅一样逐段检查信号链路。这不是玄学,而是基于TCP/IP和TLS协议栈的标准化排查。

4.1 第一层:网络连通性验证——确认数据真的流到了Charles

打开Mac终端,执行:

# 查看Charles是否在监听8888端口 lsof -i :8888 # 正常应返回类似:charles 12345 user 21u IPv4 0x... 0t0 TCP *:http-alt (LISTEN) # 检查iPhone能否ping通Mac # 在iPhone上安装“Network Analyzer”App,输入Mac的IP,执行Ping # 或在Mac上执行:sudo tcpdump -i en0 port 8888 -w debug.pcap,然后在iPhone上打开App,等待10秒后Ctrl+C停止,用Wireshark打开debug.pcap查看是否有来自iPhone IP的SYN包

如果lsof无输出,说明Charles没启动或端口被占;如果tcpdump里看不到iPhone的SYN包,说明Wi-Fi代理根本没生效——回到第3.1节重新检查iPhone的代理设置。

4.2 第二层:证书链验证——用OpenSSL直连Charles中间证书

这是最常被跳过的一步,但它能10秒定位90%的证书问题。在Mac终端执行:

# 替换为你的iPhone IP和Charles端口 openssl s_client -connect 192.168.1.101:8888 -servername bookdou.com -showcerts

观察输出:

  • 如果返回CONNECTED(00000003)但紧接着是verify error:num=20:unable to get local issuer certificate,说明iPhone没信任Charles根证书;
  • 如果返回verify return:1但最后是Verify return code: 0 (ok),说明证书链完整,问题出在App层(如SSL Pinning);
  • 如果卡在CONNECTED后无响应,说明Charles的SSL Proxying规则没匹配到该域名,检查第2.2节的配置。

技巧:把bookdou.com换成你App实际请求的域名,确保SNI字段一致。很多App用IP直连,此时需用-servername指定SNI,否则OpenSSL会发送空SNI,Charles无法生成对应中间证书。

4.3 第三层:Charles日志与事件面板——读懂它的“抱怨”

Charles顶部菜单栏有个隐藏利器:View → Event Log。它会实时记录所有代理事件,包括:

  • SSL handshake failed for bookdou.com:443→ 证书问题或SSL Pinning
  • Connection refused by server→ 目标服务器拒绝Charles的代理连接(常见于内网服务)
  • Request timed out→ 网络延迟过高或Charles处理不过来(调高Proxy → SSL Proxying Settings → Timeout值)

更关键的是Structure面板:右键某个unknown请求 →Copy → cURL Command,然后在终端粘贴执行。如果cURL能成功返回JSON,说明Charles代理本身没问题,问题一定在iOS端(如证书未信任或App沙盒限制);如果cURL也失败,则是Charles配置或网络问题。

4.4 第四层:App沙盒与ATS例外域——那些被iOS悄悄拦截的请求

iOS 9引入的ATS(App Transport Security)默认禁止HTTP和不安全的HTTPS(如SHA1签名、弱加密套件)。即使你开了NSAllowsArbitraryLoads,某些系统级API(如UIActivityViewController分享)仍会强制ATS。此时,Charles里会出现Failed to connect to host,但Event Log里无记录。

解决方案是:在App的Info.plist中精确声明例外域,而非全局放开:

<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>bookdou.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSTemporaryExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>

这告诉iOS:“只对bookdou.com及其子域名放宽限制,其他域名仍走严格ATS”。既满足调试需求,又不降低整体安全性。这个配置必须由iOS开发同学添加并重新编译,无法通过Charles远程修改。

5. 进阶技巧与长期维护:如何让Charles成为你iOS调试的“呼吸般自然”的存在

配置完成只是起点,真正让Charles融入日常开发节奏,需要一套可持续的维护习惯和几个“偷懒”技巧。这些不是官方文档里的内容,而是我在三年间调试过200+个iOS App后沉淀下来的肌肉记忆。

5.1 一键切换:为不同项目创建独立的Charles配置集

你不会只为一个App调试。今天调电商,明天调金融,后天调内部OA,每个App的域名、证书策略、甚至是否启用SSL Kill Switch都不同。手动来回切换配置极易出错。Charles支持配置集(Configuration Set):

  • File → Save Session As:将当前所有请求、过滤规则、SSL Proxying列表保存为.chls文件,如taobao.chlswechat-pay.chls
  • File → Load Session:下次打开直接加载,所有设置还原。
  • 更进一步:用Tools → Repeatable Requests将高频调试请求(如登录、刷新Token)保存为可一键重放的集合,命名如Login Flow - Taobao

我桌面有一个Charles-Configs文件夹,里面按项目分类存放配置,配合Alfred快速搜索,3秒内切到目标环境。

5.2 过滤与高亮:从千条请求中秒杀目标流量

Charles默认显示所有流量,包括系统更新、iCloud同步、后台推送。一个典型App启动过程会产生200+请求,其中真正属于业务逻辑的可能只有5条。学会过滤是效率分水岭:

  • 结构化过滤:右键左侧Structure面板 →Focus on Domain→ 输入bookdou.com,只显示该域名请求。
  • 正则高亮View → Highlighting → Add Rule,创建规则如Path contains "/v2/shelf",匹配的请求行背景变黄。
  • 自定义列:右键请求列表标题栏 →Customize Columns,勾选Status CodeContent-TypeTime,让关键信息一目了然。

经验:永远开启Status Code列。我曾靠一眼扫出429 Too Many Requests,才发现是测试账号被风控,而非接口Bug。

5.3 与Xcode协同:当Charles遇上Swift断点调试

Charles不是替代Xcode调试器,而是它的超级外挂。两者结合能形成闭环:

  • 在Xcode中设断点,停在URLSession.shared.dataTask创建处,复制request.url?.absoluteString
  • 切到Charles,用Cmd+F搜索该URL,立刻定位到完整请求/响应;
  • 在Charles中右键该请求 →Copy → cURL Command,粘贴到终端,用curl -v查看详细TLS握手过程;
  • 若需修改请求体,用Charles的Breakpoint暂停,Xcode中修改变量值,再继续执行。

这种“Xcode看逻辑,Charles看数据”的分工,让我定位一个OAuth2.0 Token刷新失败问题,从半天缩短到15分钟。

5.4 安全边界提醒:为什么你不该在办公网长期开启Charles代理

最后,一个严肃但常被忽视的提醒:Charles是一个全流量代理,它能看到你手机上所有App的明文请求,包括微信聊天记录(如果对方服务器没做端到端加密)、邮箱密码、甚至银行验证码。因此:

  • ✅ 只在调试时开启,调试结束立即关闭iPhone代理;
  • ✅ 绝不在公司Wi-Fi下对非测试App开启SSL Proxying;
  • ✅ 不将Charles证书安装到主力机,专机专用(如一台旧iPhone 8专用于调试);
  • ✅ 定期清理Charles的History(右键 → Clear History),避免敏感数据残留。

这不是 paranoia,而是职业基本素养。我见过同事因在咖啡馆连公共Wi-Fi时忘了关Charles,导致测试用的支付宝沙箱账号密钥被截获。技术是把双刃剑,用得好是生产力,用得莽撞就是风险源。

我在实际使用中发现,最高效的调试节奏是:每天早上花5分钟加载项目专属配置集,用Sequence跑一遍核心流程确认环境正常,然后全程开着Charles,让所有网络请求像呼吸一样自然流过。当Bug出现时,我不再问“是不是后端的问题”,而是直接打开Charles,输入关键词,3秒内锁定请求,10秒内对比前后端日志。这种确定性,是任何文档和会议都无法替代的。

http://www.cnnetsun.cn/news/2550103.html

相关文章:

  • 不止于播放:用VideoPlayer脚本控制实现一个简易的Unity视频播放器UI
  • CVE-2023-51767深度复现:acme.sh DNS TXT解析RCE漏洞剖析
  • 渗透测试入门实战:从信息收集到权限提升的完整链路
  • 开源社区贡献者画像分析:核心与外围贡献者的行为差异与影响
  • 时间序列预测实战:从LightGBM到GNN与强化学习的算法选型指南
  • Unity银河战士类游戏开发:状态机、关卡拓扑与Boss行为树实战
  • 【表达式】JAVA解析数学表达式 parsii 计算数学公式 表达式规则引擎 动态脚本语言
  • vue-axios-github解密:5分钟理解axios拦截器实现请求/响应统一处理
  • 如何快速部署PostgreSQL数据建模工具:跨平台完整安装教程
  • 戴森球计划FactoryBluePrints:构建星际工厂的终极蓝图库
  • 零基础也能创作视觉小说:WebGAL引擎3分钟快速上手指南
  • FIFA 23生涯模式终极修改指南:免费开源工具打造完美足球世界
  • MPC Video Renderer:开源视频渲染器的完整安装与配置终极指南
  • 告别杂乱!用FileMenu Tools 8.4.2一键清理Windows 11右键菜单,附赠我的常用命令清单
  • WinFsp深度解析:如何在Windows上轻松构建用户空间文件系统
  • 如何高效使用Python SoundCloud下载器:打造个人音乐库的完整指南
  • NexoPOS用户指南:从小白到专家的10个实用技巧
  • 5分钟上手!Linux用户必备的Apple Emoji字体安装教程
  • JWT令牌机制完全指南
  • Keil MDK优化级别设置与嵌入式开发性能调优
  • ViVeTool-GUI专业指南:解锁Windows隐藏功能的智能方案
  • 别再踩坑了!Ubuntu 22.04 上编译 Mbedtls 3.6 的完整避坑指南(附 Python 依赖解决)
  • 告别虚拟机!保姆级教程:在Win11上用WSL2+Ubuntu 22.04跑起你的第一个Linux桌面
  • 《Java 100 天进阶之路》第12篇:Java对象、类、抽象类、构造方法
  • 机器学习数据集详解,公开免费数据集获取渠道汇总
  • 从零构建通用关系数据库系统:总体设计方案
  • 2026电工杯数学建模竞赛A题论文、代码、数据(改进)
  • 2026保姆级免费去图片水印教程,这4款微信小程序一键搞定
  • VMware虚拟机里装FydeOS,给旧电脑或MacBook找个轻量‘副系统’
  • Unity新手村:用Terrain工具5分钟搭出你的第一个3D场景(含环境包导入)