Skip to content

iOS 证书解密与 MitM 脚本重写规则集群 ​

集群导读与技术定位

欢迎查阅 iOS 证书解密与 MitM 脚本重写规则集群。本集群隶属于 Shadowrocket 小火箭 iOS 移动端深度排障与进阶架构专题,是苹果移动生态下实现七层流量可观测性、应用层报文篡改、去广告以及高级重写调优的核心三级枢纽。 在现代互联网中,超过 98% 的流量均由 TLS 加密保护。若要在移动端实现拦截应用内开屏广告、解锁流媒体特定功能或监控 HTTP 请求体,客户端必须扮演中间人(Man-in-the-Middle, MitM)角色动态解密 HTTPS 数据流。然而,这一高级特性直接触碰了苹果系统最敏感的安全防线:证书信任链断裂引发全网报废、SSL Pinning 证书固定导致金融网银闪退、以及 JavaScript 脚本在解析超大响应体时瞬间踩中 15MB 内存死刑线(Jetsam 强杀)。本集群旨在系统化攻坚这些深水区难题,指导工程师构筑安全、稳定且轻量的高级重写流水线。


模块一:中间人(MitM)解密与动态证书签发底层时序流 ​

为了理清小火箭在解密 HTTPS 流量时的微观行为,必须深入剖析操作系统、本地虚拟网卡与远端目标服务器之间的三次握手与证书置换流程:

+─────────────────────────────────────────────────────────────────────────────+
|               Shadowrocket 本地 MitM 中间人解密与证书置换时序流              |
+─────────────────────────────────────────────────────────────────────────────+
[客户端应用: 浏览器 / App]                      [小火箭后台扩展 (utun 网卡)]                    [真实目标服务器]
       │                                            │                                            │
       ├─► 1. 发起 TCP 握手与 TLS Client Hello ────►│                                            │
       │     (请求目标: api.target.com)             │                                            │
       │                                            ├─► 2. 与目标服务器建立原生 TLS 握手 ───────►│
       │                                            │◄─ 3. 接收目标服务器真实证书与密码协商 ─────┤
       │                                            │                                            │
       │                                            ├── [核心中间人介入: 动态伪造证书]           │
       │                                            │   - 读取本地内置的私有 CA 根证书私钥       │
       │                                            │   - 动态签发属于 api.target.com 的伪造证书 │
       │                                            │                                            │
       │◄─ 4. 向 App 返回伪造的服务器证书与协商 ────┤                                            │
       │                                            │                                            │
       ├── [关键关卡: iOS 系统信任链校验]           │                                            │
       │   - 校验该伪造证书的签发者 (Issuer)        │                                            │
       │   - 是否在系统「证书信任设置」中完全信任? │                                            │
       │     ├── [已完全信任] ──► 握手成功!        │                                            │
       │     └── [未开启信任] ──► 报错 SSL 终止!   │                                            │
       │                                            │                                            │
       ├─► 5. 发送密文 HTTP 请求 (GET /api/v1) ─────►│ (小火箭本地解密为明文 HTTP 报文)           │
       │                                            │   - 执行 URL Rewrite 规则匹配              │
       │                                            │   - 调用 JavaScript 引擎修改请求头/响应体  │
       │                                            │                                            │
       │                                            ├─► 6. 重新以原生 TLS 发往真实服务器 ────────►│
       │                                            │◄─ 7. 接收真实响应 ─────────────────────────┤
       │                                            │   - 脚本修改响应内容 (如剔除广告 JSON)     │
       │◄─ 8. 重新加密并返回修改后的响应数据 ───────┤                                            │

1. 动态伪造证书(Dynamic Impersonation)的物理本质 ​

