Configure LDAP Referrals in 389 Directory Server

Configure default, smart, suffix, and replication LDAP referrals in 389 Directory Server with dsconf, ldapmodify, client tests, security notes, and cleanup.

Published

Updated

Read time 14 min read

Reviewed byDeepak Prasad

389 Directory Server LDAP referral flow from client request through result code 10 and referral URL to a second directory server

An LDAP referral tells a client where it can continue an operation. Directory Server returns one or more LDAP URLs either in an LDAP referral result (result code 10) or, during some searches, as search-result references. Smart-referral entries store these URLs in the ref attribute, but ordinary clients normally receive the URL as a referral rather than reading ref as a regular attribute. The original server does not fetch the remote data for the client. That behaviour belongs to database chaining.

text
LDAP client
    |
    | Request for remote data
    v
Directory Server 1 (ldap1)
    |
    | LDAP result 10 + referral URL
    v
LDAP client
    |
    | New request (client-dependent bind)
    v
Directory Server 2 (ldap2)

The client must recognize referral results or search-result references and follow the returned URL. If the application ignores them, the operation appears to fail even when the server configured the referral correctly.

Before you start:

IMPORTANT
This guide covers default, smart, suffix, and replication referrals using dsconf and ldapmodify. It does not cover database chaining (dedicated chapter), full replication topology design, or the legacy server-wide referral mode removed in Directory Server 13.1.

Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.


Understand LDAP referral types

Referral type When it is returned
Default referral The requested DN is outside every local naming context
Smart referral A specific entry carries the referral object class and a ref URL
Suffix referral A backend is in referral state and redirects its suffix subtree
Replication referral A write reaches a read-only replica or a replica that is temporarily busy

Directory Server implements these flows through global configuration (nsslapd-referral), entry attributes (ref), backend state (--state=referral, --add-referral), and replication settings (--repl-add-ref).


Plan the referral lab

This guide uses two instances on one host. That is the same layout as the multiple instances chapter:

Component Example in this lab
Local server ldap1.example.com — port 389
Destination server ldap2.example.com — port 1389
Local suffix dc=example,dc=com
Smart-referred entry uid=user1,ou=people,dc=example,dc=com
Destination subtree ou=Users,dc=lab,dc=example,dc=com
Suffix-referral branch ou=RemoteUsers,dc=example,dc=com (separate backend)

ldap2 uses suffix dc=lab,dc=example,dc=com from its install profile. The referral URLs therefore point at ou=Users,dc=lab,dc=example,dc=com on port 1389, not at the same dc=example,dc=com tree on both hosts.

Verify the destination LDAP URL, entry, and credentials before you configure referrals on ldap1. Referral URLs are consumed by LDAP clients, so the advertised hostname must resolve from every client that follows the referral. It must not resolve only from the Directory Server host. Using localhost or 127.0.0.1 in a referral URL would direct remote clients back to themselves.

Confirm the hostname resolves:

bash
getent hosts ldap2.example.com

Sample output:

output
192.168.56.109  ldap2.example.com ldap2

Test the advertised endpoint with ldapsearch. Use the same hostname and port you plan to embed in referral URLs:

bash
ldapsearch -LLL -x -H ldap://ldap2.example.com:1389 -D "cn=Directory Manager" -y /root/dm.pw -b "ou=Users,dc=lab,dc=example,dc=com" "(uid=user1)" dn cn

When that command fails with Can't contact LDAP server, the hostname does not reach the LDAP listener from this client. Fix DNS, firewall rules, or nsslapd-listenhost before you publish the name in a referral URL. On a single host running both instances, you can confirm ldap2 is answering with ldapsearch -H ldap://127.0.0.1:1389 first, then align DNS so ldap2.example.com reaches the same listener from client systems.

If the destination tree does not exist yet, create it on ldap2:

bash
cat > /tmp/users-ou.ldif <<'EOF'
dn: ou=Users,dc=lab,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: Users

