用 rclone 连接 iCloud:iCloud Drive 与 iCloud Photos 后端的配置、认证原理与实战指南
rclone 自 v1.69 起内置 iclouddrive 后端,可在一个 remote 中同时覆盖 iCloud Drive(默认服务)与 iCloud Photos(只读照片库)两大 Apple 云服务。本文以其官方文档 docs/content/iclouddrive.md 为骨架,结合仓库源码讲解完整的交互式配置流程、SRP-6a 免密上送认证机制、Photos 服务的层级结构与磁盘缓存、FUSE 挂载参数以及 Advanced Data Protection(ADP)下的故障排查方法,帮助你安全地备份、浏览与归档 iCloud 数据。
一、后端概览:一个 remote,两种服务
iclouddrive 后端在注册时即定义了两种服务类型(见 backend/iclouddrive/icloud.go 中的常量定义与 init 注册表):
| 服务值 | 含义 | 用途 |
|---|---|---|
drive(默认) |
iCloud Drive | 访问 iCloud 云盘文件,支持读写 |
photos |
iCloud Photos | 以只读层级树访问照片图库 |
选择在哪一层生效有三种方式:
- 在
rclone config中新建 remote 时直接选定service; - 在配置文件中把已有 remote 的
service改为photos; - 不改配置,仅在使用命令时追加
--iclouddrive-service photos临时切换。
rclone config 之后路由到具体后端的逻辑位于 backend/iclouddrive/icloud.go:NewServiceFs 解析 service 选项后,默认补为 drive,再分别分发到 Drive 的 NewFs 或 Photos 的 NewFsPhotos。
需要留意的是平台支持范围:该后端本体带有 //go:build !plan9 && !solaris 构建标签,无法构建的平台上由 backend/iclouddrive/iclouddrive_unsupported.go 提供占位实现。
二、初次配置:交互式创建与 30 天信任令牌
创建 iCloud remote 的前提条件与注意事项:
- 使用你常规的 Apple ID 密码,配合受信设备弹窗或短信的 2FA 验证码;
- ⚠️ 重要:不接受 App 专用密码(App-specific passwords),只能用普通密码 + 2FA。
以下示例创建一个专门用于照片的 remote icloudphotos。若只想用 iCloud Drive,让 service 保持默认值 drive 即可。首先执行:
rclone config
rclone 会引导你进入交互式配置流程(Storage 选项中的编号因版本而异,选择 iclouddrive 即可):
No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n
name> icloudphotos
Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.
[snip]
XX / iCloud Drive
\ (iclouddrive)
[snip]
Storage> iclouddrive
Option service.
iCloud service to use.
Choose a number from below, or type in your own value of type string.
Press Enter for the default (drive).
1 / iCloud Drive
\ (drive)
2 / iCloud Photos
\ (photos)
service> 2
Option apple_id.
Apple ID.
Enter a value.
apple_id> APPLEID
Option password.
Password.
Choose an alternative below.
y) Yes, type in my own password
g) Generate random password
y/g> y
Enter the password:
password:
Confirm the password:
password:
Edit advanced config?
y) Yes
n) No (default)
y/n> n
Option config_2fa.
Two-factor authentication: enter your 2FA code or type 'sms' for a text message
Enter a value.
config_2fa> 2FACODE
Remote config
--------------------
[icloudphotos]
- type: iclouddrive
- service: photos
- apple_id: APPLEID
- password: *** ENCRYPTED ***
- cookies: ****************************
- trust_token: ****************************
--------------------
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d> y
最终写入配置的关键字段包括:type、service、apple_id、password(rclone obscure 加密存储)、cookies 与 trust_token(均以密文/掩码形式保存,由 rclone 自动维护,无需手工填写)。
信任令牌(trust token)有效期 30 天,到期后需重新认证。重新认证有两个途径:
# 交互式重建
rclone config
# 或仅刷新认证状态(对应 cmd/config/config.go 中 Use: "reconnect remote:" 的子命令)
rclone config reconnect icloudphotos:
在配置阶段的源码实现中,重新认证并不只是刷新令牌:当 config.State == "" 时,Config 函数 会主动丢弃旧的 trust token 与 cookies,强制走完整 SRP + 2FA 流程,确保每次 reconnect 都提示 2FA 而不是悄悄复用旧会话。
三、认证原理:SRP-6a 协议与 2FA 状态机
rclone 采用与 iCloud 网页端相同的 SRP(Secure Remote Password,安全远程密码)协议 与 Apple 身份服务通信。核心承诺是:你的密码永远不会被发送到 Apple 服务器——客户端用密码在本地派生密钥,与服务端交换密码学证明来验证“你知道密码”这一事实。
3.1 认证流程
- rclone 向 Apple 身份服务发起会话(源码中端点位于 api/client.go:
idmsa.apple.com/appleauth/auth等); - 完成 SRP 密钥交换——密码仅在本地用于派生密钥;
- Apple 向受信设备推送 2FA 提示,或允许你请求短信验证码;
- 输入 2FA 验证码后,rclone 获得可用于后续会话的 trust token 与 cookies。
3.2 SRP 参数与本地证明
SRP 客户端实现集中在 api/srp.go。它使用 RFC 5054 定义的 2048-bit 大素数群(g=2,SHA-256) 作为协商参数:客户端生成 32 字节随机私钥 a,计算公钥 A = g^a mod N 发送给服务端;收到服务端挑战后按 RFC 5054 校验 B 落在 1..N-1 区间,并拒绝计算得到 u = 0 的非法挑战,随后用 PBKDF2(SHA256) 派生的密码密钥、盐值与双方公钥计算会话密钥与证明值 M1/M2。服务器只能验证证明,拿不到明文密码。
3.3 2FA 交互状态机与短信通道
iCloud 的 2FA 存在多种形态,icloud.go 用显式的状态机覆盖了全部路径:
- 若账号没有任何受信设备且配置了受信手机号,rclone 会跳过推送,直接自动触发短信流程(
triggerSMSFlow); - 若存在受信设备,rclone 显式调用
RequestPushNotification向设备推送验证码——这是针对 iOS 26.4+ 上 SRP 409 不再自动推送 的兼容处理,旧版本上可能产生一次无害的重复推送; - 用户在
config_2fa处输入 6 位验证码,或输入sms改用短信; - 账号绑定多个手机号时,rclone 会先列出手机号供选择,再向所选号码发送短信;
- 关键中间状态(SRP 会话等)被 base64 编码存入配置的
_auth_session字段,以便在“获取验证码”与“校验验证码”两步之间复用会话,避免重复做一次 SRP 往返并触发第二次推送。
校验通过后调用 saveAuthCredentials:写入新的 trust_token 与 cookies,清空临时会话状态,并清除磁盘上旧的认证缓存。
3.4 会话保持与自动续期
日常使用时(非配置阶段),若配置中已存有 trust token,客户端通过 newICloudClient(icloud.go)以最小开销恢复会话:优先复用已缓存的会话与服务端点,跳过昂贵的 /validate 往返。当请求遇到 401/421(会话过期)时会自动重认证并重放请求,详见 api/client.go;若此时仍被要求 2FA,则返回错误提示用户重新执行 rclone config reconnect。
四、选择服务:--iclouddrive-service 命令行覆盖
如果不想为照片单独建一个 remote,也可以保留 service = drive 的通用 remote(如 iclouddrive:),在需要访问照片库时通过命令行开关临时切换:
# 列出照片图库(第一层即各个 Library)
rclone lsd iclouddrive: --iclouddrive-service photos
# 列出个人图库中的相册
rclone lsd iclouddrive:PrimarySync/ --iclouddrive-service photos
# 列出某相册中的全部照片/视频
rclone ls iclouddrive:PrimarySync/All\ Photos/ --iclouddrive-service photos
# 把一张 HEIC 照片下载到本地
rclone copy iclouddrive:PrimarySync/Favorites/IMG_0001.HEIC /tmp/ --iclouddrive-service photos
即两种用法等价,任选其一:
- 配置时设
service = photos,得到专用于照片的 remote(如示例的icloudphotos); - 配置保持
drive,按需在命令后追加--iclouddrive-service photos。
五、iCloud Photos 的层级结构与只读访问
当 service = photos 时,remote 呈现一棵只读的、根植于照片图库的层级树:
- 第一层:照片图库(Library)——包括你的个人图库
PrimarySync,以及任何共享图库SharedSync-XXXX; - 第二层及以下:相册与文件夹——在 Apple Photos 中组织的嵌套结构原样呈现(相册可含子文件夹);
- 叶节点:照片与视频文件——相册内的媒体资源,Live Photo 的
.MOV伴随文件也会一并列出。
List 的层级分发逻辑见 icloudphotos.go:根 ID 下列出所有库(并附带各库相册数量),lib: 前缀的目录 ID 列出库内相册,album: 前缀的目录 ID 则列出相册内媒体或子文件夹。
5.1 需要注意的首次列举延迟
由于 Apple 照片 API 存在分页上限,超大相册(如含 75,000 个条目的 All Photos)首次冷列举可能需要数分钟。这个开销只在第一次发生——后续列举会命中磁盘缓存(详见下文缓存机制)。
5.2 只读限制
iCloud Photos 服务是只读的:上传、删除、重命名与移动均不受支持。从源码特性看,Photos 后端的能力集仅声明了 ReadMetadata 等只读特性(icloudphotos.go),没有暴露任何写接口。若把 Photos remote 当作普通可写目标使用,会收到明确的能力错误。
六、Photos 元数据:--metadata 下的五个只读键
启用 --metadata 后,iCloud Photos 的条目会暴露以下只读元数据(仅当 service = photos 时可用):
| 元数据键 | 含义 | 类型 | 示例值 | 只读 |
|---|---|---|---|---|
added-time |
条目被加入 iCloud 图库的时间 | RFC 3339 | 2006-01-02T15:04:05Z |
✅ |
favorite |
是否标记为收藏 | bool | ✅ | |
height |
图片高度(像素) | int | ✅ | |
hidden |
是否被隐藏 | bool | ✅ | |
width |
图片宽度(像素) | int | ✅ |
这些键与 fs.RegInfo.MetadataInfo 中的注册完全一致(见 icloud.go),Photos 对象的 Metadata() 方法在读取时动态组装(icloudphotos.go)——added-time 内部以毫秒时间戳存储、对外格式化为 RFC 3339。rclone 元数据机制的整体用法可参考仓库文档 fs/operations/operations.md。
元数据的典型消费场景是备份后的筛选与检索,例如结合 rclone copy --metadata 保留收藏/隐藏标记,或配合 rclone lsjson 输出做相册级整理。注意 favorite、hidden 等仅由元数据携带,不作为文件系统的真实“属性”持久化到目标。
七、磁盘缓存机制:首跑并行分页 + 轻量增量检查
iCloud Photos 会把相册清单缓存到本地磁盘,保证后续访问快速。这是反复列举大相册时体验差异巨大的关键机制。
7.1 首次冷列举:并行 startRank 分区
首次列举大相册时,Photos API 的 CloudKit 查询接口只支持按 startRank(记录偏移)遍历。rclone 将整个相册按 stride = photosQueryLimit/2(即每次 100 个照片)划分成多个分区,用多个 worker 并行拉取,见 api/photos.go 的 fetchPhotosParallel。
7.2 增量检查:约 200ms 的 changes/zone
此后再次访问,rclone 不再全量拉取:它会针对该 zone(图库)调用一次 changes/zone 接口,做一次约 200ms 的轻量变更检查(batchCheckForChanges 甚至可把多个 zone 的检查合并进单个 API 调用,见 api/photos.go)。只有确认有变更时才失效并重建对应相册缓存;无变更则直接复用。变更结果按新增/删除/相册成员关系/元数据标记分类处理(parseDeltaRecords),并精确失效受影响的相册而非整库刷新。
7.3 缓存位置与清理
缓存目录按 remote 与图库 zone 隔离:
~/.cache/rclone/iclouddrive-photos/<remote>/<zone>/
其中 <remote> 是 remote 名称,<zone> 是图库 CloudKit zone(如 PrimarySync);目录由 Photos API 层的 cacheSubdir = "iclouddrive-photos" 常量拼接而来(api/photos.go),库元数据 libraries.json 与各 zone 的 albums.json 也存放在该命名空间下。缓存清理有两种方式:
- 直接删除该目录;
- 执行
rclone config reconnect <remote>:——它调用后端的Disconnect(icloudphotos.go),在清除认证状态的同时移除磁盘缓存。
八、FUSE 挂载 iCloud Photos 的推荐参数
将 iCloud Photos 以文件系统形式挂载浏览时,官方推荐如下组合:
rclone mount remote: /mnt/photos \
--iclouddrive-service photos \
--vfs-refresh \
--dir-cache-time 1h \
--vfs-cache-mode full \
--attr-timeout 1m \
--read-only
各参数作用与取舍:
--vfs-refresh:挂载启动时在后台预热目录缓存,浏览相册时即刻就绪;--dir-cache-time 1h:把目录内存缓存寿命从默认的 5 分钟延长到 1 小时——由于后端增量变更检查很快,延长缓存是安全的;--vfs-cache-mode full:把下载过的照片/视频落盘缓存到本地,重复访问走本地 IO;--attr-timeout 1m:降低内核属性查找频率(后端只读,属性不会在挂载期内被外部改变,因此安全);--read-only:避免对只读后端产生令人困惑的写错误。
再次强调:超大相册(如数万张照片的 All Photos)首次列出的等待不可避免,这是 API 分页限制所致;耐心等待一次后,后续浏览将由磁盘缓存接管。
九、Advanced Data Protection(ADP,高级数据保护)支持
iCloud Drive/Photos 后端支持开启 ADP 的账号,但有一个关键前提:
- 在 iPhone 上进入 设置
>Apple 账户>iCloud>,确保 “在网页上访问 iCloud 数据”(Access iCloud Data on the Web)为开启状态。
若账号启用了 ADP,rclone 会在 2FA 之后额外请求 PCS cookies(一种端到端加密场景所需的授权 cookie)。Apple 可能在受信设备上弹出批准请求——必须手动批准,PCS cookie 才会签发。
从源码看,PCS cookie 的获取是按服务域(drivews/ckdatabasews)作用域的:api.New 的 pcsWSKey 参数决定了 cookie 归属哪个云服务,空值则完全跳过 PCS 流程(api/client.go),认证成功后统一由 ensurePCSCookies 保证存在(api/client.go)。
十、故障排查
10.1 PCS cookie 错误与 ADP 批准未完成
症状:出现 Missing PCS cookies from the request 或形如 requestPCS: 的错误。其含义是 ADP 账号所需的授权流程未成功完成——会话请求被服务端以 423(Locked) 判定为缺少 PCS cookie(见 api/client.go 对 423 的注释)。
解决步骤:
- 确认 “在网页上访问 iCloud 数据” 已开启;
- 在受信设备上批准弹出的授权请求;
- 重新认证以获取新 cookie:
rclone config reconnect icloudphotos:
- 若 remote 仍残留过期认证状态,清空配置中的
cookies与trust_token字段;仍不行则直接删除并重建该 remote。
十一、配置选项速查
以下为 iclouddrive 后端的全部选项(与文档自动生成部分一致)。
标准选项
| 选项 | Config 键 | 环境变量 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|---|
--iclouddrive-service |
service |
RCLONE_ICLOUDDRIVE_SERVICE |
string | "drive" |
取值 drive(iCloud Drive)或 photos(iCloud Photos) |
--iclouddrive-apple-id |
apple_id |
RCLONE_ICLOUDDRIVE_APPLE_ID |
string | 必填 | Apple ID |
--iclouddrive-password |
password |
RCLONE_ICLOUDDRIVE_PASSWORD |
string | 必填 | Apple ID 密码,输入必须用 rclone obscure 加密(见 rclone obscure 命令) |
密码之所以要求 obscure 存储,是因为后端在运行时会调用 obscure.Reveal 还原明文参与 SRP 推导(icloud.go),明文不能直接落盘。
高级选项
| 选项 | Config 键 | 环境变量 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|---|
--iclouddrive-client-id |
client_id |
RCLONE_ICLOUDDRIVE_CLIENT_ID |
string | "d39ba9916b7251055b22c7f910e2ea796ee65e98b2ddecea8f5dde8d9d1a815d" |
用于 iCloud API 访问的客户端 ID(一般无需修改) |
--iclouddrive-encoding |
encoding |
RCLONE_ICLOUDDRIVE_ENCODING |
Encoding | Slash,BackSlash,Del,Ctl,InvalidUtf8,Dot |
后端编码配置,通用编码规则见 overview 的 encoding 一节 |
--iclouddrive-description |
description |
RCLONE_ICLOUDDRIVE_DESCRIPTION |
string | 空 | remote 描述 |
运行时还有一组由 rclone 自动写入、用于保持认证状态的非交互键:
trust_token、cookies与临时_auth_session。请勿手工改动,除非在执行故障排查里的“清空认证字段”步骤。
十二、实践要点总结
- 认证安全:SRP-6a + 2FA 保证密码永不上传,30 天 trust token 到期后用
rclone config reconnect <remote>:快速续期; - 照片访问两条路:专用
photosremote 或--iclouddrive-service photos临时切换,结构为Library(如 PrimarySync) → 相册/文件夹 → 媒体文件; - 性能关键在缓存:首次大相册列举较慢,之后 ~200ms 增量检查 + 磁盘缓存让重复访问近乎瞬时;需要释放空间时删
~/.cache/rclone/iclouddrive-photos/或执行 reconnect; - 元数据是只读附加值:
--metadata下仅 Photos 服务暴露width/height/added-time/favorite/hidden; - 挂载用只读姿态:配合
--vfs-refresh、--vfs-cache-mode full、--read-only可获得流畅的浏览体验; - ADP 账号:先开“在网页上访问 iCloud 数据”,2FA 后在受信设备上批准 PCS cookie 请求,即可正常使用。
相关集成测试入口见 backend/iclouddrive/iclouddrive_test.go(基于 fstest/fstests 的标准后端一致性测试套件),版本演进记录可查阅 docs/content/changelog.md 中 iclouddrive 相关条目。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00