当开启 MitM 并在配置文件中添加了 hostname = *.example.com 后:

  • 小火箭在拦截到发往 example.com 的 TLS 握手请求时,并不会将握手透传给真实服务器;
  • 它利用本地生成的 私有根证书(Root CA),在 iPhone 内存中动态实时生成一张属于 *.example.com 的 X.509 数字证书,并用私有 CA 私钥完成数字签名;
  • 如果系统已经将该私有 CA 设为“完全受信任的根证书”,iOS 网络框架 Security.framework 会判定该动态证书完全合法,从而完成 TLS 建立;
  • 小火箭由此获得了在内存中读取和篡改明文 HTTP 请求体与响应体的特权。

2. 为什么开启 MitM 会带来系统级断网风险? ​

  • 如果用户生成了 CA 根证书,但未在系统“关于本机”中勾选“完全信任”;
  • 此时发往所有被 MitM 匹配的域名的 HTTPS 请求,在第一步验证证书签名时就会被系统安全机制直接拦截,报出 kSecTrustResultFatalTrustFailure 错误;
  • 在用户手机上,表现为只要打开该网站就提示“证书无效”、“网络连接被重置”,彻底断网!

模块二:本集群下辖核心攻坚学术长文矩阵 ​

本集群为苹果生态高级用户提供两篇覆盖实操安装与高级重写脚本编写的工业级攻坚指南:

页面标识与文献标题路径索引核心技术攻坚突破点适用排查场景
PAGE-CLI-014
Shadowrocket CA 根证书生成与 iOS 系统信任链断裂排查:SSL Handshake Failed 与网页证书不受信任根治实战
docs/clients/shadowrocket/mitm-rewrite/mitm-ca-certificate-trust-chain-troubleshooting.md- X.509 v3 根证书生成核心参数(cA:TRUE, KeyUsage)
- iOS 10.3+ 双层证书授权标准操作全流程
- SSL Pinning 证书固定机理与网银/微信安全豁免
- 证书过期与系统时间偏差诱发的握手崩溃自救
开启 MitM 后所有网站报证书不受信任;微信/支付宝无法使用;Safari 提示此连接非专用
PAGE-CLI-015
Shadowrocket URL Rewrite 与 JavaScript 脚本重写进阶指南:广告拦截、响应头修改与 15MB 内存崩溃防范
docs/clients/shadowrocket/mitm-rewrite/url-rewrite-script-rule-syntax-guide.md- 302/307 重定向、Header 覆写与 Reject 语法
- script-response-body 报文解密篡改生命周期
- 15MB Jetsam 内存溢出机制与轻量化流式处理
- Gzip/Brotli 压缩解压导致内存爆炸的物理防范
开启去广告脚本后小火箭瞬间闪退;状态栏 VPN 图标无故消失;脚本重写不生效

模块三:iOS MitM 与脚本重写四大工程陷阱与避坑全景 ​

在实际配置小火箭 MitM 功能时,稍有不慎就会引发系统级崩溃。以下四大陷阱是工程师排查时的核心考点:

陷阱 1:主机名泛通配符(* 或 *.com)灾难 ​

某些新手为了省事,在 [MITM] 配置中将解密主机名直接设定为 hostname = * 或 hostname = *.com。

  • 灾难后果:小火箭会尝试对 iPhone 上产生的所有 HTTPS 连接发起中间人解密,包含 Apple 系统更新、iCloud 同步、微信支付以及手机银行 App;
  • 这些敏感核心应用普遍内置了 SSL Pinning(证书公钥固定) 机制,它们拒绝信任系统根证书库,仅信任 App 编译时硬编码的官方公钥;
  • 一旦检测到证书被小火箭替换,网银和微信会立即终止连接并直接弹窗报警,导致整台 iPhone 核心功能全面瘫痪!
  • 防御准则:严禁使用全局通配符,必须且仅能将明确需要重写解密的特定子域名(如 api.example.com)填入主机名列表。

陷阱 2:超大 JSON 响应体导致 15MB Jetsam 秒杀 ​

