使用Let's Encrypt证书的389 Directory Server LDAP复制失败,提示'unable to get issuer certificate'
我完全理解你遇到的这个头疼问题——明明Let's Encrypt的CA应该是系统默认信任的,但389 Directory Server的复制偏就卡在证书验证上了。咱们先把问题理清楚,再一步步找解决办法:
问题回顾
你在两台Fedora 37的389 DS实例($SUPPLIER和$CONSUMER)间配置LDAP复制,两者都用Let's Encrypt证书,供应商的客户端都能正常通过ldaps://连接,但从供应商到消费者的复制失败,日志抛出核心错误:
[02/May/2023:14:28:07.389193770 +0200] - ERR - NSMMReplicationPlugin - bind_and_check_pwp - agmt="cn=Synchronize with $CONSUMER" (ldap3:636) - Replication bind with SIMPLE auth failed: LDAP error -1 (Can't contact LDAP server) (error:0A000086:SSL routines::certificate verify failed (unable to get issuer certificate)) [02/May/2023:14:28:10.408516918 +0200] - ERR - slapi_ldap_bind - Could not send bind request for id [cn=replication manager,cn=config] authentication mechanism [SIMPLE]: error -1 (Can't contact LDAP server), system error -5987 (Invalid function argument.), network error 0 (Unknown error, host "consumer.mydomain.example:636")
已验证的有效操作(排除基础网络/证书问题)
你已经做了不少排查,这些操作能排除很多基础问题:
- dsconf连接验证正常:从供应商用复制管理员账号连接消费者的监控接口完全没问题:
返回了正常的服务器版本等监控信息,说明账号、网络、证书本身是有效的。user@supplier.mydomain.example$ dsconf -D "cn=replication manager,cn=config" ldaps://consumer.mydomain.example:636 monitor server - openssl s_client证书链验证通过:直接用openssl测试消费者的LDAPS端口,证书链从服务器证书到R3中间再到ISRG Root X1根证书都验证通过:
最终输出user@supplier.mydomain.example$ echo -n "" | openssl s_client -showcerts consumer.mydomain.example:636Verify return code: 0 (ok),证明系统层面能正确信任这个证书链。 - 系统信任列表包含根证书:通过
trust list能看到ISRG Root X1被标记为信任锚(anchor),系统默认信任链是完整的。
另外你提到的单独用openssl verify验证导出的服务器证书失败,这个确实是个“红鲱鱼”——因为单独的服务器证书没有包含中间链,openssl默认找不到完整验证路径,这个失败是正常的,不用纠结。
可能的解决方向
既然系统层面信任没问题,但389 DS的复制进程不认,大概率是389 DS自身的证书信任配置或者库依赖问题,试试下面几个方案:
1. 确认389 DS自身的证书数据库包含Let's Encrypt链
389 DS可能不使用系统默认的信任存储,而是有自己的证书数据库(通常在/etc/dirsrv/slapd-<你的实例名>/下,文件是cert9.db或cert8.db)。你可以用certutil检查里面的证书:
certutil -L -d /etc/dirsrv/slapd-<供应商实例名>/
如果看不到ISRG Root X1和Let's Encrypt R3中间证书,就需要导入它们:
# 导入ISRG Root X1根证书 certutil -A -n "ISRG Root X1" -t "C,," -d /etc/dirsrv/slapd-<供应商实例名>/ -i /path/to/isrgrootx1.pem # 导入R3中间证书 certutil -A -n "Let's Encrypt R3" -t "C,," -d /etc/dirsrv/slapd-<供应商实例名>/ -i /path/to/r3.pem
导入后重启389 DS服务:
systemctl restart dirsrv@<供应商实例名>.service
2. 给复制连接手动指定CA证书链
可以在复制协议的配置里,明确指定包含完整证书链的文件,让389 DS复制进程用这个路径去验证:
dsconf ldap://supplier.mydomain.example repl-agmt set "cn=Synchronize with $CONSUMER" --tls-ca-file /etc/letsencrypt/live/consumer.mydomain.example/fullchain.pem
这里的fullchain.pem是消费者服务器上Let's Encrypt生成的包含服务器证书+中间证书的文件,你也可以自己合并根证书和中间证书生成这个文件。
3. 检查389 DS的OpenSSL库依赖
389 DS可能链接了和系统默认不同的OpenSSL库,导致无法读取系统信任链。你可以检查进程使用的库:
lsof -p $(pidof ns-slapd) | grep libssl
如果发现使用的不是系统默认的libssl.so(比如路径不在/usr/lib64/下),可能需要调整389 DS的依赖,或者重新安装389 DS包,确保它使用系统默认的OpenSSL库。
4. 检查复制协议的TLS配置细节
确认复制协议的配置里,TLS相关的参数正确:
- 查看复制协议的配置条目,检查
nsDS5ReplicaTransportInfo是否设置为LDAPS,nsDS5ReplicaBindMethod是否为SIMPLE(符合你的配置)。 - 确保没有意外设置了禁用证书验证的参数(比如
nsDS5ReplicaTLSVerifyCert如果设为off会跳过验证,但不建议长期这么用,只是临时测试用)。
备注:内容来源于stack exchange,提问作者TuringTux

