openziti/ziti-sdk-swift

GitHub: openziti/ziti-sdk-swift

面向 macOS 和 iOS 应用的 OpenZiti SDK,帮助 Apple 平台开发者将网络请求接入零信任 overlay 网络并实现透明路由。

Stars: 58 | Forks: 8

![Ziggy 使用 ziti-sdk-swift](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/74d8af3303041418.jpg) # Swift 版 Ziti SDK ![构建状态](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/36d91e8684041424.svg) 一个使用 Swift 编程语言从 macOS 和 iOS 应用程序访问 Ziti 的 SDK。 此 SDK 提供了 __Ziti Tunnel C SDK__ 的 Swift 友好封装、一个用于拦截 HTTP 和 HTTPS 流量的 `URLProtocol` 实现,以及在应用程序中使用该 SDK 的示例。 # 用法 `Ziti` 类是访问 Ziti 网络的主要入口点。`Ziti` 实例在初始化时需要一个 `ZitiIdentity`。 使用 `Ziti.createConnection()` 创建 `ZitiConnection` 实例,以便 `ZitiConnection.dial(_:_:_:)` 服务或使用 `ZitiConnection.listen(_:_:_:)` 进行服务连接。 使用 `ZitiUrlProtocol` 拦截 HTTP 和 HTTPS 连接,并通过 Ziti 网络路由它们。 ## 注册 `ZitiIdentity` 是在 Ziti 网络的注册过程中创建的。`Ziti` 支持使用由您的 Ziti 网络管理员提供的一次性 JWT 进行注册。 `Ziti.enroll(_:_:)` 方法会验证 JWT 是否已正确签名,创建私钥并将其存储在 keychain 中,向 controller 发起证书签名请求 (CSR),并将生成的证书存储在 keychain 中。 __Swift__ ``` import CZiti let jwtFile = <...> let outFile = <...> Ziti.enroll(jwtFile) { zid, zErr in guard let zid = zid else { fputs("Invalid enrollment response, \(String(describing: zErr))\n", stderr) exit(-1) } guard zid.save(outFile) else { fputs("Unable to save to file \(outFile)\n", stderr) exit(-1) } print("Successfully enrolled id \"\(zid.id)\" with controller \"\(zid.ztAPI)\"") } ``` __Objective-C__ ``` #import "CZiti-Swift.h" NSString *jwtFile = <...> NSString *outFile = <...> [Ziti enroll:jwtFile : ^(ZitiIdentity *zid, ZitiError *zErr) { if (zErr != NULL) { // Handle error return; } if (![zid save:outFile]) { // Handle error return; } }]; ``` 在上面的示例代码中,保存到 `outfile` 的身份文件包含了用于联系 Ziti controller 以及在本地访问 keychain 中的私钥和证书的信息。 ## 运行 Ziti 典型的应用程序流程如下: 1. 检查已知位置是否存在存储的身份文件 2. 如果不存在,则发起注册(例如,提示用户输入一次性 JWT 注册文件的位置,或扫描 QR 码) 3. 当身份文件可用时,使用它创建并运行 `Ziti` 实例 `Ziti` 在一个 loop 上执行,类似于 `Foundation` 的 `Runloop`。`Ziti.run(_:)` 方法本质上是进入一个处理 Ziti 事件的无限循环,并且只有在 `Ziti` 被关闭后才会退出。 提供 `Ziti.runAsync(_:)` 方法是为了方便起见,用于生成一个新线程并调用 `Ziti.run(_:)`。 __Swift__ ``` let zidFile = <...> guard let ziti = Ziti(fromFile: zidFile) else { print("Unable to create Ziti identity from file \(zidFile)") return } ziti.runAsync { zErr in guard zErr == nil else { print("Unable to run Ziti: \(String(describing: zErr!))") return } print("Successfully initialized Ziti!") } ``` __Objective-C__ ``` NSString *zidFile = <...> Ziti *ziti = [[Ziti alloc] initFromFile:[self zidFile]]; if (ziti != NULL) { [ziti runAsync: ^(ZitiError *zErr) { if (zErr != NULL) { // Handle error return; } [ZitiUrlProtocol register:ziti :10000]; }]; } ``` 要在运行 Ziti 的线程上执行代码,请使用 `perform(_:)` 方法。 ## 使用 `ZitiUrlProtocol` 该 SDK 还包含 `ZitiUrlProtocol`,它实现了一个 `URLProtocol`,用于拦截 Ziti 服务的 HTTP 和 HTTPS 请求,并通过 Ziti 网络路由它们。 `ZitiUrlProtocol` 应该作为 `Ziti.run(_:)` 的 `Ziti.InitCallback` 的一部分进行实例化,以确保在开始拦截服务之前 `Ziti` 已被初始化。 __Swift__ ``` ziti.runAsync { zErr in guard zErr == nil else { // Handle error return } ZitiUrlProtocol.register(ziti) } ``` __Objective-C__ ``` [ziti runAsync: ^(ZitiError *zErr) { if (zErr != NULL) { // Handle error return; } [ZitiUrlProtocol register:ziti :10000]; }]; ``` 如果您使用自己的 `URLSession` 而不是 `URLSession.shared`,则需要在您的 `URLSession` 配置中配置 `ZitiUrlProtocol`: ``` let configuration = URLSessionConfiguration.default configuration.protocolClasses?.insert(ZitiUrlProtocol.self, at: 0) urlSession = URLSession(configuration:configuration) ``` 另请参阅 `Xcode` Quick Help 面板中提供的 `CZiti` 模块中的文档。 # 将 `CZiti` 添加为依赖项 `CZiti` 被构建到一个 XCFramework (`CZiti.xcframework`) 中,其中包含适用于每个平台和架构的静态库 (`libCZiti.a`)。 请注意,`CZiti` 不是为 Bitcode 构建的,在为设备构建时,__Build Settings - Build Options__ 应该将 `Enable Bitcode` 设置为 `No`。 请注意,`CZiti` 在链接时依赖于 `libresolv.9.tbd` 和 `libz.1.tbd`,并且在 runtime 需要访问出站网络连接和 Apple Keychain。 ## 通过 `Swift Package Manager` 请参阅 [ziti-sdk-swift-dist](https://github.com/openziti/ziti-sdk-swift-dist) 以获取从此存储库构建并作为 `.binaryTarget` 提供的 `CZiti.xcframework`。 ## 使用本地构建的 CZiti 要在您的应用程序中体验对 CZiti 框架的修改,首先按照上述说明将 CZiti 模块添加为应用程序的依赖项,然后使用本地包覆盖 CZiti 框架。有关此过程的概述,请参阅[将包依赖项编辑为本地包](https://developer.apple.com/documentation/xcode/editing-a-package-dependency-as-a-local-package)。 我使用了以下步骤在 ziti-tunnel-apple 项目中用本地构建的版本覆盖 CZiti: 1. 构建 CZiti 框架。您可能想要为调试而构建: $ CONFIGURATION=Debug ./build_all.sh 完成后,构建将位于 ./dist/CZiti.xcframework 中。 2. 为本地 CZiti 框架创建 Package.swift: cat > ./dist/Package.swift < 0.1' end target 'SomeTarget-iOS-Target' use_frameworks! platform :ios, '13.4' pod 'CZiti-iOS', '~> 0.1' end ``` 有关 Cocoapods 的更多信息,请查看[官方文档](http://guides.cocoapods.org/using/getting-started.html)。 ## 通过 `libCZiti.a` * 按照以下构建步骤创建 `libCZiti.a` * 将 `libCZiti.a` 库添加到您项目的 **Frameworks and Libraries** 中,并确保它列在您项目的 **Build Phases** 中的 **Link Binary with Libraries** 下。 * 您的 **Library Search Path** 和 **Swift Compiler Seatch Paths - Import Paths** 应该包含含有 `libCZiti.a` 和 `CZiti.swiftmodule/` 的目录 * 当此项目从 `Xcode` 构建时,`CZiti-Swift.h` 文件会被复制到 `$(PROJECT_ROOT)/include/$(PLATFORM)`(例如,`./include/iphoneos`)。从 `Xcode` 或通过 `build_all.sh` 构建后,也可以在 `./DerivedData` 下的 `DerivedSources` 目录中找到 `CZiti-Swift.h`。从 Objective-C 使用 `CZiti` 需要此文件。您的 __Search Paths - Header Search Paths__ 必须包含含有 `CZiti-Swift.h` 的目录。 * 检查此存储库中示例应用程序的配置,以获取有关库和路径的相关构建设置 ## 示例 此存储库包含一些使用该库的示例: - [`ziti-mac-enroller`](ziti-mac-enroller/main.swift) 是一个实用程序,它将使用提供的一次性 JWT token 注册身份。它可以选择性地更新 keychain,以信任 Ziti controller 使用的 CA pool - [`sample-mac-host`](sample-mac-host/main.swift) 是一个命令行实用程序,可以作为指定 Ziti server 的 client 或 server 运行 - [`sample-ios`](cziti.sample-ios/README.md) 练习使用 `ZitiUrlProtocol` 拦截 `URLSesson` 请求,通过 Ziti 路由它们,并显示结果 - [`sample-ios-objc`](sample-ios-objc/README.md) 演示了如何使用 __Objective-C__ 来运行 `ZitiUrlProtocol` # 构建 ## 更新 `xcconfig` 设置 创建一个名为 `Configs/workspace-settings-overrides.xcconfig` 的文件并填充适当的值。有关所有可能的值,请参阅 `Configs/workplace-settings.xcconfig`。 ``` DEVELOPMENT_TEAM = XXXXXXXXXX ORGANIZATION_PREFIX = ... ``` ## 执行构建脚本 该项目依赖于 __Ziti Tunnel C SDK__,该 SDK 直接构建到库中。它作为 submodule 维护在 `./deps/ziti-tunnel-sdk-c`。请务必按照 deps/ziti-tunnel-sdk-c/BUILD.md 中的说明进行 vcpkg 设置。此项目期望 macOS 的构建位于 `./deps/ziti-tunnel-sdk-c/build-macosx-x86_64` 和 `./deps/ziti-tunnel-sdk-c/build-macosx-arm64`,而 iOS 的构建位于 `./deps/ziti-sdk-c/build-iphoneos-arm64`(如果是模拟器,则位于 `build-iphonesimulator-x86_64` 或 `build-iphonesimulator-arm64`)。 该项目包含 [`buid_all.sh`](build_all.sh) 脚本,它将从命令行为 `macosx`、`iphoneos` 和 `iphonesimulator` 平台构建项目。 构建静态库后,`build_all.sh` 脚本会执行 [`make_dist.sh`](make_dist.sh),在项目的 `./dist` 目录下创建一个名为 `CZiti.xcframework` 的 XCFramework。 这些脚本要求调用者的路径中包含以下可执行文件: * `xcodebuild` 用于构建 `CZiti.xcodeproj` 中的 `CZiti-*` scheme,作为 `Xcode` 安装的一部分提供 * `xcpretty` 也用于构建 `CZiti.xcodeproj` 中的 `CZiti-*` scheme。(可以通过 `gem install xcpretty` 安装) * `cmake` 用于构建 __Ziti Tunnel C SDK__ 依赖项。(可以通过 `brew install cmake` 安装) ``` $ git clone --recurse-submodules https://github.com/openziti/ziti-sdk-swift.git $ cd ziti-sdk-swift $ /bin/sh build_all.sh ``` 默认情况下,脚本为 `Release` 配置进行构建。要为 `Debug` 构建,请执行 ``` $ CONFIGURATION=Debug /bin/sh build_all.sh ``` 生成的 `libCZiti.a` 和 `CZiti.swiftmodule` 位于 `./DerivedData` 的相应子目录中。 ## 获取帮助 请使用这些社区资源来获取帮助。 - 阅读[文档](https://docs.openziti.io/docs/learn/introduction/) - 参与 [Discourse](https://openziti.discourse.group/) 上的讨论 - 使用 GitHub [issues](https://github.com/openziti/ziti-sdk-swift/issues) 来跟踪 bug 和功能请求。 版权所有 NetFoundry Inc.
标签:CVE监控, iOS, Swift, VPN, 网络通信, 零信任网络