PostgreSQL安全认证:多客户端证书选择,简单的 POC


作者:黄品凯(Cary Huang)

Cary是HighGo Software Canada的高级软件开发人员,在加入HighGo之前,他在智能电网和计量领域拥有8年的C/ c++开发创新软件解决方案的行业经验。他于2012年在温哥华英属哥伦比亚大学(UBC)获得电气工程学士学位,并在以下技术方面拥有丰富的实践经验:高级网络,网络和数据安全,智能计量创新,部署管理与Docker,软件工程生命周期,可扩展性,身份验证,密码学,PostgreSQL和非关系数据库,web服务,防火墙,嵌入式系统,RTOS, ARM, PKI,思科设备,功能和架构设计。

 

发表于 2024年2月23日

 

原文链接:

https://www.highgo.ca/2024/02/23/multiple-client-certificate-selection-a-simple-poc/


介绍

我最近看到了几年前的电子邮件线程讨论,其中讨论了使客户端能够从客户端证书列表中进行选择以发送到服务器的方法。好处是显而易见的;当客户端必须与具有不同 TLS 设置和信任结构的不同 PostgreSQL 服务器进行通信时,该功能可以帮助减少应用程序确定要发送到哪个服务器的证书的工作量。换句话说,应用程序不需要有这个选择逻辑,因为 libpq 库能够选择正确的发送逻辑。

OpenSSL 为 PostgreSQL 提供了 TLS 和其他加密功能,并且在过去几年中也取得了重大进展。现在,它拥有更多的 API 支持,使应用程序能够做出更明智的 TLS 决策。例如,选择最合适的客户端证书以在握手期间发送到服务器。今天,在这篇文章中,我将简要解释证书信任链的工作原理,并分享“多客户端证书选择”补丁(如果有一个)。


什么是TLS、Certificate、Trust Chain?


TLS:传输层安全性

以前称为 SSL(安全套接字层)。现在这两个术语可以互换使用。这是一种用于加密和保护网络通信的协议。它有 2 个主要职责:

1. 通信加密/解密+完整性检查。

2. 使用证书验证双方的身份。


Certificate:证书

也称为 X509 v3 证书,或简称为 X509 证书。它是一种包含有效性、颁发者、扩展、目的和其他自定义信息的数据结构。主要用于表示实体的身份和确保信任。它有三种基本类型:

1. 证书颁发机构 – 也称为 CA 证书或根 CA.(IdenTrust、DigiCert、GlobalSign、Let's Encrypt 等是常见的 CA。它也可以用于测试目的的自签名)。

2. 中间 CA 证书。

3. 实体证书 – 用于通信的实际证书。它们在 TLS 握手期间交换。在大多数情况下,服务器将其证书发送到客户端仅用于验证,但在某些情况下,客户端还必须将其证书发送到服务器进行验证,也称为相互验证。


Trust Chain:信任链

确定实体证书是否可信的条件之一。如果我们能够“建立”从此证书一直到受信任的根 CA 的路径,那么该证书就可以被信任(假设它尚未过期)。此“路径”描述证书的颁发涉及多少个“签名者”,此路径也称为信任链。


几个案例

请考虑此证书设置,其中客户端和服务器证书由中间 CA-1 和 CA-2 签名,两者都由公共根 CA 颁发。


不信任案例

如果 PostgreSQL 客户端和服务器具有以下证书配置,则它们不会相互信任,因为任何一端都无法建立到公共根 CA 的可信路径。


信任案例

如果 PostgreSQL 客户端和服务器具有以下证书配置,则它们可以相互信任,因为两端都能够建立到公共根 CA 的可信路径:

1. 客户端证书 -> 中间 CA 1 ->根 CA

2. 服务器证书 -> 中间 CA 2 ->根 CA

中间 CA 和实体证书组合案例

有一种情况是,PostgreSQL 客户端和服务器都只有根 CA 证书配置为“信任锚”。他们没有配置任何中间 CA 证书,很可能是因为他们不知道有多少个。

为了确保信任,我们可以将中间 CA 证书附加到同一实体证书文件中(由下面的虚线表示)并发送给另一个对等方这很重要,因为客户端或服务器可以使用收到的中间 CA 证书来构建公共根 CA 的路径,因此在下面的情况下,客户端和服务器可以相互信任。


PostgreSQL 中的多客户端证书

现在我们已经了解了TLS协议如何借助证书和信任链确保客户端和服务器之间的信任的基础知识。然后,我们可以看看如何使 PostgreSQL 的 libpq 客户端选择要发送的最佳证书。方法如下:

1.  除了库已经支持的sslcert和sslkey之外,还添加了两个新的连接参数sslcertdir和sslkeydir。这两个新参数指明了所有证书和私钥候选目录的路径。它将从这些目录中选择最好的一个来使用。

2. 注册一个cert_cb回调函数,当客户端从服务器接收到“证书请求”时,OpenSSL将在握手期间调用该函数。这使我们有机会执行一些逻辑并设置要发送到服务器的所需证书。下面演示了何时调用cert_cb。并调用Verfiy_cb以使我们有机会检查对等证书。我们不会修改这个。

3. 在cert_cb中,我们将调用SSL_get0_peer_CA_list(ssl)来获取在服务器端配置的CA名称列表。此列表将帮助客户端选择证书。标准是这样的,如果证书的颁发者名称等于接收到的CA名称之一,那么该证书就是要使用的证书。这在大多数情况下都有效,但有一个限制,我们将在后面讨论它。

4. 打开sslcertdir并尝试查找具有3中提到的匹配条件的证书。如果找到一个,我们就尝试从sslkeydir中寻找匹配的键。

5. 最后,我们将在返回cert_cb函数之前设置新的证书和密钥,以便握手可以继续。


限制

1. 只有在服务器端配置了所有可能的CA证书时,客户端证书选择功能才有效。这包括所有根CA和中间CA证书,并假设配置的所有中间CA证书都是可信的。然而,情况可能并非总是如此。

2.  如果客户端证书是由中间证书颁发的,并且服务器没有将其与其根 CA 一起配置,则选择功能可能无法正常工作。这是因为该功能依赖于受信任的 CA 名称进行选择,因此它尚未分析附加到同一客户端证书文件的潜在中间 CA 证书。这可以在将来的版本中得到增强。

3. 加密私钥文件:如果sslkeydir下的私钥文件使用密码加密,则只能使用相同的密码(由sslkeypassword选项配置)。在搜索匹配的密钥时,不能使用不同的密码解密不同的密钥文件。


补丁

可在以下链接中找到此功能的 POC 修补程序,欢迎尝试一下。

https://www.postgresql.org/message-id/18d9f7b038e.bed67b1955405.5750105560039769878@highgo.ca


本文分享自微信公众号 - 开源软件联盟PostgreSQL分会(kaiyuanlianmeng)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部