让整个系统信任,还是只让一个仓库信任
一句话总结
RHEL 系列的私有 CA 要放进 /etc/pki/ca-trust/source/anchors/,再用 update-ca-trust extract 传播到整个系统。但是,让整个系统都信任它并不总是正确答案。如果只需要用另一个 CA 来确认某一个仓库,.repo 中的 sslcacert 就能缩小这个范围。
为什么需要它
隔离网络 RHEL 服务器上的 dnf 查看内部仓库。一旦把这个仓库搭成 HTTPS,就会出现 Curl error (60) 一类的错误,并伴随 Cannot download repomd.xml。常见的权宜之计是 sslverify=0。这样一来,内网里冒充仓库的任何人,都可以提供软件包列表。仓库元数据是决定“安装什么、对应什么哈希”的文档,不确认这份文档的来源,就等于把整个安装都托付出去。
工作原理
系统信任库。 根据 RHEL 9 文档,把证书放在 /etc/pki/ca-trust/source/anchors/(或优先级较低的 /usr/share/pki/ca-trust-source/anchors/),再运行 update-ca-trust extract。PEM 和 DER 都可以接受。确认可以用 p11-kit 的 trust list,添加和移除也可以用 trust anchor <파일>(占位符为证书文件)和 trust anchor --remove。在这个实验镜像(Rocky 9.3)中查看,/etc/pki/tls/certs/ca-bundle.crt 是指向 /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem 的符号链接。extract 重新写入的,就是这个 extracted 之下的文件,curl、dnf 这类查看系统证书包的工具,读取的就是它的结果。
只让一个仓库被信任。 dnf 配置文档把仓库选项 sslcacert 写成“用于验证 SSL 证书的 CA 文件路径,为空时使用系统默认值”,并把 sslverify 的默认值写为真。如果必须下载合作方用自己的 CA 搭建的仓库,却不想让服务器上所有程序都信任那个 CA,就只在该仓库的 .repo 中写入 sslcacert。这是把信任范围缩小到所需程度的办法。
创建仓库。 createrepo_c <디렉터리>(占位符为目录)会读取 rpm,生成 repodata/(repomd.xml 以及 primary、filelists、other)。dnf 从 baseurl 之下的 repodata/repomd.xml 开始下载。Web 服务器只需提供文件即可。
签名检查是另外一回事。 TLS 确认的是“这台仓库服务器对不对”,rpm 的 GPG 签名(gpgcheck)确认的是“这个软件包是不是发行版制作的”。从官方仓库复制来的 rpm 原本就带有签名,所以把发行版的公钥(/etc/pki/rpm-gpg/)通过 gpgkey 指向,在内部仓库中也可以在开启签名检查的情况下安装。“因为是内部仓库,所以可以关闭两者之一”,这种逻辑不成立。
在现场相遇的样子
我们在这个实验镜像中实测过。用私有 CA 证书启动 HTTPS 仓库,并通过 .repo 指向它,dnf makecache 先出现 Curl error (60): SSL peer certificate or SSH remote key was not OK ... [SSL certificate problem: unable to get local issuer certificate],然后以 Cannot download repomd.xml ... All mirrors were tried 在 0.3 秒内结束(如果加上 -q,前面的原因行就会消失,只剩最后一行,所以记录时要去掉它再运行)。把根证书放进 anchors 并运行 update-ca-trust extract 之后,trust list 中出现了 label: Airgap Internal Root CA、trust: anchor、category: authority,同一条命令就通过了。安装 tree 后,dnf info --installed tree 的 From repo 是 airgap——是从哪个仓库安装的,就用这一行来确认。
下一项实验要做什么
用离线仓库中的 rpm 制作 /srv/rpmrepo,并用私有 CA 证书以 HTTPS 在 repo.airgap.internal:8443 启动。编写 .repo 并记录失败之后,通过 anchors 和 update-ca-trust 让系统信任它,并安装 tree。最后,用 sslcacert 让另一个 CA 搭建的第二个仓库,只有那个仓库被信任。
参考文档:RHEL 9——Using shared system certificates、trust(1)、DNF Configuration Reference(sslcacert、sslverify)