我们来详细介绍一下 Ubuntu 20.04 中 /etc/apt/keyrings
这个目录的作用。
简单来说,这是一个专门用于存放 APT 软件包管理器 GPG 密钥的现代化、更安全的路径。它的出现是为了解决旧有密钥管理方式(apt-key
)的重大安全隐患。
为了完全理解它的重要性,我们需要对比一下“旧的方式”和“新的方式”。
1. 背景:为什么需要 GPG 密钥?
当你在 Ubuntu 中使用 apt install
安装软件时,软件包并非凭空而来,而是从配置好的软件源(Repository)服务器上下载的。
为了确保你下载的软件包是官方发布的、未经篡改的,并且来源是可信的,软件源的维护者会使用他们的私有 GPG 密钥对软件包列表(Release
文件)进行数字签名。
你的系统(APT)则需要拥有对应的公有 GPG 密钥,用它来验证这个签名。如果验证通过,APT 才会信任并安装来自这个源的软件包。这个过程保证了软件的真实性(Authenticity)和完整性(Integrity)。
2. 旧的方式(不推荐):apt-key
和 /etc/apt/trusted.gpg.d/
在过去,当你需要添加一个第三方软件源(比如 Google Chrome、VS Code 等)时,官方文档通常会指导你这样做:
# 下载密钥并用 apt-key 添加
wget -qO - https://example.com/key.asc | sudo apt-key add -
这个 apt-key add
命令会将 GPG 公钥添加到一个全局信任的密钥环中。这些密钥通常存放在:
/etc/apt/trusted.gpg
(一个单一的、集中的文件)/etc/apt/trusted.gpg.d/
(一个存放多个密钥文件的目录)
这种方式的严重安全问题在于:
存放在全局信任区里的任何一个密钥,都会被 APT 用来信任系统上配置的所有软件源。
举个例子:
你添加了 “CoolApp” 的软件源和它的 GPG 密钥。现在,这个密钥被放在了全局信任区。如果 “CoolApp” 的密钥被泄露,或者其服务器被黑客控制,攻击者不仅可以伪造 “CoolApp” 的软件包,还可以用这个被泄露的密钥来签名一个伪造的、恶意的 Ubuntu 系统更新包。因为 APT 在更新系统时,看到这个签名来自一个“受信任”的密钥,它就会接受这个恶意的更新,从而导致你的整个系统被攻破。
这就是所谓的**跨软件源信任(Cross-repository Trust)**问题,是一个巨大的安全漏洞。
3. 新的方式(推荐):/etc/apt/keyrings
为了解决上述安全问题,Debian 和 Ubuntu 引入了更精细、更安全的密钥管理方式。核心思想是:一个密钥只应该被用来信任它所对应的那个软件源。
/etc/apt/keyrings
目录就是为此而生的。它的工作流程如下:
-
独立存放密钥:你不再将 GPG 密钥添加到全局信任区。而是将每个第三方软件源的 GPG 密钥(通常是
.gpg
或.asc
文件)单独存放在/etc/apt/keyrings/
目录下。例如,你可以将 Visual Studio Code 的密钥存为/etc/apt/keyrings/vscode.gpg
。 -
在源配置中明确指定密钥:在添加软件源的配置文件时(通常是在
/etc/apt/sources.list.d/
目录下的.list
文件),使用[signed-by=...]
选项,明确告诉 APT 这个软件源应该由哪个具体的密钥来验证。
这样做的好处是:
APT 只会使用
/etc/apt/keyrings/vscode.gpg
这个密钥来验证来自 VS Code 软件源的包。它绝对不会用这个密钥去验证 Ubuntu 官方源或其他任何第三方源的包。
这样就实现了信任的隔离。即使 “CoolApp” 的密钥被泄露,攻击者也无法用它来伪造其他任何软件源的包,安全风险被控制在了最小范围。
实践对比:添加 VS Code 软件源
旧方式(不安全)
# 1. 下载密钥并添加到全局信任区
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
# 2. 添加软件源(没有指定密钥)
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
# 3. 更新并安装
sudo apt update
sudo apt install code
在 Ubuntu 20.04 中,apt-key
仍然可用,但已被标记为“弃用”(deprecated),在更新时可能会看到相关警告。
新方式(安全,推荐)
# 1. 安装依赖
sudo apt-get update
sudo apt-get install -y apt-transport-https gpg
# 2. 下载微软的 GPG 密钥,并保存到 /etc/apt/keyrings/ 目录
curl -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/keyrings/microsoft.gpg > /dev/null
# 3. 添加软件源,并使用 [signed-by=...] 明确指定密钥路径
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/vscode stable main" | sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null
# 4. 更新并安装
sudo apt update
sudo apt install code
注意看第 3 步中的 signed-by=/etc/apt/keyrings/microsoft.gpg
,这正是新方式的核心。
总结
特性 | 旧方式 (apt-key ) | 新方式 (/etc/apt/keyrings ) |
---|---|---|
密钥存放位置 | /etc/apt/trusted.gpg 或 /etc/apt/trusted.gpg.d/ | /etc/apt/keyrings/ |
信任范围 | 全局信任:一个密钥信任所有软件源 | 精确信任:一个密钥只信任一个特定软件源 |
安全性 | 低,存在跨软件源攻击风险 | 高,实现了信任隔离 |
配置方式 | apt-key add | 在 sources.list 文件中使用 [signed-by=...] |
当前状态 | 已弃用(Deprecated) | 官方推荐 |
在 Ubuntu 20.04 这个版本中,你正处于一个过渡期。旧的方法仍然有效,但系统已经开始鼓励并全面支持新的、更安全的方法。因此,当你现在需要添加任何新的第三方PPA或软件源时,都应该优先采用 /etc/apt/keyrings
这种方式。
你添加了 “CoolApp” 的软件源和它的 GPG 密钥。现在,这个密钥被放在了全局信任区。如果 “CoolApp” 的密钥被泄露,或者其服务器被黑客控制,攻击者不仅可以伪造 “CoolApp” 的软件包,还可以用这个被泄露的密钥来签名一个伪造的、恶意的 Ubuntu 系统更新包。因为 APT 在更新系统时,看到这个签名来自一个“受信任”的密钥,它就会接受这个恶意的更新,从而导致你的整个系统被攻破。
但是如果“CoolApp” 的密钥被泄露,或者其服务器被黑客控制,他发布了一个有问题的恶意更新,不管是什么密钥不是都会出问题吗
你的问题触及了 APT 密钥管理的核心安全机制,关键在于 密钥的作用范围 和 APT 的信任模型。以下是详细分析:
1. 旧方法(全局信任)的风险
如果直接将 CoolApp 的密钥添加到全局信任区(如 /etc/apt/trusted.gpg
或通过 apt-key add
):
- 密钥的作用范围:该密钥会被视为“系统级受信任”,不仅能验证 CoolApp 的软件包,还能验证任何其他仓库的包(包括 Ubuntu 官方仓库)。
- 攻击场景:
- 如果 CoolApp 的密钥泄露,攻击者可以用它签名一个伪造的
ubuntu-focal-security
包(假设包名和版本与官方一致)。 - APT 在更新时发现该包由“受信任”的密钥签名(因为密钥在全局信任区),会直接放行,导致系统被植入恶意软件。
- 如果 CoolApp 的密钥泄露,攻击者可以用它签名一个伪造的
2. 新方法(signed-by
限定作用范围)的安全性
如果将 CoolApp 的密钥放在 /etc/apt/keyrings/coolapp.gpg
,并在源文件中明确指定 [signed-by=/etc/apt/keyrings/coolapp.gpg]
:
- 密钥的作用范围:该密钥仅用于验证 CoolApp 的仓库,与其他仓库(如 Ubuntu 官方源)无关。
- 攻击场景:
- 即使 CoolApp 的密钥泄露,攻击者也无法用它伪造 Ubuntu 官方更新包,因为官方仓库的验证使用的是 Ubuntu 自己的密钥(存储在
/usr/share/keyrings/ubuntu-*.gpg
)。 - 攻击者只能伪造 CoolApp 的包,但无法影响其他仓库。
- 即使 CoolApp 的密钥泄露,攻击者也无法用它伪造 Ubuntu 官方更新包,因为官方仓库的验证使用的是 Ubuntu 自己的密钥(存储在
3. 为什么作用范围限定能解决问题?
- 密钥与仓库的绑定关系:
signed-by
显式声明了“哪个密钥对应哪个仓库”,APT 会严格按此规则验证。即使密钥泄露,也无法跨仓库滥用。 - 隔离性:
第三方密钥的泄露不会污染系统全局信任链,官方仓库和其他第三方仓库的验证互不影响。
4. 如果 CoolApp 的密钥泄露,是否仍会出问题?
- 是的,但影响范围不同:
- 旧方法(全局信任):整个系统的任何包都可能被伪造(灾难性后果)。
- 新方法(
signed-by
):仅 CoolApp 的包可能被伪造(局部风险)。
- 缓解措施:
- 及时撤销泄露的密钥(通过仓库更新通知)。
- 使用更安全的密钥分发方式(如密钥轮换、硬件安全模块 HSMs)。
5. 类比说明
- 旧方法:像把 CoolApp 的钥匙放在你家大门钥匙串上(小偷拿到后能开所有门)。
- 新方法:像为 CoolApp 单独配一把钥匙,并标明“仅用于 CoolApp 抽屉”(小偷拿到后只能开这个抽屉)。
总结
- 全局信任的密钥:一旦泄露,等同于系统所有包失去信任基础。
signed-by
限定作用范围:将风险限制在单一仓库内,是更安全的现代实践。
结论:密钥泄露仍会导致该仓库的包被伪造,但不会连锁影响整个系统。这就是为什么 Ubuntu/Debian 推荐使用/etc/apt/keyrings/
和signed-by
。