dn: uid=user1,ou=Users,dc=lab,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: User One
sn: One
uid: user1
EOF

Apply the destination subtree LDIF on ldap2:

bash
ldapadd -x -H ldap://127.0.0.1:1389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/users-ou.ldif

Sample output:

output
adding new entry "ou=Users,dc=lab,dc=example,dc=com"

adding new entry "uid=user1,ou=Users,dc=lab,dc=example,dc=com"

A direct search on ldap2 confirms the destination entry exists before ldap1 starts returning referral URLs.


Understand the LDAP referral URL

A referral URL uses standard LDAP URL syntax:

text
ldap://host:port/base-dn
ldaps://host:port/base-dn
Part Purpose
Hostname and port Destination server the client should contact
Base DN Starting point for the continued operation on the remote server
Scheme ldap:// for plain LDAP; ldaps:// when the client must use LDAPS

An ldap:// referral URL does not itself require StartTLS. The client must be separately configured to issue StartTLS after connecting. Use ldaps:// when the referral must explicitly direct the client to an LDAP-over-TLS listener.

Special characters in the base DN must be URL-encoded. You can list multiple ref values or --add-referral URLs when alternative destinations should be offered.

Include the non-default port in this lab (1389 for ldap2). Omitting it makes clients default to port 389 and miss the second instance.


Configure a default referral

Use a default referral when the client requests a DN outside every naming context managed locally. Set the global nsslapd-referral attribute on ldap1:

bash
dsconf ldap1 config replace nsslapd-referral="ldap://ldap2.example.com:1389/"

Sample output:

output
Successfully replaced value(s) for 'nsslapd-referral': 'ldap://ldap2.example.com:1389/'

Confirm the value:

bash
dsconf ldap1 config get nsslapd-referral

Sample output:

output
nsslapd-referral: ldap://ldap2.example.com:1389/

Query a naming context the instance does not manage:

bash
ldapsearch -x -H ldap://127.0.0.1:389 -b "dc=other,dc=org" -s base dn

Sample output:

output
# extended LDIF
#
# LDAPv3
# base <dc=other,dc=org> with scope baseObject
# filter: (objectclass=*)
# requesting: dn 
#

# search result
search: 2
result: 10 Referral
ref: ldap://ldap2.example.com:1389/

# numResponses: 1

Result code 10 with the ref line is the expected referral response. A default referral is a fallback for unknown namespaces. It must not redirect valid entries already stored under dc=example,dc=com. Confirm local data still resolves normally:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -b "dc=example,dc=com" -s base dn

Sample output:

output
dn: dc=example,dc=com

Configure a smart referral for an entry

A smart referral redirects one entry, or a subtree rooted at that entry, to a remote LDAP URL. The entry needs the referral object class and a ref attribute.

Add both on user1, then apply the referral with ldapmodify:

bash
cat > /tmp/user1-referral.ldif <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
add: objectClass
objectClass: referral
-
add: ref
ref: ldap://ldap2.example.com:1389/uid=user1,ou=Users,dc=lab,dc=example,dc=com
EOF

Apply the smart-referral modification on ldap1:

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/user1-referral.ldif

Sample output:

output
modifying entry "uid=user1,ou=people,dc=example,dc=com"

Inspect the locally stored referral entry with the Manage DSA IT control (-M). OpenLDAP tools use -M to send the Manage DSA IT control. This tells Directory Server to treat the referral object as an ordinary local entry instead of returning its referral URL:

bash
ldapsearch -LLL -M -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user1,ou=people,dc=example,dc=com" -s base objectClass ref

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com
objectClass: referral
ref: ldap://ldap2.example.com:1389/uid=user1,ou=Users,dc=lab,dc=example,dc=com

The referral object class and ref attribute confirm the smart referral is stored on ldap1.

Now search without -M to see what an ordinary application receives:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user1,ou=people,dc=example,dc=com" -s base ref

Sample output:

output
# refldap://ldap2.example.com:1389/uid=user1,ou=Users,dc=lab,dc=example,dc=com

