![OpenSSL/HAProxy 使用非 CA 证书验证客户端证书](https://linux22.com/image/733596/OpenSSL%2FHAProxy%20%E4%BD%BF%E7%94%A8%E9%9D%9E%20CA%20%E8%AF%81%E4%B9%A6%E9%AA%8C%E8%AF%81%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AF%81%E4%B9%A6.png)
我在配置 HAProxy 实例 (v1.8.13) 时遇到问题,该实例带有编译的 OpenSSL 支持,仅接受由以下客户端签名的证书:非 CA 证书。具体来说,我想在验证客户端证书时使用中间证书(非自签名)证书作为信任锚。
这是我正在使用的配置:
frontend myfrontend
bind *:${PORT} ssl crt /certs/haproxy-server-cert-bundle.pem ca-file /certs/intermediate_cert2.pem verify required
客户端通过满足以下证书链的证书进行连接:
client certificate -> intermediate cert1 -> intermediate cert2 (this should become the new trust anchor) -> root CA certificate
使用此配置通过客户端证书连接到 HAProxy 时会导致以下错误:
Feb 13 09:17:26 my-forwarder haproxy[108]: <ip>:<port> [13/Feb/2019:09:17:26.619] my-forwarder/1: SSL client CA chain cannot be verified
如果我指定根 CA 证书作为信任锚(ca 文件HAProxy 配置中的 config 参数)可以成功建立 TLS 握手。但是,我只想接受由证书分支签名的证书中级证书 2 -> 根 CA 证书,不是通过 ie一些其他中间证书 -> 根 CA 证书。
我尝试使用普通的 OpenSSL 验证并通过一些 OpenSSL s_server/s_client 设置重现此行为。似乎使用这些工具也存在同样的问题。
一些证据:
$ openssl verify -CAfile test-certificate-chain.pem test-cert.pem test-cert.pem: C = ..., O = ..., OU = ..., ST = ..., CN = intermediate-cert2 error 2 at 2 depth lookup:unable to get issuer certificate
将根 CA 证书附加到 -CAfile 会导致:
$ openssl verify -CAfile <(cat test-certificate-chain.pem root-ca.pem) test-cert.pem test-cert.pem: OK
为了解决这个问题,我能想到的仅有的两个选择如下:
- 创建自签名 CA 证书,对中级证书2证书的公钥。然后必须在 HAProxy 配置的ca 文件配置键。
- 通过 HAProxy 配置键配置 HAProxy 以忽略 OpenSSL 错误编号 2(无法获取颁发者证书)ca-file /certs/intermediate_cert2.pem 验证需要 ca-ignore-err 2
我对以上任一选项的安全级别都不满意。因此,我很想知道是否有“更干净”的解决方案来解决这个问题。
还有其他人遇到过类似的问题吗?
谢谢!
答案1
更新:我以稍微不同的方式解决了这个问题,因为我无法找到一种方法来信任中间(非 CA)证书,而无需通过 OpenSSL 验证证书链来信任父(CA)证书。
另一种方法是利用 HAProxy 强大的 ACL 功能。具体来说:
frontend my-frontend
...
acl my_tls_ca_issuer_acl ssl_c_i_dn(cn) -m reg ^<some-regex-matching-the-client-cert's-issuer-cn>$
tcp-request content reject unless my_tls_ca_issuer_acl
我正在配置 HAProxy,使其仅接受由与给定通用名称正则表达式匹配的实体颁发的客户端证书。这就是匹配器ssl_c_i_dn(中国)正在做(参见文档了解详情)。
通过实现这一点,不幸的是,我只能匹配客户端证书(中间证书 1)的颁发者/父级的专有名称(DN),而不能匹配其祖父级(中间证书 2)。
我仍然希望这对某些人有帮助。