在编写 JavaScript 响应体修改脚本(script-response-body)时,部分视频 App 或社交软件返回的单条 JSON 响应数据超过 8MB。

  • 小火箭在执行脚本时,首先需要将压缩的 gzip 响应体在内存中解压,再解析为 JS 对象(JSON.parse);
  • 这一连串操作需要开辟相当于原始数据体积 3 到 5 倍的连续内存空间;
  • 在 iOS 强加给小火箭扩展进程的 15MB 常驻内存上限 面前,扩展内存瞬间打满;
  • iOS 内核在微秒级时间内执行 Jetsam 查杀,导致 VPN 瞬间闪退断开。

陷阱 3:HTTP/2 多路复用流失步 ​

现代网站普遍启用了 HTTP/2 协议,在单条 TCP 连接上并发复用数百个虚拟流(Stream)。

  • 若小火箭的脚本重写引擎在处理某一个特定的 Stream 时出现执行耗时过长或未正确返回响应(没有显式调用 $done());
  • 将导致该 TCP 连接上的后续所有 Stream 发生队列阻塞或时钟超时(Stream Desynchronization);
  • 表现为网页加载一半后卡死,部分图片无法显示。

陷阱 4:系统时间偏差超 90 秒引发证书不可逆作废 ​

数字证书的有效性严格依赖两组时间戳:Not Before(生效时间)与 Not After(过期时间)。

  • 当小火箭动态生成证书时,使用的是当前 iPhone 的系统时间;
  • 如果手机本地时间由于越狱插件或手动修改,与国际标准时间偏差超过 90 秒;
  • 目标服务器或 iOS 验证机制会判定该证书“尚未生效”或“已经过期”,瞬间抛出 certificate is not yet valid 握手异常。

模块四:常见高频应用 MitM 安全豁免与解密合规对照表 ​

下表汇集了移动端日常最高频应用的 MitM 解密风险分级与推荐策略:

应用程序名称典型核心域名MitM 解密策略风险评级与强制避坑指导
Apple 系统服务*.apple.com, *.icloud.com绝对严禁解密 (Pass-Through)极高风险:触发 SSL Pinning,导致 App Store 与 iCloud 彻底瘫痪
手机银行 / 支付宝*.alipay.com, *.cmbchina.com绝对严禁解密 (Pass-Through)极高风险:触发金融反欺诈,账号被风控锁定或强制要求人脸核验
微信 (WeChat)*.wechat.com, *.qpic.cn绝对严禁解密 (Pass-Through)极高风险:长连接中断,朋友圈打不开,微信支付报系统错误
Google 服务框架*.googleapis.com, *.google.com谨慎解密 (除特定搜索外)高风险:导致 Google Play 商店无法完成应用内购买鉴权
特定资讯/去广告应用api.zhihu.com, *.biliapi.net按需精细化解密 (Host-Specific)低风险:支持剔除开屏广告与信息流广告,但需注意防范 15MB 内存溢出

模块五:自动化脚本:配置文件 MitM 主机名与脚本内存风险核验 ​

在将小火箭配置文件部署到手机前,可在电脑端通过以下脚本快速审计是否存在高危泛通配符与内存溢出隐患:

python
#!/usr/bin/env python3
# ==============================================================================
# netzhenduan.cc Shadowrocket 配置文件 MitM 与重写规则安全性审计探针
# ==============================================================================

import re
import sys

def audit_config(file_path):
    print("=" * 60)
    print("  netzhenduan.cc Shadowrocket 配置与 MitM 规则安全性审计")
    print("=" * 60)

    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
    except Exception as e:
        print(f"[FAIL] 无法读取配置文件: {e}")
        return

    # 1. 检查 MitM 主机名
    print("\n[1/3] 审计 [MITM] 主机名安全性...")
    mitm_match = re.search(r'\[MITM\][\s\S]*?hostname\s*=\s*(.*?)\n', content)
    if mitm_match:
        hosts = [h.strip() for h in mitm_match.group(1).split(',')]
        print(f"  [INFO] 发现已配置的主机名数量: {len(hosts)}")
        for h in hosts:
            if h in ['*', '*.com', '*.cn', '*.net']:
                print(f"  [CRITICAL] 严重危险: 发现全局通配符 '{h}'!将导致整机 HTTPS 瘫痪!")
            elif any(danger in h for danger in ['apple', 'icloud', 'bank', 'alipay', 'wechat']):
                print(f"  [CRITICAL] 高危配置: 主机名 '{h}' 涉及核心系统或金融服务!极易触发风控!")
            else:
                print(f"  [OK] 主机名合规: {h}")
    else:
        print("  [INFO] 未启用 MitM 主机名解密模块。")

    # 2. 检查脚本重写数量 (防范 15MB 内存溢出)
    print("\n[2/3] 审计 [Script] 模块规模 (防范 15MB Jetsam 闪退)...")
    scripts = re.findall(r'^[^#\n].*?script-path', content, re.MULTILINE)
    print(f"  [INFO] 发现活动的重写脚本项: {len(scripts)} 条")
    if len(scripts) > 30:
        print(f"  [WARN] 警告: 脚本总数过多 ({len(scripts)} 条),在 iOS 15MB 限制下极易崩溃!建议精简至 15 条以内。")
    else:
        print("  [OK] 脚本数量在安全范围内。")

    print("\n" + "=" * 60)
    print("  审计完成!请确保手机已在系统关于本机中开启完全信任!")
    print("=" * 60)

if __name__ == '__main__':
    cfg = sys.argv[1] if len(sys.argv) > 1 else "shadowrocket.conf"
    audit_config(cfg)

模块六:真实生产环境 MitM 故障根因分析(RCA) ​

案例一:生成 CA 证书后 Safari 打开任何网页均报“此连接非专用” ​

  • 故障背景:某苹果用户按照网上教程在小火箭中开启了 HTTPS 解密,并点击生成了 CA 根证书。随后用户发现不仅去广告未生效,使用 Safari 打开任何网站均弹出红字警告“此连接非专用”或“无法验证服务器证书”,微信与银行 App 几乎全部掉线。
  • 技术复盘与根因分析:
    1. 工程师远程检查发现,用户在小火箭中生成证书后,虽然在系统「VPN与设备管理」中安装了该描述文件;
    2. 但用户遗漏了苹果 iOS 10.3+ 强制要求的第二道关卡——未进入「通用 -> 关于本机 -> 证书信任设置」手动激活完全信任;
    3. 导致 Safari 和系统网络框架将小火箭动态生成的证书视为“未受信的伪造证书”,直接阻断连接;
  • 根治措施:指导用户进入系统证书信任设置勾选开关,所有网页瞬时恢复正常,去广告重写规则秒级生效。

案例二:开启全功能去广告脚本后小火箭每隔 3 分钟闪退一次 ​

  • 故障背景:某极客用户在小火箭中导入了一套包含 80 多个外部 JavaScript 脚本的“全能重写去广告懒人配置”。只要打开某长视频 App 或刷小红书,手机状态栏上的 VPN 图标瞬间消失,小火箭在后台无声被杀。
  • 技术复盘与根因分析:
    1. 工程师连接 Mac 电脑并打开 Xcode 查看 iPhone 的系统崩溃日志(Crash Reporter / Analytics Data);
    2. 发现了海量针对 Shadowrocket 的 jetsam_event 崩溃记录,日志显示扩展进程在崩溃时的内存占用达到了 15.2 MB,触发了 EXC_RESOURCE -> RESOURCE_TYPE_MEMORY 硬件硬中断;
    3. 进一步排查发现,某个视频 App 的去广告脚本在解析一个 6MB 的压缩响应体时,在内存中连续分配了多个临时变量,直接打爆了 15MB 沙盒空间;
  • 根治措施:精简脚本库,删除非核心的体积过大脚本,改用规则层的 REJECT(零内存开销)代替应用层的 JS 脚本修改,内存常驻稳定在 8.5MB,闪退彻底根除。

模块七:集群纵深导航与跨专题指引 ​

网络诊断实验室(NetZhenDuan.cc)坚持独立技术实测与客观数据呈现。部分测速与线路评测内容包含商业推广标记(Sponsored),返利佣金不影响最终评测结论与用户付费价格。