ldapsearch prints the referral URL as a # ref… continuation line rather than listing ref as a normal attribute.

In this lab, uid=user1 is a leaf entry, so the referral affects only that DN. When a smart referral is placed on a container entry, it can redirect the tree rooted at that entry.

Converting an existing entry into a smart referral means ordinary clients no longer read its locally stored attributes in the usual way. Use a dedicated referral entry when the local data must remain independently accessible.


Configure a referral for a non-replicated suffix

A suffix referral puts an entire backend into referral state. Every request for that suffix DN and its descendants returns the configured LDAP URL. The local backend provides the mapping-tree referral only. The authoritative data must already exist on the destination server. Create the sub-suffix with suffixes and backends before you add the referral.

This lab uses an unused branch so it does not conflict with ou=people in userroot:

bash
dsconf ldap1 backend create --suffix="ou=RemoteUsers,dc=example,dc=com" --be-name="remoteusersroot" --parent-suffix="dc=example,dc=com" --create-suffix

Sample output:

output
The database was sucessfully created

Add the referral URL to the new backend:

bash
dsconf ldap1 backend suffix set --add-referral="ldap://ldap2.example.com:1389/ou=Users,dc=lab,dc=example,dc=com" remoteusersroot

Switch the backend into referral state so clients receive the URL instead of local data:

bash
dsconf ldap1 backend suffix set --state=referral remoteusersroot

Each command updates backend configuration and exits without an LDAP error when the backend name is correct.

Query the referred suffix:

bash
ldapsearch -x -H ldap://127.0.0.1:389 -b "ou=RemoteUsers,dc=example,dc=com" -s base dn

Sample output:

output
# extended LDIF
#
# LDAPv3
# base <ou=RemoteUsers,dc=example,dc=com> with scope baseObject
# filter: (objectclass=*)
# requesting: dn 
#

# search result
search: 2
result: 10 Referral
matchedDN: ou=RemoteUsers,dc=example,dc=com
ref: ldap://ldap2.example.com:1389/ou=Users,dc=lab,dc=example,dc=com

# numResponses: 1

Result code 10 with matchedDN and ref confirms the suffix referral is active for the whole branch.


Configure a referral for a replicated suffix

Replication referrals redirect clients when a write targets a read-only consumer or when a replica is temporarily busy during operations such as import or reindex. Full replication setup belongs in dedicated replication chapters. The commands below apply only after replication is enabled on a consumer. I did not execute them in the lab instance shown here, which reports no replicated suffixes.

On a consumer, add a replication referral URL with --repl-add-ref:

bash
dsconf ldap1 replication set --suffix="dc=example,dc=com" --repl-add-ref="ldap://ldap2.example.com:1389"

The command adds the URL to nsDS5ReplicaReferral in the consumer's replication configuration for the selected suffix. A read-only consumer returns the configured URL for update requests it cannot accept. A temporarily busy replica can also return the referral while operations such as import or reindexing are in progress.

Verify the value after replication is enabled on the consumer:

bash
dsconf ldap1 replication get --suffix="dc=example,dc=com" | grep -i nsDS5ReplicaReferral

Sample output on a configured consumer:

output
nsDS5ReplicaReferral: ldap://ldap2.example.com:1389

replication list only shows suffixes with replication enabled. It does not replace this check. A consumer can have a referral configured even when it has no outgoing replication agreement.

List whether replication is enabled before you rely on replication referrals:

bash
dsconf ldap1 replication list

A lab instance with no replicated suffixes returns:

output
There are no replicated suffixes

When the suffix appears in that list, inspect agreements with dsconf ldap1 repl-agmt list --suffix="dc=example,dc=com" on the replicated topology before you change referral URLs in production.


Test the referral response

Test referrals in three layers: the URL ldap1 returns, direct access to the destination, and whether your client library follows referrals.

Read the suffix referral without chasing referrals (default ldapsearch behaviour):

