WWDC Quick Look 💓 By SwiftGGTeam
Get ready for iCloud Private Relay

Get ready for iCloud Private Relay

观看原视频

Highlight

iCloud Private Relay 是 iCloud+ 内置服务,通过双代理架构阻止网络和服务器追踪用户互联网活动;开发者无需修改代码即可自动受益,但需要确保服务器停止依赖 IP 地址推断用户位置和身份。

核心内容

没有 Private Relay 之前,隐私漏洞在哪里

你在咖啡馆连上公共 Wi-Fi,打开一个 App。此时,Wi-Fi 运营方能看到你访问了哪些域名——因为 DNS 查询是明文传输的。这些信息足以描绘出你的上网习惯画像。

更深层的问题是,目标服务器能看到你的真实 IP 地址。服务器可以据此推断你的大致位置,甚至通过 IP 地址在不同网站之间关联你的身份——即使 Safari 的智能防跟踪已经阻止了 Cookie 关联。

Private Relay 的双代理架构

Apple 的解决方案是引入两个独立的代理服务器。第一个代理由 Apple 运营,第二个由内容提供商运营。

关键设计:没有任何一方能同时看到用户的 IP 地址和访问的目标域名。Apple 只知道你是谁,但不知道你访问了什么;第二个代理只知道你访问了什么,但不知道你是谁。

02:53

哪些流量会经过 Private Relay

在 iOS 15 和 macOS 12 中,Private Relay 自动应用于:

  • Safari 的所有网页浏览
  • 所有 DNS 域名解析查询
  • App 中的不安全 HTTP 流量(TCP 80 端口)

以下流量不受影响:

  • 本地网络连接
  • 私有域名连接
  • 使用 VPN 或代理的网络扩展流量

04:15

详细内容

在代码中检测 Private Relay 状态

虽然不需要额外代码来启用 Private Relay,但你可以通过现代网络 API 了解连接是否经过了代理。

URLSession 方式:

let task = URLSession.shared.dataTask(with: url) { data, response, error in
    // 任务完成后检查 metrics
}

task.metrics { metrics in
    for metric in metrics.transactionMetrics {
        if let proxy = metric.proxyConnection {
            print("连接使用了代理: \(proxy)")
        }

        // 检查是否使用了 Private Relay
        if metric.isProxyConnection {
            print("此请求经过 Private Relay")
        }
    }
}
task.resume()

关键点:

  • transactionMetrics 数组包含每个网络请求的详细指标
  • isProxyConnection 标识请求是否经过代理
  • 需要在请求完成后才能获取准确的 metrics 数据

Network.framework 方式:

import Network

let connection = NWConnection(host: "example.com", port: 443, using: .tls)
connection.start(queue: .global())

connection.stateUpdateHandler = { state in
    switch state {
    case .ready:
        if let report = connection.currentPath?.availableInterfaces {
            // 检查连接建立报告
        }
    default:
        break
    }
}

关键点:

  • NWConnection 提供更底层的网络连接控制
  • 通过 EstablishmentReport 可以检查 DNS 解析和代理连接各阶段的时间
  • 适合需要精细控制网络行为的场景

服务器端的适配

如果你的服务器依赖 IP 地址做地理位置判断,需要做出调整。

Private Relay 的代理 IP 地址按城市或地区映射。Apple 会公布这些代理 IP 地址列表,你可以用正确的 GeoIP 数据库来映射到大致区域。

但核心建议是:停止用 IP 地址推断位置和身份。

// 推荐:显式请求用户位置
import CoreLocation

let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()

// 获取位置后按需使用
locationManager.startUpdatingLocation()

关键点:

  • CoreLocation 基于用户明确授权,比 IP 推断更精确
  • 可以指定需要的精度级别,避免过度获取
  • IP 地址地理定位本身就不准确,尤其在移动网络环境下

网络管理员的注意事项

启用 Private Relay 后,网络流量会出现两个明显变化:

  1. UDP 443 端口流量增加 — 这是 QUIC/HTTP/3 协议,用于与 Private Relay 代理通信。确保防火墙允许 UDP 443。

  2. 明文 DNS 查询减少 — 因为 DNS 查询被加密发送到代理服务器。

对于企业或学校网络,如果需要审计所有流量,可以阻止 Private Relay 代理服务器的主机名。设备连接时会提示用户:在当前网络禁用 Private Relay,或切换到其他网络。

13:43

内容过滤和家长控制

如果你的 App 提供内容过滤或家长控制功能,好消息是:你的过滤器仍然能在流量进入 Private Relay 之前看到它。

使用 NetworkExtension 框架的内容过滤 API:

import NetworkExtension

// 注册内容过滤提供程序
let provider = NEFilterProvider()
// 过滤逻辑在设备本地执行,不受 Private Relay 影响

关键点:

  • 内容过滤在设备本地执行,先于 Private Relay 处理
  • 使用 NEFilterProviderNEFilterDataProvider 实现过滤逻辑
  • 参考 “Meet the Screen Time API” session 了解具体实现

核心启发

1. 全面审计 App 中的 HTTP 连接

  • 做什么:检查项目中所有使用 http:// 的 URL,全部升级为 https://
  • 为什么值得做:Private Relay 会代理不安全的 HTTP 流量,但这只是中间保护;端到端加密才是完整方案
  • 怎么开始:搜索项目中的 http:// 字符串,检查 Info.plist 中的 NSAppTransportSecurity 例外配置,逐个移除

2. 用 Core Location 替代 IP 定位

  • 做什么:如果服务器根据 IP 推断用户位置,改为在客户端用 CLLocationManager 获取
  • 为什么值得做:IP 定位不准确且侵犯隐私;Core Location 基于用户授权,精度可控
  • 怎么开始:在需要位置信息的页面添加位置权限请求,将坐标传给服务器而非让服务器猜

3. 为网络调试增加 Private Relay 检测

  • 做什么:在 App 的网络层增加 metrics 收集,标记哪些请求走了代理
  • 为什么值得做:帮助排查用户反馈的网络问题,区分是 Private Relay 导致还是其他原因
  • 怎么开始:在现有 URLSession 回调中加入 task.metrics 检查,记录 isProxyConnection 状态到日志

4. 更新服务器端的防欺诈逻辑

  • 做什么:如果服务器用 IP 地址做风控或防刷,增加设备端验证作为补充
  • 为什么值得做:Private Relay 下多个用户共享同一个代理 IP,基于 IP 的限频会误伤正常用户
  • 怎么开始:引入 DeviceCheck 或 App Attest 做设备级验证,替代纯 IP 维度的判断

5. 企业网络适配指南

  • 做什么:为企业客户准备 Private Relay 兼容性文档
  • 为什么值得做:企业网络通常有严格的流量审计要求,提前告知配置方法减少支持工单
  • 怎么开始:在帮助文档中说明需要开放 UDP 443,以及如何配置代理主机名阻止策略

关联 Session

评论

GitHub Issues · utterances