HTTPS 和 VPN 并不认证你安装的软件包
加密传输保护的是通路,而不是发布者。比较 apt 与 dnf5 实际检查了什么,然后在动密钥之前找出是哪一层边界失败了。
一次更新失败,帖子里的建议沿着熟悉的思路走:流量经过 VPN,所以下载必定可信,于是放宽签名校验来绕过报错。两个不同的概念被并成了一句。加密保护的是两端之间的通路;认证决定的是这些字节是否来自你预期的发布者。隧道提供前者,对后者只字未提。
症状通常只在一台主机、一个仓库上出现校验错误,其余一切照常更新。这个形态已经说明网络通路是通的,分歧在于信任。
回答不同问题的两种控制
传输安全回答的是这条连接的另一端是谁,以及路径上是否有人能读取或改动它。软件包认证回答的是这个产物是否由你配置的权威发布,而且它必须经受住经由你无法控制的镜像下载。
这两个问题只在边缘处重叠。镜像上一张正确的证书证明镜像就是镜像;它并不证明镜像持有未被改动过的发布者内容。一个已签名的软件包证明发布者签了它;它不会告诉你网络送来了最新版本,也不会告诉你所指向的仓库就是组织批准的那一个。
人们靠关掉检查所制造出来的失效模式,是永久失去第二重保障,换来一次下载成功。这笔交易直到真正要紧的那天才显形。
apt 到底认证了什么
APT 的模型是一条经过认证的归档链。已签名的发布元数据通过校验和指向软件包索引,这些索引再通过校验和指向一个个软件包文件。正是链条的验证让镜像可以不被信任却仍可使用:镜像想提供什么都行,由元数据的签名决定 APT 是否接受。
这刻意不同于对每个已安装软件包检查维护者签名,这个区别也解释了为什么缺陷报告里「软件包已签名」和「归档已认证」会被混着用:前者只说明某个软件包自身带有签名,后者说明整条归档链经过校验,而它们说的并不是一回事。
apt-get update
apt-cache policy
apt-config dump | grep -iE 'AllowInsecure|AllowDowngrade'
要读更新的输出,而不只看退出码。APT 会指名元数据校验失败的仓库,这个名字就是要查的边界。被标记为可信却不校验签名的仓库,或者为不安全仓库设置的覆盖项,都是某个人做出的配置决定,他应该能解释清楚。
新鲜度又是另一项属性。一个签名有效的元数据文件可能比你上周看到的更旧,所以发布元数据带有有效期,也所以客户端上的时钟问题会造成看起来像密钥问题的校验失败。
dnf5 单独检查什么
RPM 一侧暴露了两个不同的开关,把它们混为一谈就会在另一个方向上犯同一类错误。一个管软件包文件是否必须带有效签名,另一个管仓库元数据是否必须被签名。两者可以独立设置,系统完全可能对一个严格、对另一个宽松。
dnf5 config-manager --dump 2>/dev/null | grep -iE 'gpgcheck|repo_gpgcheck'
rpm -q --qf '%{NAME} %{SIGPGP:pgpsig}\n' bash
软件包查询会显示已安装副本的签名元数据长什么样,这是对声称严格的配置文件的一次有用核对:配置文件说得很严,实际记录下来的签名信息却可能是另一回事。它不会告诉你的是发行版所支持的策略,而这才是你该遵循的,而不是论坛上「开启 GPG」的通用指令。
两个管理器不同之处,差异是架构性的,而不是某一方更弱的信号。两者都认证发布者内容;它们把签名放在链条的不同位置。
隧道加上了什么,又没加上什么
VPN 可以提供一条必需的路由,让更新流量避开不可信的接入网,并减少本地观察者能看到的东西。这些都是实实在在的运维收益,但没有一项是发布者认证。
HTTPS 加上了自己的保障,而且它比感觉上要窄。它认证的是你所连接的 TLS 端点。如果那个端点是镜像,你认证的是镜像,而不是它提供的归档内容。这正是签名元数据链条存在的场合。
两种控制都不承诺可用性。网络可以拒绝投递,而经过认证的对象也不自动就是最新的。请使用软件包管理器自己的新鲜度策略,而不是从有没有锁形图标去推断。
诊断失败的那一层边界
在改动任何东西之前先点名阶段:DNS 解析、代理或路由、TLS 端点身份、归档认证、软件包签名检查,或者安装。每一层都有各自的错误形态和各自的负责人。
修复网络通路绝不该包含把陌生签名密钥声明为可信、忽略证书,或者接受你没要求的仓库配置。如果密钥确实轮换了,发行版或仓库所有者会通过你能验证的渠道公布新密钥,那才是应当采取的更正,而不是在本地把校验关掉。
写下哪一层边界失败、由谁负责。下一次更新失败会发生在另一层边界上,而手里有这份清单,就能把它变成五分钟的诊断,而不是又一场关于隧道是否让更新变安全的争论。