openLDAP 证书不受信任或已被撤销

openLDAP 证书不受信任或已被撤销

我已经花了两天时间解决这个问题,但我找不到任何解决方案。

在 master/master 场景中,两个openLDAP服务器从不同主机上的 docker 运行。ldapsearch命令或进程与协议syncrepl完美运行。 现在,我想使用有效的 LE 证书来启用,但出现错误:ldap
ldapsTLS: peer cert untrusted or revoked (0x80002) 但并非来自任何地方

版本

Docker 镜像基于debian:stable-slim(我写这些代码时是 v11.5)。Docker
主机是最新的 Debian bullseye。
slapd版本是slapd 2.4.57+dfsg-3+deb11u1

配置

/etc/ldap/ldap.conf文件

TLS_CACERT  /etc/ssl/certs/ca-certificates.crt

这是我的相关slapd配置ldif格式:

dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcIdleTimeout: 0
olcPidFile: /var/run/slapd/slapd.pid
olcSecurity: tls=0
olcTLSCACertificateFile: /etc/ssl/certs/ca-certificates.crt
olcTLSCertificateKeyFile: /etc/ldap/ssl/key.pem
olcTLSCertificateFile: /etc/ldap/ssl/fullchain.pem
structuralObjectClass: olcGlobal
olcTLSProtocolMin: 3.1
olcServerId: 001 ldaps://ldap1.exemple.com
olcServerId: 002 ldaps://ldap2.exemple.com

# Load module
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: /usr/lib/ldap
olcModuleLoad: syncprov

dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcRootDN: cn=config
olcRootPW:: REDACTED
structuralObjectClass: olcDatabaseConfig
olcSyncRepl: {0}rid=001 provider=ldaps://ldap1.exemple.com binddn="cn=config" bindmethod=simple credentials="REDACTED" searchbase="cn=config" filter="(objectClass=*)" scope="sub" attrs="*,+" schemachecking=off type=refreshAndPersist retry="5 5 300 5" timeout=1
olcSyncRepl: {1}rid=002 provider=ldaps://ldap2.exemple.com binddn="cn=config" bindmethod=simple credentials="REDACTED" searchbase="cn=config" filter="(objectClass=*)" scope="sub" attrs="*,+" schemachecking=off type=refreshAndPersist retry="5 5 300 5" timeout=1
olcMirrorMode: TRUE

测试

从 docker 主机到openLDAP客户机:
从 MacOS 主机到openLDAP客户机:
从一个openLDAP客户机到自身:
从一个openLDAP客户机到另一个openLDAP客户机:

$ openssl s_client -connect ldap1.exemple.com:636
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = ldap1.exemple.com
verify return:1
---
Certificate chain
 0 s:CN = ldap1.exemple.com
   i:C = US, O = Let's Encrypt, CN = R3
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 5112 bytes and written 392 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 4096 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)

因此,无论从哪方面看,该证书似乎都是有效的。

==========

从docker主机到openLDAPguest:
从一个openLDAPguest到自己:
从一个openLDAPguest到另一个openLDAPguest:

$ ldapsearch -x -LLL -d 1  -H ldaps://ldap1.exemple.com -D cn=config -W -b cn=config cn=config
ldap_url_parse_ext(ldaps://ldap1.exemple.com)
ldap_create
ldap_url_parse_ext(ldaps://ldap1.exemple.com:636/??base)
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP ldap1.exemple.com:636
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying 192.168.65.2:636
ldap_pvt_connect: fd: 3 tm: -1 async: 0
attempting to connect:
connect success
TLS: peer cert untrusted or revoked (0x80002)
TLS: can't connect: (unknown error code).
ldap_err2string
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

openLDAP使用内置命令从 MacOS 主机到客户机ldapsearch:使用命令
从 MacOS 主机到openLDAP客户机homebrew ldapsearch

$ ldapsearch -x -LLL -H ldaps://ldap1.exemple.com -D cn=config -w REDACTED -b cn=config cn=config
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcIdleTimeout: 0
olcPidFile: /var/run/slapd/slapd.pid
olcSecurity: tls=0
olcTLSCACertificateFile: /etc/ssl/certs/ca-certificates.crt
olcTLSCertificateKeyFile: /etc/ldap/ssl/key.pem
olcTLSCertificateFile: /etc/ldap/ssl/fullchain.pem
structuralObjectClass: olcGlobal
olcTLSProtocolMin: 3.1
olcServerId: 001 ldaps://ldap1.exemple.com
olcServerId: 002 ldaps://ldap2.exemple.com

这里,证书仅受 MacOS 主机信任,我不知道为什么。当我在配置中用替换
时,会发生相同的行为。olcTLSCACertificateFile: /etc/ssl/certs/ca-certificates.crtolcTLSCACertificateFile: /etc/ldap/ssl/fullchain.pemslapd

我需要 Docker 主机和openLDAP客户机识别 LE 证书以允许ldap*命令和进程与协议syncrepl一起工作。ldaps

我知道我可以添加TLS_REQCERT allow文件/etc/ldap/ldap.conf。但它只适用于ldap*命令,而不适用于syncrepl进程。

我错过了什么?我做错了什么?

PS:我将 DNS 条目编辑为 ldap1.exemple.com,但我使用的是真实 DNS 条目和有效的 LE 证书(没有暂存证书)

答案1

我终于明白了为什么要考虑证书untrusted or revoked

我的证书是使用 Apache HTTPD 模块mod_md带有MDMustStaple指令生成的On

OpenLDAP 不处理OCSP Stapling

我向 LE 请求了不带 OCSP 必须装订标志的新证书,现在一切都运行正常,ldap*无论是命令还是syncrepl流程。

答案2

尝试安装软件包libldap-common。它不会ldap-utils在我们的环境中作为依赖项自动安装。安装软件包后,错误消失,我们能够连接到使用 LetsEncrypt 证书的 LDAP 服务器。

如果您遇到以下错误,您也必须安装libsasl2-modules

ldap_sasl_interactive_bind_s: Unknown authentication method (-6)
    additional info: SASL(-4): no mechanism available: No worthy mechs found

答案3

理解的关键TLS: peer cert untrusted or revoked (0x80002)是解码数字。错误消息由 OpenLDAP 生成,但数字错误代码来自 GnuTLS。

https://codesearch.debian.net发现此错误消息仅在https://sources.debian.org/src/openldap/2.5.13+dfsg-5/libraries/libldap/tls_g.c/?hl=1195#L1195,这表明该数字由 存储gnutls_certificate_verify_peers2(),其手册页说:“此函数将验证对等方的证书,并将状态存储在状态变量中,作为 gnutls_certificate_status_t 值的按位或,如果证书受信任,则存储为零。”

gnutls_certificate_status_t 的值定义在格努特尔斯. 当前列表:

typedef enum {
    GNUTLS_CERT_INVALID = 1 << 1,                           //      0x2
    GNUTLS_CERT_REVOKED = 1 << 5,                           //     0x20
    GNUTLS_CERT_SIGNER_NOT_FOUND = 1 << 6,                  //     0x40
    GNUTLS_CERT_SIGNER_NOT_CA = 1 << 7,                     //     0x80
    GNUTLS_CERT_INSECURE_ALGORITHM = 1 << 8,                //    0x100
    GNUTLS_CERT_NOT_ACTIVATED = 1 << 9,                     //    0x200
    GNUTLS_CERT_EXPIRED = 1 << 10,                          //    0x400
    GNUTLS_CERT_SIGNATURE_FAILURE = 1 << 11,                //    0x800
    GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED = 1 << 12,       //   0x1000
    GNUTLS_CERT_UNEXPECTED_OWNER = 1 << 14,                 //   0x4000
    GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE = 1 << 15, //   0x8000
    GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE = 1 << 16,       //  0x10000
    GNUTLS_CERT_MISMATCH = 1 << 17,                         //  0x20000
    GNUTLS_CERT_PURPOSE_MISMATCH = 1 << 18,                 //  0x40000
    GNUTLS_CERT_MISSING_OCSP_STATUS = 1 << 19,              //  0x80000
    GNUTLS_CERT_INVALID_OCSP_STATUS = 1 << 20,              // 0x100000
    GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS = 1 << 21           // 0x200000
} gnutls_certificate_status_t;

例如,0x80002是 GNUTLS_CERT_MISSING_OCSP_STATUS + GNUTLS_CERT_INVALID。所以它直接指向与 OCSP 相关的问题。可惜错误消息太糟糕了。


在我的例子中,错误TLS: peer cert untrusted or revoked (0x42)等于 GNUTLS_CERT_SIGNER_NOT_FOUND + GNUTLS_CERT_INVALID。这仍然不是很有用。

GnuTLS 有一个命令行工具gnutls-cli可以显示更多详细信息。它与 OpenSSL 类似,openssl s_client但最好使用正确的工具,因为它们的行为并不总是相同的。在 Debian 上,它是通过 来安装的apt install gnutls-bin

# Connect to LDAPS:
$ gnutls-cli ldap.example.com:636

# Connect to LDAP with STARTTLS:
$ gnutls-cli --starttls-proto=ldap ldap.example.com:389

在我的特定情况下,问题在于我们的 LDAP 服务器配置错误,它在链中发送了两次叶证书。OpenSSL 对此没有异议,但 GnuTLS 拒绝了它。修复方法是在 LDAP 服务器配置中使用.../chain.pem而不是.../fullchain.pem。要找到根本原因,将坏 LDAP 服务器和具有相同证书的正常工作的 HTTPS 服务器之间的 gnutls-cli 输出进行比较非常有帮助。我不知道其他人是否也会遇到同样的问题,但至少这是 gnutls-cli 如何提供帮助的一个很好的例子。

$ gnutls-cli --starttls-proto=ldap example.com:389
Processed 137 CA certificate(s).
Resolving 'example.com:389'...
Connecting to '[...]:389'...
- Certificate type: X.509
- Got a certificate list of 4 certificates.
- Certificate[0] info:
 - subject `CN=*.example.com', issuer `CN=R3,O=Let's Encrypt,C=US', serial [...], EC/ECDSA key 256 bits, signed using RSA-SHA256, activated `2023-11-24 xx:xx:xx UTC', expires `2024-02-22 xx:xx:xx UTC', pin-sha256="[...]"
- Certificate[1] info:
 - subject `CN=*.example.com', issuer `CN=R3,O=Let's Encrypt,C=US', serial [...], EC/ECDSA key 256 bits, signed using RSA-SHA256, activated `2023-11-24 xx:xx:xx UTC', expires `2024-02-22 xx:xx:xx UTC', pin-sha256="[...]"
- Certificate[2] info:
 - subject `CN=R3,O=Let's Encrypt,C=US', issuer `CN=ISRG Root X1,O=Internet Security Research Group,C=US', serial 0x00912b084acf0c18a753f6d62e25a75f5a, RSA key 2048 bits, signed using RSA-SHA256, activated `2020-09-04 00:00:00 UTC', expires `2025-09-15 16:00:00 UTC', pin-sha256="jQJTbIh0grw0/1TkHSumWb+Fs0Ggogr621gT3PvPKG0="
- Certificate[3] info:
 - subject `CN=ISRG Root X1,O=Internet Security Research Group,C=US', issuer `CN=DST Root CA X3,O=Digital Signature Trust Co.', serial 0x4001772137d4e942b8ee76aa3c640ab7, RSA key 4096 bits, signed using RSA-SHA256, activated `2021-01-20 19:14:03 UTC', expires `2024-09-30 18:14:03 UTC', pin-sha256="C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M="
- Status: The certificate is NOT trusted. The certificate issuer is unknown.
*** PKI verification of server certificate failed...
*** Fatal error: Error in the certificate.

最后,请注意 gnutls-cli 会自动加载操作系统的证书颁发机构,但 ldapsearch 只有在正确配置的情况下才会加载它们。

这就是为什么ForJ9 的回答建议安装libldap-common。它是一个 Debian 包,仅包含一个文件/etc/ldap/ldap.conf(和一些文档),该文件仅包含一行未注释的行:

TLS_CACERT      /etc/ssl/certs/ca-certificates.crt

为了稳健性,您可以直接在 ldapsearch 命令行上设置此选项,如下所示:

ldapsearch -v -d 65535 -ZZ -H ldap://example.com:389/ -o tls_cacert=/etc/ssl/certs/ca-certificates.crt -x '(objectClass=*)'

相关内容