bash
ldapsearch -x -H ldap://127.0.0.1:389 -b "ou=RemoteUsers,dc=example,dc=com" -s base dn

The output should include result: 10 Referral and the ref: line pointing at ldap2.

Confirm the destination answers on the advertised hostname when that name is reachable from your client:

bash
ldapsearch -LLL -x -H ldap://ldap2.example.com:1389 -D "cn=Directory Manager" -y /root/dm.pw -b "ou=Users,dc=lab,dc=example,dc=com" -s sub "(uid=user1)" dn

Sample output when the hostname reaches the listener:

output
dn: uid=user1,ou=Users,dc=lab,dc=example,dc=com

ldapsearch -C asks the OpenLDAP client to chase referrals. Referral chasing does not guarantee that the original authenticated identity will be reused on the destination. OpenLDAP command-line referral chasing has historically followed referrals anonymously, so the destination must either allow the operation anonymously or the application must implement its own rebind callback.

An anonymous chase can succeed only when anonymous search access is allowed on ldap2:

bash
ldapsearch -C -LLL -x -H ldap://127.0.0.1:389 -b "ou=RemoteUsers,dc=example,dc=com" -s sub "(uid=user1)" dn

Do not treat this as guaranteed to work with the Directory Manager credentials supplied to the initial server.


Secure authentication and referral traffic

The server that returns the referral does not transfer the client's authenticated session to the destination. After an LDAP referral result or search-result reference, the client opens a new connection and must bind again unless anonymous access is sufficient on the remote suffix.

Check these items before production use:

  • Whether the client rebinds to the referred server with the same or a service bind DN
  • Whether the user entry exists on the destination with compatible object classes
  • Whether anonymous read is acceptable on the referred subtree
  • Whether the client supports referral credentials or SASL rebind
  • Whether the destination certificate is trusted when the URL uses ldaps://
  • Whether the hostname in the URL matches the certificate SAN

Plain ldap:// referrals expose the continued operation to network observers unless the client upgrades to StartTLS or LDAPS on the second hop.


Update or remove referrals

Restore the lab in reverse order when you created these objects only for this guide.

Remove the default referral with the explicit delete operation:

bash
dsconf ldap1 config delete nsslapd-referral

Sample output:

output
Removed attribute 'nsslapd-referral' completely

Confirm it is unset:

bash
dsconf ldap1 config get nsslapd-referral

The command returns no value when the default referral is removed. Repeat the unknown-suffix search and confirm it no longer returns the configured URL.

Remove the smart referral from user1 with Manage DSA IT so the server processes the entry locally:

bash
ldapmodify -M -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
delete: ref
-
delete: objectClass
objectClass: referral
EOF

Sample output:

output
modifying entry "uid=user1,ou=people,dc=example,dc=com"

Without -M, an ordinary ldapmodify against a smart-referral entry may return the referral URL instead of changing the local entry.

Return the suffix backend to normal state:

bash
dsconf ldap1 backend suffix set --state=backend remoteusersroot

Remove the referral URL from the backend configuration:

bash
dsconf ldap1 backend suffix set --del-referral="ldap://ldap2.example.com:1389/ou=Users,dc=lab,dc=example,dc=com" remoteusersroot

Delete the suffix-referral backend when it was lab-only:

bash
dsconf ldap1 backend delete remoteusersroot --do-it

Sample output:

output
Deleting Backend cn=remoteusersroot,cn=ldbm database,cn=plugins,cn=config :
Type 'Yes I am sure' to continue: Yes I am sure
The database, and any sub-suffixes, were successfully deleted

Remove a replication referral when replication is configured:

bash
dsconf ldap1 replication set --suffix="dc=example,dc=com" --repl-del-ref="ldap://ldap2.example.com:1389"

After cleanup, searches against the original DNs should no longer return result code 10.

Run the following commands only when the destination entries were created exclusively for this referral lab. Delete the referred user entry first:

