b25c8bbc2c
把 PoC 的 sudo sing-box 外部二进制换成自包含、免 root 的 NEPacketTunnelProvider (System Extension)+ 嵌入 libbox 的生产架构铺好骨架(不破坏现有 PoC 构建)。 - PacketTunnel/:扩展 target 源 — PacketTunnelProvider(LibboxSetup→NewService→start, openTun 建 NEPacketTunnelNetworkSettings)、Info.plist(NEProviderClasses)、 entitlements(packet-tunnel-provider-systemextension + App Group) - Runner/VpnChannel.swift:主 app 经 NETunnelProviderManager 启停 + 状态/速率回传, 对齐 Dart 侧 VpnNativeBridge 的 pangolin/vpn channel 契约 - vpn_bridge_provider.dart:kUseNativeVpnMacOS 开关(默认 false,联调通过后置 true) - docs/p1-macos-system-extension.md:文件清单 + Xcode/签名步骤 + 待办 (Team BYL4KQHMTN;Network Extensions 已确认自助开通、无需 Apple 审批) 非破坏:新源文件未入 build target、注册行/app-group entitlements 均注释、gate 默认 false。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
P1 · macOS System Extension 接线指南(方案B)
状态:骨架已落(本仓库)。把 PoC 的
sudo sing-box run外部二进制换成自包含、免 root 的 NEPacketTunnelProvider(System Extension)+ 嵌入式 libbox。本文档列清单 + 待人工在 Xcode/开发者后台完成的步骤。总览见 vpn-core-embedding.md。
0. 关键标识(已确定)
| 项 | 值 |
|---|---|
| Team ID | BYL4KQHMTN |
| 主 app bundle id | com.pangolin.pangolin(App ID 已注册,勾 Network Extensions + App Groups) |
| 隧道扩展 bundle id | com.pangolin.pangolin.tunnel(待注册,同样勾 Network Extensions + App Groups) |
| App Group | group.com.pangolin.pangolin(待在 Identifiers → App Groups 注册) |
| 分发方式 | 站外 Developer ID + 公证(非 App Store)→ entitlement 用 -systemextension 后缀 |
| 权限审批 | 无需——Network Extensions 在 Identifiers 自助勾选即得(Packet Tunnel Provider 已 GA) |
1. 仓库里已就位的文件(骨架)
client/macos/
├─ Runner/
│ ├─ DebugProfile.entitlements / Release.entitlements ← application-groups 已备(注释,待 §3.6 解开)
│ ├─ MainFlutterWindow.swift ← VpnChannel 注册行已备(注释,待 §3.6 解开)
│ └─ VpnChannel.swift ← 主app:NETunnelProviderManager 启停+状态/速率回传(待加入 target)
└─ PacketTunnel/ ← 新 System Extension target 的源
├─ PacketTunnelProvider.swift ← 扩展:LibboxSetup→NewService→start;openTun 建 TUN
├─ PacketTunnel.entitlements ← packet-tunnel-provider-systemextension + app group
└─ Info.plist ← NEProviderClasses → PacketTunnelProvider
client/lib/bridge/
├─ vpn_bridge.dart ← VpnNativeBridge(method/event channel,已存在)
└─ vpn_bridge_provider.dart ← kUseNativeVpnMacOS 开关(默认 false;原生就绪后置 true)
Channel 契约(VpnNativeBridge ↔ VpnChannel):
- MethodChannel
pangolin/vpn:start(configJson)/stop/getStatus/selectOutbound(tag)/getActiveOutbound/setKillSwitch(bool) - EventChannel
pangolin/vpn/status:状态字符串(on/connecting/off/…) - EventChannel
pangolin/vpn/stats:每秒一帧{up, down, uplinkTotal, downlinkTotal}
2. 开发者后台(你来做,几分钟)
- App Group:Identifiers → App Groups → ➕ →
group.com.pangolin.pangolin。 - 回到 App ID
com.pangolin.pangolin的 App Groups capability → Edit → 勾上该 group。 - 新建 App ID
com.pangolin.pangolin.tunnel(扩展)→ 勾 Network Extensions + App Groups(关联同一 group)。 - Developer ID Application 证书(Certificates → ➕,若还没有)——签名 + 公证用。
3. Xcode:新增 System Extension target + 接 libbox(核心人工步骤)
Flutter 工程开
client/macos/Runner.xcworkspace。
- 编 libbox:
bash scripts/build-libbox.sh apple macos→ 得Libbox.xcframework(~204MB,不入 git)。 - 新 target:File → New → Target → Network Extension(macOS)→ Packet Tunnel
- Product Name:
PacketTunnel,bundle idcom.pangolin.pangolin.tunnel,语言 Swift。 - 删掉模板生成的
PacketTunnelProvider.swift,把client/macos/PacketTunnel/下的三个文件 加入该 target(Provider/Info.plist/entitlements);Info.plist 与 entitlements 设为本 target 用。
- Product Name:
- 链接 libbox:把
Libbox.xcframework拖进工程,在 PacketTunnel target 的 Frameworks and Libraries 加入(Embed & Sign);解开PacketTunnelProvider.swift里import Libbox与被注释的真实接线段(LibboxSetup/LibboxNewService/service.start())。 - 补平台接口:
PangolinPlatformInterface对LibboxPlatformInterfaceProtocol的完整实现 (openTun / writeLog / useProcFS / findConnectionOwner / defaultInterfaceMonitor / getInterfaces / underNetworkExtension / systemCertificates …)——对照官方 sing-box-for-appleExtensionPlatformInterface逐方法移植(NE 部分两端高度一致,可大段复用)。这是 P1 唯一"重"的代码块。 - sysex 激活:
VpnChannel.activateSystemExtensionIfNeeded()用OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: tunnelBundleId, queue:)- delegate 等结果;首启用户在「系统设置 → 隐私与安全性」点允许。
- 接主 app(Runner):
- 把
client/macos/Runner/VpnChannel.swift加入 Runner target 的 Compile Sources。 - 解开
MainFlutterWindow.swift里VpnChannel.register(...)那行注释。 - 解开
Runner/DebugProfile.entitlements、Release.entitlements里application-groups注释块 (注册 App Group 后)。
这三处在仓库里有意保持注释/未接,以免在 target/签名就绪前破坏现有 PoC 构建。
- 把
- 签名:两个 target(Runner + PacketTunnel)都用 Team BYL4KQHMTN + Developer ID; 开 Hardened Runtime;Runner 的 System Extensions capability 自动带出。
4. 速率/状态联调(libbox CommandServer)
- 扩展内
LibboxNewCommandServer(loopback)暴露状态/速率/连接;主 app 用LibboxCommandClient订阅 → 回填pangolin/vpn/stats与…/status(替换VpnChannel里的占位 timer)。 - 连接页(
connect_page.dart)与统计页已消费这两路流,无需改动。
5. 切换上线
- 全部联调通过(连真节点、出口 IP=节点、速率/延迟、Kill Switch、退出拆隧道、明暗/中英)后,
把
vpn_bridge_provider.dart的kUseNativeVpnMacOS置 true。 - PoC 的
DesktopVpnBridge(sudo 子进程)保留作 fallback/调试,不删。
6. 待办清单(TODO,代码内已标 TODO(P1))
- 开发者后台:App Group + 扩展 App ID + Developer ID 证书(§2)
- Xcode:新 PacketTunnel target + 加入
Libbox.xcframework(§3.1–3.3) - 解开
PacketTunnelProvider.swift真实接线 + 移植PangolinPlatformInterface(§3.4) OSSystemExtensionRequest激活流程(§3.5)LibboxCommandClient接速率/状态(§4)setKillSwitch/selectOutbound真实实现- 签名 + 公证流水线(Team BYL4KQHMTN)
- 联调通过 →
kUseNativeVpnMacOS = true(§5)