更新时间:2026 年 6 月 25 日
LUKS2 + TPM 2.0 + Clevis 自动解锁是 Linux 全盘加密在 2026 年最实用的"无人值守 + 防离线攻击"方案。LUKS2 负责扇区级 AES-XTS 加密,TPM 2.0 在 PCR 测量启动链(Secure Boot、shim、kernel、initrd)完整时释放密封过的解密密钥,Clevis 则在 TPM 缺失或失效时通过 Tang 服务器在受信任网络内完成"网络绑定解密"。本文以 cryptsetup 2.8、systemd 257、Clevis 21 为基准,完整覆盖威胁模型、密钥层级、PCR 选择、升级回滚与运维剧本。坦白说,这套流程可以直接抄回去作为生产环境的部署手册使用。
- LUKS2 的反离线攻击能力来自 Argon2id KDF 加上加密 keyslot 区。2026 年 cryptsetup 2.8 默认启用 PBKDF 内存 1 GiB,普通暴力破解已不可行。
- TPM 2.0 自动解锁并不是"免密码",而是把"知识因子(passphrase)"替换为"完整性因子(PCR 状态)"。一旦 BIOS、Secure Boot 或 kernel 被篡改,密钥就不会释放。
- 推荐 PCR 选择是
0+2+4+7+11,或者基于 systemd 的 11(UKI 测量),不要再用老式的 0+7,后者无法检测 initrd 替换。
- Clevis + Tang 适合机房和边缘节点的"网络绑定"场景:机器一旦离开本地网段,磁盘自动无法解密,比 TPM 更能扛"整机被盗"威胁。
- 必须保留至少 2 个独立 keyslot,一个绑 TPM 或 Clevis,一个长 passphrase 离线保存。升级 kernel 后 PCR 漂移导致无法启动,是头号生产事故。
- systemd-cryptenroll 在 systemd 254+ 已经取代了手工
tpm2-tools 流程,是 2026 年的事实标准命令。
威胁模型:什么算"防住了"?
在动手敲 cryptsetup 之前,我习惯先把威胁模型写下来。这是我每次评审同事的加密方案时的第一个问题:什么会先出问题?全盘加密通常被用来防御四类攻击者,而 LUKS2 + TPM 在这四类下的"爆炸半径"差别其实蛮大。
- 整机失窃(冷攻击)。笔记本被拿走,机房硬盘被拔走。LUKS2 + 强 passphrase + Argon2id 在这一档基本足够;TPM 反而引入"芯片被解焊嗅探 LPC/SPI 总线"的新风险(对桌面级 dTPM 已有公开 PoC,但需要物理接触和实验室条件)。
- Evil Maid(短暂物理接触)。攻击者短时间内可以修改 EFI 分区、shim 或 initrd 然后归还。这是 TPM + Secure Boot + 测量启动唯一能真正缓解的场景:PCR 0/2/4/7 一旦漂移,密钥就拒绝释放。
- 在线远程攻击。磁盘加密在系统运行时是"透明"的,因此对 RCE 和容器逃逸毫无作用,这部分要交给 容器加固以及 内核运行时防护。
- 内部威胁。有 root 权限的运维理论上可以
dd if=/dev/sda 拷走整盘,加密对此无效,要靠审计、最小权限和密钥托管来兜底。
说人话:TPM 自动解锁的核心价值不是"省一次输密码",而是"把启动链完整性变成密钥释放的前提"。如果你的部署没有 Secure Boot、没有 measured boot,只是把 PCR 0/7 锁死,那基本上等于把密码用便签贴在主板上。
LUKS2 基础:keyslot、KDF 与头部备份
LUKS2 把磁盘分成三层:头部(header,含 binary header 加 JSON 元数据)、keyslot 区(默认 32 个槽位,每个槽位独立加密一份 master volume key)、加密数据区。理解这三层对后续 TPM 绑定至关重要。TPM、Clevis、passphrase 都只是"开 keyslot"的方式,真正解密数据用的是同一把 master key。
2026 年用 cryptsetup 2.8+ 创建一块加密分区的推荐命令:
# 1. 用安全字段擦除标头,防止旧 LUKS 残留
cryptsetup erase /dev/nvme0n1p3 || true
# 2. 创建 LUKS2 容器(AES-XTS-Plain64 + Argon2id 默认值)
cryptsetup luksFormat \
--type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--use-random \
/dev/nvme0n1p3
# 3. 立刻备份 header(否则一旦头部损坏=数据永久丢失)
cryptsetup luksHeaderBackup /dev/nvme0n1p3 \
--header-backup-file /root/secure/nvme0n1p3.luks.header
chmod 600 /root/secure/nvme0n1p3.luks.header
# 然后把这个文件离线归档到至少两个地点
有三个细节常被忽略。第一,--key-size 512 在 AES-XTS 模式下意味着两把 256 位子密钥,这是 NIST SP 800-38E 的推荐值。第二,Argon2id 的 1 GiB 内存参数会让低配 VM 加密慢半秒左右,但极大抬高了 GPU 暴破成本。第三,头部备份不是可选项:LUKS2 的 JSON 元数据区损坏后,没有任何 fsck 等价工具能恢复。
如何用 TPM 自动解锁 LUKS 加密磁盘?
2026 年的标准做法是 systemd-cryptenroll 配合 UKI(Unified Kernel Image)。systemd-cryptenroll 从 systemd 254 起就内置了 TPM 2.0 支持,免去了过去 clevis luks bind tpm2 或裸 tpm2-tools 流程。完整步骤如下:
# 1. 确认 TPM 设备存在且为 2.0
systemd-cryptenroll --tpm2-device=list
# 期望输出类似 /dev/tpmrm0 TPM2 STM ST33HTPH
# 2. 选择 PCR 策略(这是整套方案最关键的决定)
# PCR 0 = BIOS/UEFI 固件
# PCR 2 = 选项 ROM
# PCR 4 = boot loader (shim/sd-boot)
# PCR 7 = Secure Boot 状态(db/dbx/MOK)
# PCR 11 = systemd UKI 内核 + initrd + cmdline 测量
# PCR 12/13/15 = 内核命令行/系统扩展/用户空间策略
cryptenroll_pcrs="0+2+4+7+11"
# 3. 注册 TPM 2.0 keyslot(会要求当前的 passphrase 来解锁 master key)
systemd-cryptenroll \
--tpm2-device=auto \
--tpm2-pcrs="${cryptenroll_pcrs}" \
--tpm2-with-pin=yes \
/dev/nvme0n1p3
# 4. /etc/crypttab 改成 tpm2-device 选项
echo 'root UUID=xxxx none tpm2-device=auto,tpm2-measure-pcr=15,discard' \
| sudo tee -a /etc/crypttab
# 5. 重建 initrd / UKI
sudo dracut -f --regenerate-all
# 或在 systemd-boot/sd-stub UKI 工作流中:
sudo kernel-install add-all
说几个非显然的取舍。--tpm2-with-pin=yes 再加一道 6 位以上的 PIN,可以挡住"开机就把硬盘抽走":单纯的 PCR 解锁在攻击者拿到整机后没有任何二次防御。tpm2-measure-pcr=15 让 systemd 把"已成功解锁"这件事也写进 PCR 15,后续 service 可以做 attestation。最后,0+2+4+7+11 看起来很多,但对 UKI 部署其实"够用且最稳":只锁 7 会被 initrd 替换攻击绕过,只锁 0 又会被 Secure Boot 关闭绕过。
LUKS2 和 LUKS1 有什么区别?
简短回答:LUKS1 在 2026 年应只用于和老旧 GRUB1 兼容的极端边缘场景,新部署一律选 LUKS2。下面是落到运维决策上的差异:
| 维度 | LUKS1 | LUKS2 |
| 头部格式 | 定长二进制 | 二进制 + JSON 元数据,可扩展 |
| 默认 KDF | PBKDF2-SHA256(迭代次数) | Argon2id(内存 + 并行) |
| 抗 GPU 暴破 | 弱,GPU 加速效果显著 | 强,内存硬性 KDF 抵抗 GPU/ASIC |
| keyslot 数量 | 8 | 32 |
| 令牌(token)系统 | 不支持 | 支持 TPM2/FIDO2/PKCS11/Clevis 令牌 |
| 头部恢复 | 定长备份 | JSON 校验和 + 备份头 |
| online reencrypt | 不支持 | 支持(cryptsetup reencrypt --resilience) |
| integrity 模式 | 不支持 | 支持 dm-integrity AEAD |
已有 LUKS1 盘需要在线升级:cryptsetup convert /dev/sdX --type luks2。这一步几乎"零停机",但升级前必须备份头部,因为如果中间断电,LUKS1 头会被部分覆盖。我个人在生产上倾向于"备份后做 reencrypt 而不是 convert":多花几小时,但可以同步换掉旧的 KDF 参数。
Clevis 和 Tang 是如何工作的?
当你的服务器不在桌面 TPM 范畴(比如机房刀片、边缘网关、加密备份服务器),"网络绑定磁盘加密(NBDE)"是更合适的方案。Clevis 是客户端,Tang 是无状态服务器,组合后能实现:磁盘只能在能联系到 Tang 的网络里解锁;Tang 不存任何密文,迁机房直接黑屏。
架构上 Clevis 用了一个被低估的密码学技巧,叫 McCallum-Relyea 协商:Tang 持有一对 ECMR 密钥,客户端生成临时密钥与 Tang 公钥做 ECDH 派生出"绑定密钥",然后用绑定密钥包裹 LUKS keyslot 密码。解锁时客户端再次发起 ECDH,Tang 用私钥参与计算,但看不到任何客户端机密。换句话说,哪怕 Tang 服务器整个被攻破,历史磁盘也无法离线解密。
# Tang 服务器(任意 Linux,通常和 PXE/DHCP 放一起)
sudo dnf install tang
sudo systemctl enable --now tangd.socket
# Tang 监听 80/tcp,通过 systemd socket activation 启动
sudo tang-show-keys 80
# 输出指纹,比如 tH0u-mO... 记录下来,客户端要校验
# 客户端绑定(假设已有 passphrase keyslot)
sudo clevis luks bind -d /dev/nvme0n1p3 tang \
'{"url":"http://tang.internal.lan","thp":"tH0u-mO..."}'
# /etc/crypttab 加 _netdev 让 systemd 等网络就绪
echo 'data UUID=yyyy - _netdev,discard' | sudo tee -a /etc/crypttab
# 重建 initramfs 时把 clevis 模块塞进去
sudo dracut -f --add clevis
实战经验:把 Tang 至少部署两台,并用 clevis luks bind ... sss(Shamir 秘密共享)做 t-of-n 阈值。单点故障的 Tang 等于整机房启动失败。我们在某个网段做的是 2-of-3:任意两台 Tang 在线就能解锁。详细原理可以参阅 Clevis 项目仓库的协议文档。
系统升级后 PCR 变化会导致无法启动吗?
会,而且这是 TPM 解锁部署最常见的生产事故。升级 kernel、shim、microcode,甚至打开或关闭 Secure Boot 里的 OPROM,都会改变对应 PCR 的测量值,绑定的 keyslot 立刻失效。下次启动时 TPM 拒绝释放密钥,系统停在 emergency shell。我之前替团队排查过一次半夜告警,就是因为有人偷偷给 kernel 打了热补丁。
缓解方案分两层。第一层,用 PolicyAuthorize 而不是裸 PolicyPCR:把 PCR 策略变成"签名的 PCR 列表",升级前用离线签名密钥签发新策略,TPM 看到签名匹配就放行,即使具体 PCR 值变了。systemd 257 的 systemd-pcrlock 和 --tpm2-public-key 选项就是干这个用的。
# 生成离线签名密钥(放到 HSM/智能卡里,绝对不要留在加密盘上)
openssl genrsa -out tpm-policy-signer.key 2048
openssl rsa -in tpm-policy-signer.key -pubout -out tpm-policy-signer.pub
# 注册时把公钥也写进 keyslot
systemd-cryptenroll \
--tpm2-device=auto \
--tpm2-pcrs="0+2+4+7+11" \
--tpm2-public-key=/root/secure/tpm-policy-signer.pub \
--tpm2-public-key-pcrs="11" \
/dev/nvme0n1p3
# 每次升级 kernel 前预测新 PCR,然后签名
systemd-measure calculate \
--linux=/boot/vmlinuz-6.13.1 \
--initrd=/boot/initrd.img-6.13.1 \
--bank=sha256 \
--phase=enter-initrd \
> new-policy.json
systemd-measure sign \
--private-key=/path/to/hsm/tpm-policy-signer.key \
--bank=sha256 \
--json=short \
< new-policy.json > /etc/systemd/tpm2-pcr-signature.json
第二层,永远保留一个长 passphrase keyslot(cryptsetup luksAddKey),把 32 字符随机口令打印两份,分别封进生产安全官和异地保险柜。这是最后一道"哪怕 TPM 坏了、主板换了、签名服务挂了"的兜底。LUKS2 的 32 个 keyslot 还可以多放一两个 FIDO2 应急,可以参考我们之前写过的 FIDO2 在 SSH 加固中的用法,同一把硬件 key 可以复用。
如何创建 LUKS 恢复密钥与离线运维流程?
恢复密钥是 LUKS2 keyslot 体系里成本最低、收益最高的一项投入。下面是我们目前在生产用的流程,基本能覆盖 95% 的"我打不开磁盘"工单。
- 生成 32 字节随机密钥:
head -c 32 /dev/random | base64 > /tmp/recovery.key,然后 cryptsetup luksAddKey /dev/nvme0n1p3 /tmp/recovery.key --pbkdf argon2id。
- 登记到资产系统:把 base64 密钥、磁盘 UUID、机器 hostname、生成时间、负责人塞进 Vault 或类似的密钥托管系统,并打上 TTL 与审计标签。我们用的是 Vault Transit 包一层后再存。
- 立刻 shred 临时文件:
shred -u /tmp/recovery.key,别留在 tmpfs 之外的任何地方。
- 每季度做一次解锁演练:在 staging 机用恢复密钥
cryptsetup open 一次,确认它确实可用。"备份的恢复密钥从没被验证过能用"是另一种灾难。
- 定期轮换:每 12 个月生成新恢复密钥并删除旧 keyslot,
cryptsetup luksKillSlot 干净利落。
关于密钥托管本身,2026 年我倾向于"恢复密钥放企业内部 KMS,日常 TPM 解锁在本地"。这套组合对内部威胁的爆炸半径有限:运维拿不到磁盘的 TPM 密钥(被 PCR 绑死),也拿不到恢复密钥(只有安全、合规角色能 unwrap)。想偷数据,必须串通至少两个角色。这种"双钥模型"和 systemd 服务的 capability 拆分是一脉相承的设计哲学。
生产加固清单与监控指标
把上面所有片段拼成一个可签字的部署清单,这是我每次给团队做 review 时的勾选项:
- cryptsetup ≥ 2.8,systemd ≥ 257,kernel ≥ 6.6 LTS
- LUKS2 + AES-XTS-Plain64 + 512 位密钥 + Argon2id(1 GiB / 4 并行)
- header 备份归档到至少 2 个异地位置
- keyslot 矩阵:1 个 TPM+PIN,1 个 Clevis(若 NBDE),1 个离线 passphrase,1 个 KMS 恢复密钥
- PCR 策略使用 PolicyAuthorize 配合 systemd-pcrlock 签名
- Secure Boot 开启,自有 MOK,固件设管理员密码
- /boot 与 ESP 设置 IMA/EVM 完整性签名(防 Evil Maid)
- crypttab 启用
discard 仅对桌面、SSD 寿命关键的场景;否则关闭以减少明文模式泄露
- 上报指标:解锁次数、解锁失败次数、PCR 漂移告警、恢复密钥使用次数
- 每季度演练一次"TPM 坏了、Tang 全挂"的恢复剧本
监控这块往往被忽视。journalctl [email protected] 里能看到每次解锁的 PCR 命中情况,把 "TPM2 policy rejected" 这条 grep 出来送 SIEM,任何一次出现都应该触发"主机被改"工单。这部分串接可以参考 auditd 与 ATT&CK 映射的告警规则,把"加密解锁失败"映射到 T1485 数据破坏的前置阶段。如果想再读底层规范,cryptsetup 项目的 LUKS2 on-disk format 规范是唯一权威的参考文档。
常见问题
TPM 自动解锁是不是意味着"不再需要密码"?
不是。TPM 释放密钥的前提是 PCR 测量值匹配,本质上是用"系统完整性"替代了"人脑记忆的口令"。强烈建议同时启用 --tpm2-with-pin=yes 添加 6 位以上的 PIN,否则攻击者拿到开机的机器就可以直接读取数据。
没有硬件 TPM 的旧服务器还能做自动解锁吗?
可以,用 Clevis + Tang 做网络绑定磁盘加密(NBDE)。机器只能在能联系到 Tang 服务器的网络内启动,带离网络后自动失效。fTPM、Intel PTT 也可以作为 dTPM 的替代,但要注意固件 TPM 在某些 BIOS 升级后会被重置,务必准备好恢复密钥。
LUKS2 加密会对性能有多大影响?
2026 年的 x86_64 CPU 几乎都有 AES-NI 和 VAES 指令集,AES-XTS 的吞吐量通常能跑到 5 到 10 GB/s,对 NVMe 实际是"测不出来"的开销。瓶颈反而是 Argon2id KDF,开机解锁时长 0.5 到 2 秒一次,但只发生一次。
同一块盘可以同时绑 TPM 和 Clevis Tang 吗?
可以,而且推荐这样做。LUKS2 的每个 keyslot 完全独立,可以一个放 TPM 绑定、一个放 Tang 绑定、一个放离线 passphrase。systemd 在解锁时按 crypttab 顺序尝试,任一成功即可。这是"启动失败爆炸半径"最小的配置。
云上虚拟机做全盘加密还有意义吗?
有,但威胁模型不同。云上 root volume 加密主要防御"快照泄露"和"底层存储被窃听",此时密钥应使用云 KMS 而非 TPM。参考 AWS Nitro Enclaves 或 Azure Confidential VM 的 vTPM,搭配 systemd-cryptenroll 的 --tpm2-device 同样能工作,但要确保 KMS 的 IAM 策略经过严格审计。