bash
ldapdelete -x -H ldap://ldap2.example.com:1389 -D "cn=Directory Manager" -y /root/dm.pw "uid=user1,ou=Users,dc=lab,dc=example,dc=com"

Remove the parent OU when it is no longer needed:

bash
ldapdelete -x -H ldap://ldap2.example.com:1389 -D "cn=Directory Manager" -y /root/dm.pw "ou=Users,dc=lab,dc=example,dc=com"

Each delete succeeds when the DN exists on ldap2 and the hostname in the URI reaches the listener.


Referrals vs database chaining

Area Referral Database chaining
Remote request performed by LDAP client Local Directory Server
Client must understand distribution Yes No
Client sees referral result Yes No
Authentication to remote server Client-dependent Configured on database link
Configuration complexity Lower Higher
Transparent namespace No Yes

Use referrals when clients can follow LDAP URLs and you want a simple redirect. Use database chaining when applications should see one directory tree and let the server fan out remote queries.


Troubleshoot LDAP referrals

Symptom Likely cause Fix
Result code 10 but no data from the remote server Client does not chase referrals or cannot rebind Enable referral chasing in the client library; verify bind DN and password on the destination
Referral points to the wrong DN Incomplete base DN in ref or --add-referral Include the full destination base DN and port in the LDAP URL
Referral loop between two servers Cross-referrals on both instances Trace ref values and backend referral URLs on each host
Authentication fails after following the referral User missing remotely or anonymous access denied Create the entry on the destination or configure service-bind credentials
TLS hostname or CA validation fails Hostname in URL does not match the certificate Align DNS, SAN entries, and ldaps:// URLs
Local entries unexpectedly return referrals Smart referral entry, suffix backend state, or global default Inspect ref on the entry, backend get-tree, and nsslapd-referral
Smart-referral modify or delete has no effect Manage DSA IT not used Inspect the local referral entry with ldapsearch -M; change it with ldapmodify -M, or use ldapdelete -M when deleting the referral entry itself
Suffix referral create fails on existing OU Branch already stored in parent backend Export the subtree, import and verify it on the destination server, remove the local copy from the parent backend, and then create the local suffix-referral backend

Summary

  1. Default referrals (nsslapd-referral) handle unknown directory namespaces outside local naming contexts.
  2. Smart referrals add referral and ref on entries; use Manage DSA IT (-M) to inspect or remove them.
  3. Suffix referrals combine --add-referral with --state=referral on a dedicated backend whose data lives on the destination server.
  4. Replication referrals (--repl-add-ref) on consumers redirect operations from read-only or busy replicas.
  5. The client, not the original server, normally follows the referral URL and must handle authentication to the destination.

What's Next


References


Frequently Asked Questions

1. What is the difference between an LDAP referral and database chaining in 389 Directory Server?

A referral returns an LDAP referral result or search-result reference with a destination URL; the LDAP client must contact that server. Database chaining makes the local Directory Server query the remote server on behalf of the client, so the client sees a single namespace.

2. Does every LDAP client follow referrals automatically?

No. The client library or application must recognize an LDAP referral result or search-result reference, extract the LDAP URL, open a connection to the destination, and issue the continued operation. Many clients do not rebind with the original credentials unless explicitly configured.

3. What is nsslapd-referral used for?

nsslapd-referral sets the instance-wide default referral returned when a client requests a DN outside every local naming context. It is a fallback and must not redirect entries that the instance already stores locally.

4. Can I put a suffix referral on ou=People when that OU already exists in userroot?

Not directly. First export the existing subtree and import it into the destination directory server. Verify that the remote copy is complete, update or pause applications, and then remove the original subtree from the parent backend. Finally, create a dedicated local sub-suffix backend for that DN, add the destination referral URL, and set its state to referral.

5. Was server-wide referral mode removed from 389 Directory Server?

Yes. Directory Server 13.1 removed the old server-wide referral mode and refer workflow. Default, smart, suffix, and replication referrals remain supported through nsslapd-referral, entry ref attributes, backend referral state, and replication settings.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …