| Tested on | Rocky Linux 10.2 (Red Quartz) |
|---|---|
| Package | 389-ds-base 3.2.0-8.el10_2 |
| Applies to | RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora |
| Privilege | sudo or root |
| Scope | Fix LDAP works but LDAPS fails: port 636, TLS handshake, trust, hostname matching, and certificates. Does not cover unrelated LDAP error codes. |
| Related guides | Install 389 Directory Server 389 DS TLS Certificate management dsconf commands Fix LDAP invalid credentials error 49 |
LDAP works but LDAPS fails is a common production pattern: directory data is reachable over ldap:// on port 389, while applications, scripts, or ldapsearch against ldaps:// on port 636 time out, refuse the connection, or exit before bind with a generic client error. SSSD, Apache, replication tools, and backup jobs often show the same split when only the secure URI was changed.
Typical LDAPS failures look like this on the client:
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)With debug output enabled, the same session often reveals the underlying TLS problem:
TLS certificate verification: Error, self-signed certificate in certificate chain
TLS: can't connect: error:0A000086:SSL routines::certificate verify failed (self-signed certificate in certificate chain).
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)Plain LDAP on the same client can still return directory data:
dn:
namingContexts: dc=example,dc=comA failed TLS handshake may never reach the LDAP bind stage, so the access log on the server can show no bind attempt for the failed client session. Separate port or listener failures from certificate-validation failures from LDAP bind failures after TLS succeeds.
Use the diagnosis table below to jump to the fix that matches your situation. Initial TLS setup, certificate renewal, and cipher policy stay in the linked chapters.
Examples use instance ldap1 on ldap1.example.com with LDAP port 389 and LDAPS port 636, suffix dc=example,dc=com, and server address 192.0.2.10 in DNS examples. Use the same DNS hostname in client URIs, certificates, and firewall rules.
Keep server-side and client-side paths separate:
| Location | Path |
|---|---|
| Server NSS database | /etc/dirsrv/slapd-ldap1/ |
| CA exported on the server | /tmp/ds-ca.crt |
| CA installed on the client | /etc/pki/ca-trust/source/anchors/ds-ca.crt |
Export the CA on the directory server, transfer /tmp/ds-ca.crt to the failing client, then install it with update-ca-trust or LDAPTLS_CACERT. Commands that use -y /root/dm.pw run on the machine where that password file exists; a server-side credential file is not present on remote SSSD, Apache, or application hosts unless you create it there deliberately.
Causes and fixes at a glance
| Symptom or test result | Likely cause | Fix |
|---|---|---|
| LDAP works, LDAPS connection refused | Port 636 not listening or blocked | Check the LDAPS listener |
LDAP works, LDAPS certificate error in -d 1 output |
Client does not trust the issuing CA | Fix client CA trust |
| LDAP URI uses an IP but certificate lists DNS names only | Hostname or SAN mismatch | Fix client CA trust |
| StartTLS works, LDAPS fails | Dedicated port 636 or listener issue | Check the LDAPS listener |
| LDAPS works locally but not remotely | Firewall, routing, DNS, or load balancer | Check network access and TLS compatibility |
| LDAPS works only through localhost | Secure listener bound to loopback | ss and nsslapd-securelistenhost |
openssl verifies with CA file but ldapsearch fails |
LDAP client CA configuration | Fix client CA trust |
| No peer certificate returned | Server did not complete TLS negotiation | Test the TLS handshake |
| Certificate expired | Server presents an expired certificate | Check the server certificate database |
| Old client cannot connect | TLS version or cipher mismatch | Check network access and TLS compatibility |
| TLS succeeds but bind returns error 49 | Credentials are incorrect | Fix LDAP invalid credentials error 49 |
| TLS succeeds but operation returns error 50 | ACI denies the operation | Fix LDAP insufficient access error 50 |
Classify the failure with LDAP, LDAPS, and StartTLS
Run anonymous Root DSE searches from the client that fails in production. These commands test transport and trust without sending bind credentials over plain LDAP.
Plain LDAP on port 389:
ldapsearch -LLL -x -H ldap://ldap1.example.com:389 -b "" -s base "(objectClass=*)" namingContextsSample output when LDAP transport is healthy:
dn:
namingContexts: dc=example,dc=comLDAPS on port 636 without a trusted CA on the client often fails before any LDAP result is returned:
ldapsearch -LLL -x -H ldaps://ldap1.example.com:636 -b "" -s base "(objectClass=*)" namingContextsSample output:
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)After you install the CA on the client, retry LDAPS with the client-side path:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapsearch -LLL -x -H ldaps://ldap1.example.com:636 -b "" -s base "(objectClass=*)" namingContextsSample output when LDAPS transport and trust are configured correctly:
dn:
namingContexts: dc=example,dc=comStartTLS on port 389 isolates whether TLS works on the shared LDAP listener. Use the same client-side CA path:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapsearch -LLL -x -ZZ -H ldap://ldap1.example.com:389 -b "" -s base "(objectClass=*)" namingContextsSample output when StartTLS and trust are configured correctly:
dn:
namingContexts: dc=example,dc=com| Result | Likely direction |
|---|---|
| LDAP works, LDAPS connection refused | Port 636 is not listening or is blocked |
| LDAP works, LDAPS certificate error in debug output | Client trust, certificate chain, or hostname problem |
| StartTLS works, LDAPS fails | Dedicated LDAPS listener, port 636, listen address, or firewall; check ss, nsslapd-securelistenhost, and firewall rules |
| LDAPS works locally but not remotely | Firewall, routing, DNS, or load balancer |
openssl succeeds with -CAfile but ldapsearch fails |
LDAP client CA configuration |
| All TLS connections fail | Server certificate or TLS configuration |
When LDAPS fails with -1, add debug output before you change server certificates:
ldapsearch -d1 -x -H ldaps://ldap1.example.com:636 -b "" -s baseThe TLS trace lines above the -1 result identify verification failure versus an unreachable port.
After LDAPS transport succeeds, test authentication separately on the same client:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapwhoami -x -H ldaps://ldap1.example.com:636 -D "cn=Directory Manager" -y /root/dm.pwSample output:
dn: cn=directory managerA transport success followed by error 49 here is a credential problem, not an LDAPS listener problem.
Check the LDAPS listener
Confirm the instance is running and TLS security is enabled:
dsctl ldap1 statusSample output:
Instance "ldap1" is runningdsconf ldap1 security getSample output (trimmed):
nsslapd-security: on
nsslapd-secureport: 636
sslversionmin: TLS1.2
sslversionmax: TLS1.3dsconf ldap1 config get nsslapd-security nsslapd-secureport nsslapd-securelistenhostSample output (trimmed):
nsslapd-security: on
nsslapd-secureport: 636
nsslapd-securelistenhost:An empty nsslapd-securelistenhost means the secure listener uses the default bind address. When set to a specific hostname or address, LDAPS accepts connections only on that interface.
dsconf ldap1 security rsa getSample output (trimmed):
nssslpersonalityssl: Server-Cert
nsssltoken: internal (software)This shows which NSS nickname the running RSA TLS configuration presents. A certificate can exist in the database under another name but still not be selected for LDAPS until it is configured here.
Inspect listening ports on the directory server:
sudo ss -ltnp | grep -E ':389|:636'Sample output:
LISTEN 0 128 *:636 *:* users:(("ns-slapd",pid=17960,fd=9))
LISTEN 0 128 *:389 *:* users:(("ns-slapd",pid=17960,fd=8))Read the local address column:
ss local address |
Meaning |
|---|---|
*:636 |
Listening on all interfaces |
192.0.2.10:636 |
Listening on one server interface |
127.0.0.1:636 |
Local connections only |
Port 636 with ns-slapd confirms the LDAPS listener is active. If port 636 is absent, verify nsslapd-security and nsslapd-secureport, check the errors log for certificate loading failures, and confirm no other service owns the port. A locally working LDAPS session combined with remote failure can be a listen-address problem even when the firewall is open. Complete initial listener and certificate setup is in configure TLS in 389 Directory Server.
Test the TLS handshake and certificate
Test the TCP and TLS layer independently of the LDAP client:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com -showcerts </dev/nullSample output (trimmed):
depth=1 C=AU, ST=Queensland, L=389ds, O=testing, CN=ssca.389ds.example.com
verify error:num=19:self-signed certificate in certificate chain
CONNECTED(00000005)
Certificate chain
0 s:CN=ldap1.example.com
i:CN=ssca.389ds.example.comCONNECTED confirms that TCP port 636 accepted the connection. A presented peer certificate and negotiated protocol or cipher show that TLS progressed. A verification error still means the client does not trust or cannot validate the server identity. openssl s_client normally continues after certificate-verification errors unless you pass -verify_return_error. Use -CAfile, -verify_hostname, and -verify_return_error for a conclusive validation test.
When summarizing this initial untrusted probe, distinguish:
| Observation | What it proves |
|---|---|
CONNECTED |
TCP reachable |
| Protocol and cipher lines | TLS negotiated |
| Certificate chain section | Server certificate presented |
verify error or non-zero Verify return code |
Trust or identity validation failed |
Inspect subject, issuer, validity, and Subject Alternative Names:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltNameSample output:
subject=C=AU, ST=Queensland, L=389ds, O=testing, GN=dfba1287-caca-47e5-a406-98347d7c0e30, CN=ldap1.example.com
issuer=C=AU, ST=Queensland, L=389ds, O=testing, CN=ssca.389ds.example.com
notBefore=Jul 22 01:18:03 2026 GMT
notAfter=Jul 22 01:18:03 2028 GMT
X509v3 Subject Alternative Name:
DNS:ldap1.example.comUse a URI hostname present in the certificate SAN. Modern deployments should issue SAN-bearing certificates rather than relying on legacy CN fallback behavior. OpenLDAP also exposes TLS_REQSAN policy levels, with stricter modes rejecting certificates that lack a matching SAN. Connecting with an IP address when the certificate lists only DNS:ldap1.example.com commonly fails verification even when port 636 is open.
Always pass -servername with the DNS name the client will use. If no certificate is returned, investigate the listener and server NSS database before you change application LDAP settings.
Fix client CA trust and hostname matching
On the directory server, list the NSS database and identify the issuing CA nickname:
sudo certutil -d /etc/dirsrv/slapd-ldap1/ -LSample output:
Certificate Nickname Trust Attributes
Self-Signed-CA CT,,
Server-Cert u,u,uExport the issuing CA certificate, not the leaf server certificate. Clients trust the CA and then validate the server certificate issued by it.
CA_NICKNAME="Self-Signed-CA" # Replace with the listed CA nicknamesudo certutil -d /etc/dirsrv/slapd-ldap1/ -L -n "$CA_NICKNAME" -a > /tmp/ds-ca.crtCopy /tmp/ds-ca.crt from the server to the failing client with scp, configuration management, or your standard file-transfer process.
On a RHEL-family client, install it into the system trust store:
sudo cp /tmp/ds-ca.crt /etc/pki/ca-trust/source/anchors/ds-ca.crtsudo update-ca-trustFor OpenLDAP utilities, point the client at the same CA explicitly:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapsearch -LLL -x -H ldaps://ldap1.example.com:636 -b "" -s base "(objectClass=*)" namingContextsSample output after trust is configured:
dn:
namingContexts: dc=example,dc=comYou can also set the default in /etc/openldap/ldap.conf:
TLS_CACERT /etc/pki/ca-trust/source/anchors/ds-ca.crtDo not use TLS_REQCERT never as the permanent fix because it bypasses certificate verification.
Retest from the same host that failed in production, not only from the directory server itself. A connection to ldaps://127.0.0.1:636 can fail when the certificate covers ldap1.example.com only. On a remote client, resolving ldap1.example.com to 127.0.0.1 sends the connection back to that client rather than to the directory server.
Check the server certificate database
List certificates in the instance NSS database:
sudo certutil -d /etc/dirsrv/slapd-ldap1/ -LSample output:
Certificate Nickname Trust Attributes
Self-Signed-CA CT,,
Server-Cert u,u,uDisplay the active server certificate details. Use the nickname from dsconf ldap1 security rsa get, not an assumed default:
sudo certutil -d /etc/dirsrv/slapd-ldap1/ -L -n "Server-Cert"Confirm that the active server certificate exists, is not expired, and has an associated private key. In NSS trust flags, u indicates private-key material. Separately confirm that the issuing CA has suitable CA trust flags, commonly C,, or CT,, depending on whether client-certificate authentication is also required.
Also inspect the running configuration:
dsconf ldap1 security certificate listdsconf ldap1 security ca-certificate listSample output (trimmed):
Certificate Name: Server-Cert
Subject DN: CN=ldap1.example.com,...
Expires: 2028-07-22 01:18:03
Trust Flags: u,u,uFinding a certificate in the NSS database does not prove it is the one selected by the active RSA configuration. Compare dsconf ldap1 security rsa get with the certificate list before you renew or replace files.
Certificate import, renewal, replacement, and NSS database recovery belong in certificate management and NSS database troubleshooting, not in this connection guide.
Check network access and TLS compatibility
Test remote reachability of port 636 from the failing client:
nc -vz ldap1.example.com 636Confirm DNS resolves to the server you intend to reach:
getent hosts ldap1.example.comSample output:
192.0.2.10 ldap1.example.comThe result must be the intended directory-server or load-balancer address. 127.0.0.1 is valid only when the LDAP client and Directory Server run on the same host; on a remote client it indicates a DNS or /etc/hosts error.
On the directory server, confirm the firewall allows LDAPS when firewalld is in use. A host may allow LDAPS through a named service rule rather than a raw port rule:
sudo firewall-cmd --query-service=ldapssudo firewall-cmd --query-port=636/tcpWhen both queries return no, open the port or service persistently. Use either the documented port rule or the ldaps service, but avoid adding duplicate rules:
sudo firewall-cmd --permanent --add-port=636/tcpsudo firewall-cmd --reloadReview the server TLS bounds:
dsconf ldap1 security get | grep -Ei 'sslVersion|cipher'Test a specific protocol when an old client is suspected:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com -tls1_2 </dev/nullDo not lower sslversionmin until you confirm the client cannot negotiate a supported protocol. Cipher policy details are in TLS cipher configuration. Minimum SSF and secure-bind enforcement are in enforce TLS and secure binds.
When StartTLS works against the same server and certificate but LDAPS fails, prioritize the dedicated port, secure listener address, firewall, and load-balancer configuration. Still confirm that both tests reached the same host rather than different load-balancer backends. When LDAPS works on the directory server host but fails from remote clients, compare firewall rules, network ACLs, load balancer backend ports, and whether the balancer forwards port 389 but not 636.
Inspect logs and verify the fix
Reproduce the client connection while you follow the errors log:
sudo tail -f /var/log/dirsrv/slapd-ldap1/errorsCertificate loading failures, missing private keys, expired certificates, and NSS database problems appear here. A failed TLS handshake may produce no bind line in /var/log/dirsrv/slapd-ldap1/access because the LDAP operation never starts. Successful secure sessions can also appear in /var/log/dirsrv/slapd-ldap1/security.
Repeat the production LDAPS transport test after you apply the fix:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapsearch -LLL -x -H ldaps://ldap1.example.com:636 -b "" -s base "(objectClass=*)" namingContextsConfirm certificate verification independently with OpenSSL. LDAPTLS_CACERT is an OpenLDAP client variable and does not configure the standalone openssl command:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com -CAfile /etc/pki/ca-trust/source/anchors/ds-ca.crt -verify_hostname ldap1.example.com -verify_return_error </dev/nullSample output (trimmed):
Verify return code: 0 (ok)Then confirm authentication on the same client:
LDAPTLS_CACERT=/etc/pki/ca-trust/source/anchors/ds-ca.crt ldapwhoami -x -H ldaps://ldap1.example.com:636 -D "cn=Directory Manager" -y /root/dm.pwRetest the original client: ldapsearch, SSSD, Apache, replication, monitoring, or backup tools against the same hostname and port you repaired. Test every replica directly when a load balancer fronts the topology.
Troubleshooting
| Symptom | Likely cause | Check |
|---|---|---|
| Port 389 works but 636 is refused | LDAPS listener disabled or blocked | ss, firewall, and nsslapd-secureport |
| LDAPS works locally only | Network or firewall restriction | Remote nc and firewall rules |
| LDAPS works only through localhost | Secure listener bound to loopback | ss and nsslapd-securelistenhost |
Can't contact LDAP server (-1) |
Often certificate verification or handshake failure | ldapsearch -d 1 and openssl s_client |
| Self-signed certificate in chain | Client does not trust the issuing CA | Client trust store or LDAPTLS_CACERT |
| Hostname mismatch | URI hostname missing from certificate SAN | Certificate SAN and client URI |
| Certificate expired | Server presents an expired certificate | openssl x509 -dates and certutil -L |
| StartTLS works but LDAPS fails | Dedicated port 636, listener address, or firewall | ss, nsslapd-securelistenhost, and secure-port settings |
openssl works but ldapsearch fails |
LDAP client CA configuration | ldap.conf and LDAPTLS_CACERT |
| No peer certificate returned | Server did not complete TLS negotiation | Listener and errors log |
| Works with hostname but not IP | Certificate covers DNS name only | Use the certificate hostname in the URI |
| Old client cannot connect | TLS protocol or cipher incompatibility | Protocol negotiation and sslversionmin |
| Works on one replica only | Certificate or TLS configuration differs | Test each server directly |
| TLS succeeds but bind returns error 49 | Credentials are incorrect | Error 49 troubleshooting guide |
| TLS succeeds but operation returns error 50 | ACI denies the operation | Error 50 troubleshooting guide |
References
- RFC 4511 — LDAP result codes
- RFC 4513 — LDAP authentication and TLS
- 389 Directory Server documentation
- Red Hat Directory Server 13 — Securing RHDS
- OpenLDAP ldap.conf(5) — TLS_CACERT, TLS_REQCERT, and environment variables
- OpenSSL s_client — -CAfile, -verify_hostname, and -verify_return_error
Summary
When LDAP works but LDAPS fails in 389 Directory Server, classify the failure with side-by-side anonymous LDAP, LDAPS, and StartTLS transport tests, then work through the listener on port 636, the TLS handshake, client CA trust, hostname matching, the server NSS certificate database, network access, and TLS compatibility. Treat Can't contact LDAP server (-1) on LDAPS as a transport or verification problem until openssl s_client with -CAfile and -verify_hostname and ldapsearch -d 1 show a completed handshake. After TLS succeeds, test authentication separately and distinguish bind and authorization errors from connection problems.

