haproxy返回的服务器证书为何混入CA bundle根证书及调整方法
异常现象根本原因
当前配置下两个核心参数的生效逻辑存在职责错位,是触发所有异常的根源:
ca-file参数在当前配置中同时承担两个功能:一是作为客户端证书校验的信任锚池,用来验证客户端上传的证书链是否合法;二是当crt参数指定的服务端PEM文件仅包含单张叶子服务器证书、没有附带匹配的中间证书时,HAProxy会自动从ca-file的证书池中匹配和当前服务器证书有签发关系的证书,自动拼接成最长可到达信任根的完整证书链,附在服务端响应的证书列表里返回给客户端。- 你之前尝试删除ca-bundle中根证书的操作会触发两个连锁反应:
- HAProxy拼服务端返回链时,因为ca-bundle里没有了根证书,无法继续往上凑到根层级,最终返回的链就只剩服务器证书+对应中间证书,符合业务要求;
- 但因为客户端证书校验需要依赖ca-bundle中的根证书作为最终信任锚,缺少根证书后校验流程直接找不到可信终点,自然导致客户端证书校验功能失效。
- 之前出现证书链冗余的核心原因:
crt参数指定的服务器PEM文件没有把和自身匹配的中间证书预先拼入,把证书链拼接的工作完全丢给了HAProxy基于ca-file的自动匹配逻辑,才会出现附带根证书的问题。
符合业务要求的调整方案
整个方案的核心是拆分证书的使用场景,不让自动拼链逻辑跨场景生效,具体操作步骤:
- 第一步,拆分证书文件为两个独立用途的PEM资源:
- 制作服务端专用证书PEM文件:按顺序将「单张服务器证书原文」+「和该服务器证书严格匹配的对应中间证书(G1/EV中对应签发服务器证书的那张)」拼接为一个PEM文件,不要将根证书拼入这个文件;如果原文件里有对应的私钥,直接保留在文件中即可。
- 制作客户端校验专用CA信任PEM文件:将原混合CA bundle里的所有根证书、所有中间证书完整保留到这个新PEM文件里,不做任何删减,保证客户端证书校验的信任锚池完整。
- 第二步,调整HAProxy的bind配置参数:
将原配置的crt和ca-file参数指向新制作的两个独立PEM文件,调整后的bind配置为:
调整后逻辑生效原理:frontend https mode http bind *:443 accept-proxy ssl verify optional crt-ignore-err all crt <SERVER-CERT-CHAINS-NO-ROOT>.pem ca-file <FULL-CLIENT-TRUST-CA>.pem crl-file <CRL-FILE>.crl default_backend ssl-proxy- 因为
crt指定的服务端PEM已经预先包含了完整的“服务器证书+对应中间证书”链,HAProxy会直接使用这个预配置的链作为服务端返回的证书列表,不会再额外从ca-file中捞取其他证书(包括根证书)拼接到返回链中,最终实现返回链仅包含要求的两张证书。 - 因为
ca-file指定的信任池是完整保留了所有根、中间证书,客户端证书校验时依然可以从这个池子里找到对应的信任锚完成校验,不会出现之前移除根导致的校验失效问题。
- 因为
- 第三步,上线前验证:
用openssl s_client -connect <HAProxy监听地址>:443 -showcerts检查服务端返回的证书链,确认输出的证书数量为2(服务器证书+对应中间证书)、无根证书;同时携带合法客户端证书发起请求,确认校验流程正常、CRL校验逻辑无异常。
注意:服务端crt文件里拼接的中间证书必须和服务器证书为直接签发关系,不能错配其他层级的证书,否则会触发证书链不匹配的告警。
内容的提问来源于stack exchange,提问作者botenbreuk
相关产品推荐
相关产品推荐

