Ubuntu 22.04 安装 OpenLDAP 2.5.20 指南

Ubuntu 22.04 从零安装 OpenLDAP 2.5.20 实测:debconf 静默安装与重配域、组织结构与用户导入、ACL 收紧、自签 TLS 与远程客户端验证,全部命令回显实测。

OpenLDAP身份认证目录服务2026/10/27

Ubuntu 22.04 安装 OpenLDAP 2.5.20 指南

目标:在一台 Ubuntu 22.04 服务器上从零安装 OpenLDAP 2.5.20(slapd 2.5.20+dfsg-0ubuntu0.22.04.1),完成域初始化(dc=lab,dc=local)、组织结构与用户导入、ACL 收紧、TLS(自签证书 ldaps/StartTLS)与远程客户端验证,全流程命令与回显均已在真实环境实测通过。

一、环境信息

本文实测环境:

  • 操作系统:Ubuntu 22.04.5 LTS(amd64)
  • 主机名:ldap01.lab.local(FQDN)
  • 内网 IP:10.89.63.2
  • 软件版本:slapd 2.5.20+dfsg-0ubuntu0.22.04.1、ldap-utils 2.5.20+dfsg-0ubuntu0.22.04.1(均来自 Ubuntu jammy-updates/main 官方仓库)、openssl 3.0.2-0ubuntu1.30
  • 目录域(suffix):dc=lab,dc=local
  • 管理员 DN:cn=admin,dc=lab,dc=local,密码 q1w2e3r4
  • 端口:389(ldap)、636(ldaps)、Unix socket(ldapi:///,本地管理)
  • 数据目录:/var/lib/ldap;配置目录:/etc/ldap/(cn=config 树位于 /etc/ldap/slapd.d/)

💡 说明:Ubuntu 22.04 仓库的 slapd 是上游 2.5 系最终版 2.5.20 的发行版打包。官网最新稳定版为 2.7.1(feature)/2.6.15(LTS),apt 渠道装不到,需源码编译,版本口径详见《OpenLDAP 2.7.1 介绍与选型指南》。

二、前置条件

  1. 一台 Ubuntu 22.04 服务器(物理机或虚拟机均可),具备 sudo 权限的账号;
  2. 服务器可访问 Ubuntu 官方软件源(archive.ubuntu.com / security.ubuntu.com;内网环境需配置镜像源或代理);
  3. 规划好目录域:本文用 dc=lab,dc=local,对应组织域名 lab.local;
  4. 主机名建议设为该域下的 FQDN(如 ldap01.lab.local)——slapd 安装时会从主机名推导默认域,FQDN 与目标域一致可省去重配(原理见 11.1);
  5. 确认 389/636 端口未被占用:
ss -ltn | grep -E ':389|:636'

实测回显(空闲时应无输出):

(无输出,端口空闲)
  1. TLS 章节需要 openssl 签发证书。Ubuntu Server 22.04 通常自带;最小化系统可能没有,先确认:
which openssl || echo "openssl not installed"

实测回显(最小化环境):

openssl not installed

缺失则安装:

sudo apt-get install -y openssl

实测回显(输出节选):

Setting up openssl (3.0.2-0ubuntu1.30) ...

三、版本选型说明

安装前先看仓库里 slapd 的候选版本:

sudo apt update && apt-cache policy slapd

实测回显(输出节选):

Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [4759 kB]
Fetched 12.5 MB in 9s (1437 kB/s)
Reading package lists...
slapd:
  Installed: (none)
  Candidate: 2.5.20+dfsg-0ubuntu0.22.04.1
  Version table:
     2.5.20+dfsg-0ubuntu0.22.04.1 500
        500 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
     2.5.16+dfsg-0ubuntu0.22.04.2 500
        500 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages

版本结论:

四、安装方案 A:Ubuntu 仓库 apt 在线安装(预置 debconf 静默安装)

4.1 方案说明

Ubuntu 的 slapd 包在安装时会通过 debconf 向导询问四个问题:目录域、管理员密码(两次确认)、是否允许 LDAPv2、数据库是否随卸载删除。自动化安装(脚本/批量装机)推荐用 debconf-set-selections 预置答案再静默安装,一次成型。本方案的目标配置:域 lab.local(dc=lab,dc=local)、管理员密码 q1w2e3r4。

4.2 预置 debconf 答案

sudo debconf-set-selections << "EOF"
slapd slapd/domain string lab.local
slapd shared/organization string lab.local
slapd slapd/password1 password q1w2e3r4
slapd slapd/password2 password q1w2e3r4
slapd slapd/no_configuration boolean false
slapd slapd/allow_ldap_v2 boolean false
slapd slapd/purge_database boolean false
slapd slapd/move_old_database boolean true
slapd slapd/dump_database select when needed
EOF

实测无输出即预置成功。各答案含义:

问题预置值说明
slapd/domain 与 shared/organizationlab.local目录域,生成 dc=lab,dc=local 后缀,两个问题必须同时给
password1/password2q1w2e3r4cn=admin,dc=lab,dc=local 的管理员口令,两次一致
no_configurationfalse走标准初始化(true 会跳过配置生成)
allow_ldap_v2false关闭已废弃的 LDAPv2
purge_databasefalse卸载时保留数据库
move_old_databasetrue重装时自动迁移旧库(⚠️ 必须为 true,false 的后果见 11.2)
dump_databasewhen needed升级/重配前自动 dump 备份到 /var/backups/slapd-版本号/

4.3 静默安装

sudo DEBIAN_FRONTEND=noninteractive apt-get install -y slapd ldap-utils

实测回显(输出节选,实测首尾):

Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  ldap-utils liblber-2.5-0 libldap-2.5-0 slapd
Setting up slapd (2.5.20+dfsg-0ubuntu0.22.04.1) ...
  Creating new user openldap... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.
Setting up ldap-utils (2.5.20+dfsg-0ubuntu0.22.04.1) ...

安装器创建了 openldap 运行账号、生成了初始 cn=config 配置并初始化了目录库。Ubuntu 的 slapd 包安装完成即由 systemd 自动启动。

4.4 验证服务与域

systemctl is-active slapd

实测回显:

active

查看数据库后缀与根 DN(cn=config 配置库,编号 -n 0):

sudo slapcat -n 0 | grep -E 'olcSuffix|olcRootDN:'

实测回显:

olcRootDN: cn=admin,cn=config
olcSuffix: dc=lab,dc=local
olcRootDN: cn=admin,dc=lab,dc=local

用管理员口令验证绑定(本地 ldapi socket):

ldapwhoami -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4

实测回显:

dn:cn=admin,dc=lab,dc=local

绑定成功且回显身份 DN,安装与域初始化闭环完成。

五、安装方案 B:交互安装与 dpkg-reconfigure 重配域

5.1 方案说明

未预置 debconf 直接交互安装、或安装后想改域/改管理员密码,用 dpkg-reconfigure slapd 重走向导。本方案演示:在已装好的机器上把配置重配为 lab.local + 密码 q1w2e3r4(与方案 A 等效,也是「装错了域怎么改」的标准做法)。

5.2 交互式重配

sudo dpkg-reconfigure slapd

交互向导依次回答(每屏一个):

  1. DNS domain name: 输入 lab.local(生成 dc=lab,dc=local);
  2. Organization name: 输入 lab.local;
  3. Administrator password: 输入 q1w2e3r4;
  4. Confirm administrator password: 再次输入 q1w2e3r4;
  5. Move old database? 选 <Yes>(把旧库转存到 /var/backups 后重建,⚠️ 选 No 会撞库报错,见 11.2);
  6. Allow LDAPv2 protocol? 选 <No>。

脚本化等价写法(预置答案 + 非交互重配):

sudo debconf-set-selections << "EOF"
slapd slapd/domain string lab.local
slapd shared/organization string lab.local
slapd slapd/password1 password q1w2e3r4
slapd slapd/password2 password q1w2e3r4
slapd slapd/move_old_database boolean true
slapd slapd/dump_database select when needed
slapd slapd/purge_database boolean false
slapd slapd/no_configuration boolean false
slapd slapd/allow_ldap_v2 boolean false
EOF
sudo dpkg-reconfigure -f noninteractive slapd

实测回显(输出节选,实测首尾):

  Backing up /etc/ldap/slapd.d in /var/backups/slapd-2.5.20+dfsg-0ubuntu0.22.04.1... done.
  - directory unknown... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.

5.3 重配后验证

重配会重建目录与配置,slapd 会按需重启。逐项验证:

systemctl is-active slapd
ldapwhoami -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4
sudo slapcat -b dc=lab,dc=local | grep '^dn:'

实测回显:

active
dn:cn=admin,dc=lab,dc=local
dn: dc=lab,dc=local

服务 active、新口令绑定成功、目录中已有根条目 dc=lab,dc=local,重配闭环完成。

六、方案对比与选择建议

维度方案 A(预置 debconf 静默安装)方案 B(交互安装 / dpkg-reconfigure)
适用脚本、批量装机、Ansible/user-data单台手工装机、装错后改域改密码
域与密码设定安装前预置,一次成型向导逐屏回答
可重复性完全可重复依赖人工输入
失败风险预置答案缺项时行为回退(见 11.1/11.2)选错「Move old database」撞库(见 11.2)

选择建议:可自动化场景一律用方案 A;单台手工装或补救时用方案 B。两方案产物完全一致,可混用(先 A 装好后需要改域再走 B 的 dpkg-reconfigure)。

七、安装后配置说明

7.1 服务默认项 /etc/default/slapd

grep -vE '^#|^$' /etc/default/slapd

实测回显:

SLAPD_CONF=
SLAPD_USER="openldap"
SLAPD_GROUP="openldap"
SLAPD_PIDFILE=
SLAPD_SERVICES="ldap:/// ldapi:///"
SLAPD_SENTINEL_FILE=/etc/ldap/noslapd
SLAPD_OPTIONS=""

逐项解释:

  • SLAPD_CONF=:空=走 cn=config 在线配置(/etc/ldap/slapd.d/);填 /etc/ldap/slapd.conf 路径则切老式单文件配置,二选一(双口径,见 7.3);
  • SLAPD_USER/GROUP:服务运行身份 openldap;
  • SLAPD_SERVICES:监听 URL 列表。默认只有 ldap:///(389)与 ldapi:///(本地 socket),没有 ldaps:///(636)——TLS 章节要启用 636 必须在此加 ldaps:///(见 10.6);
  • SLAPD_SENTINEL_FILE:存在 /etc/ldap/noslapd 文件时 init 脚本拒绝启动(判断文件存在性的保护开关)。

7.2 文件与目录布局

ls -la /etc/ldap/ && sudo ls /var/lib/ldap/

实测回显:

total 28
drwxr-xr-x 5 root     root     4096 Oct 27 02:49 .
drwxr-xr-x 1 root     root     4096 Oct 27 02:49 ..
-rw-r--r-- 1 root     root      334 Sep 24  2025 ldap.conf
drwxr-xr-x 2 root     root     4096 Sep 24  2025 sasl2
drwxr-xr-x 2 root     root     4096 Oct 27 02:49 schema
drwxr-x--- 3 openldap openldap 4096 Oct 27 02:49 slapd.d
data.mdb
lock.mdb
  • /etc/ldap/ldap.conf:客户端全局配置(BASE/URI/TLS 信任),改它不影响服务端;
  • /etc/ldap/schema/:schema 源文件(core/cosine/nis/inetorgperson 等);
  • /etc/ldap/slapd.d/:cn=config 在线配置树(LDIF 文件形态),服务端配置真身;
  • /var/lib/ldap/:mdb 数据库文件(data.mdb/lock.mdb);
  • /var/backups/slapd-<版本>/:重配/升级时自动 dump 的备份(排障时注意它会被自动恢复,见 11.3)。

7.3 slapd.conf 与 cn=config 双口径

OpenLDAP 2.4 起提供两套配置机制:

  • cn=config(推荐):配置是 LDAP 树(dn: cn=config),用 ldapmodify 在线改,sudo slapcat -n 0 导出全树;文件落在 /etc/ldap/slapd.d/ 但禁止手改(内部有 CRC 与序号约定,手改会丢失改动);
  • slapd.conf(老式):单文本文件,改完 systemctl restart slapd 生效;Ubuntu 默认不启用(SLAPD_CONF 为空),需要时填 /etc/default/slapd 的 SLAPD_CONF 切换。

本篇全部用 cn=config 口径;参数逐项修改-验证的完整详解见本专栏《OpenLDAP 2.5.20 配置参数详解》篇。

7.4 客户端全局配置 /etc/ldap/ldap.conf

服务器本机 ldap-utils 默认走 ldapi:/// 或显式 -H 参数,通常无需改。若想让本机命令默认连本目录,可设置:

sudo tee -a /etc/ldap/ldap.conf > /dev/null << "EOF"
BASE    dc=lab,dc=local
URI     ldap://ldap01.lab.local
TLS_CACERT  /etc/ssl/certs/lab-ca.crt
EOF

追加三行后,ldapsearch -x uid=zhangsan 不再需要 -b/-H。本文为清晰起见,命令一律显式带参。

八、导入组织结构与用户

8.1 创建组织单元(ou)

规划两个组织单元:ou=people(用户)、ou=groups(组)。先写 LDIF:

sudo tee /root/ou.ldif > /dev/null << "EOF"
dn: ou=people,dc=lab,dc=local
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=lab,dc=local
objectClass: organizationalUnit
ou: groups
EOF

用 ldapadd 以管理员身份导入:

ldapadd -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -f /root/ou.ldif

实测回显:

adding new entry "ou=people,dc=lab,dc=local"

adding new entry "ou=groups,dc=lab,dc=local"

8.2 生成 SSHA 口令哈希

slappasswd 以随机盐生成 {SSHA} 哈希(盐随机,每次输出不同,属正常现象):

slappasswd -s q1w2e3r4

实测回显(本次实测输出,你的输出会不同):

{SSHA}PwLIYbldg1JnQCrMM4OY5D4XY/Ia0bti

8.3 导入用户与 posixGroup

sudo tee /root/users.ldif > /dev/null << "EOF"
dn: uid=zhangsan,ou=people,dc=lab,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: zhangsan
cn: Zhang San
sn: Zhang
givenName: San
userPassword: {SSHA}PwLIYbldg1JnQCrMM4OY5D4XY/Ia0bti
uidNumber: 10001
gidNumber: 20001
homeDirectory: /home/zhangsan
loginShell: /bin/bash

dn: uid=lisi,ou=people,dc=lab,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: lisi
cn: Li Si
sn: Li
givenName: Si
userPassword: {SSHA}PwLIYbldg1JnQCrMM4OY5D4XY/Ia0bti
uidNumber: 10002
gidNumber: 20001
homeDirectory: /home/lisi
loginShell: /bin/bash

dn: cn=developers,ou=groups,dc=lab,dc=local
objectClass: posixGroup
cn: developers
gidNumber: 20001
memberUid: zhangsan
memberUid: lisi
EOF
ldapadd -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -f /root/users.ldif

实测回显:

adding new entry "uid=zhangsan,ou=people,dc=lab,dc=local"

adding new entry "uid=lisi,ou=people,dc=lab,dc=local"

adding new entry "cn=developers,ou=groups,dc=lab,dc=local"

LDIF 要点:userPassword 直接填 {SSHA} 哈希值;inetOrgPerson 提供姓名属性、posixAccount/shadowAccount 提供类 Unix 账号属性(供 SSSD/NSS 取用)、posixGroup 的 memberUid 存成员 uid(注意它存的是 uid 而非 DN,与 groupOfNames 的 member 属性语义不同,memberof 反解的差异见《配置参数详解》)。

九、访问控制(ACL)与查询验证

9.1 默认 ACL 实测

Ubuntu 打包的默认 ACL(olcDatabase={1}mdb 的 olcAccess,三条):

ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config '(olcDatabase={1}mdb)' olcAccess

实测回显(输出节选):

dn: olcDatabase={1}mdb,cn=config
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {1}to attrs=shadowLastChange by self write by * read
olcAccess: {2}to * by * read

语义逐条解读:

  • {0}:userPassword 属性——本人可写(by self write)、匿名只能用它做认证绑定(by anonymous auth,不能读出值)、其余人无权限;
  • {1}:shadowLastChange——本人可写,所有人可读(配合密码过期策略);
  • {2}:其余全部属性——所有人对全部条目可读(内网开放目录的常见默认,生产按需收紧)。

验证匿名搜索读不到密码哈希:

ldapsearch -x -H ldapi:/// -b dc=lab,dc=local '(uid=zhangsan)' uid cn userPassword

实测回显(输出节选):

dn: uid=zhangsan,ou=people,dc=lab,dc=local
uid: zhangsan
cn: Zhang San

匿名能查到 uid/cn,userPassword 整个属性被 ACL 隐藏(连空值都不返回),{0} 条生效。

9.2 收紧 ACL:禁止匿名读

生产建议把 {2} 从「人人可读」收紧为「认证用户可读」。用 ldapmodify 整体替换 olcAccess(olcAccess 为多值有序属性,先 delete 再 add):

sudo tee /root/acl.ldif > /dev/null << "EOF"
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
-
add: olcAccess
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {1}to attrs=shadowLastChange by self write by * read
olcAccess: {2}to * by self write by users read by * none
EOF
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f /root/acl.ldif

实测回显:

modifying entry "olcDatabase={1}mdb,cn=config"

-Q -Y EXTERNAL 走 ldapi socket 的 SASL EXTERNAL 认证,本地 root 等价 cn=config 管理员,无需密码(机制见《配置参数详解》 frontend 库一节)。

9.3 验证收紧效果

匿名再搜(预期被拒):

ldapsearch -x -H ldapi:/// -b dc=lab,dc=local '(uid=zhangsan)' dn 2>&1 | tail -4

实测回显:

search: 2
result: 32 No such object

认证用户再搜(预期可读):

ldapsearch -x -H ldapi:/// -D "uid=zhangsan,ou=people,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local '(uid=lisi)' dn | grep -c '^dn:'

实测回显:

1

⚠️ ACL 语义坑:匿名无权限时返回的不是 49(凭据错误)而是 32 No such object——LDAP 用「装作不存在」防信息泄露。排查「明明有条目却报 32」时先查 ACL 再怀疑数据。

9.4 全量条目验证

以管理员列出全目录 DN:

ldapsearch -LLL -x -H ldapi:/// -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local '(objectClass=*)' dn

实测回显(输出节选):

dn: dc=lab,dc=local

dn: ou=people,dc=lab,dc=local

dn: ou=groups,dc=lab,dc=local

dn: uid=zhangsan,ou=people,dc=lab,dc=local

dn: uid=lisi,ou=people,dc=lab,dc=local

dn: cn=developers,ou=groups,dc=lab,dc=local

6 条条目齐整,目录结构与数据导入完成。

十、TLS 配置(自签证书)

10.1 生成自签 CA 与服务器证书

用 openssl 生成 10 年期自签 CA,再签发 ldap01 服务器证书(SAN 必须含服务器名,否则客户端校验不过):

sudo mkdir -p /etc/ldap/tls && cd /etc/ldap/tls
sudo openssl req -x509 -newkey rsa:2048 -keyout ca.key -out ca.crt -days 3650 -nodes -subj "/CN=Lab Root CA/O=Lab"
sudo openssl req -newkey rsa:2048 -keyout server.key -out server.csr -nodes -subj "/CN=ldap01.lab.local/O=Lab"
printf "subjectAltName=DNS:ldap01.lab.local,IP:10.89.63.2\n" | sudo tee ext.cnf > /dev/null
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 825 -extfile ext.cnf

实测回显(输出节选):

Certificate request self-signature ok
subject=CN = ldap01.lab.local, O = Lab

查看签发结果:

sudo openssl x509 -in server.crt -noout -subject -dates -ext subjectAltName

实测回显:

subject=CN = ldap01.lab.local, O = Lab
notBefore=Oct 27 02:53:45 2026 GMT
notAfter=Jan 29 02:53:45 2029 GMT
X509v3 Subject Alternative Name: 
    DNS:ldap01.lab.local, IP Address:10.89.63.2

10.2 权限收敛

slapd 以 openldap 身份运行,私钥必须让 openldap 可读且他人不可读:

sudo chown openldap:openldap /etc/ldap/tls/server.key /etc/ldap/tls/server.crt
sudo chmod 640 /etc/ldap/tls/server.key
ls -l /etc/ldap/tls/

实测回显:

total 24
-rw-r--r-- 1 root     root     1155 Oct 27 02:53 ca.crt
-rw------- 1 root     root     1704 Oct 27 02:53 ca.key
-rw-r--r-- 1 root     root       50 Oct 27 02:53 ext.cnf
-rw-r--r-- 1 openldap openldap 1188 Oct 27 02:53 server.crt
-rw-r--r-- 1 root     root      920 Oct 27 02:53 server.csr
-rw-r----- 1 openldap openldap 1704 Oct 27 02:53 server.key

10.3 写入 cn=config 的 TLS 参数

sudo tee /root/tls.ldif > /dev/null << "EOF"
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/tls/ca.crt
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/tls/server.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/tls/server.key
-
add: olcTLSProtocolMin
olcTLSProtocolMin: 3.3
EOF
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f /root/tls.ldif

实测回显:

modifying entry "cn=config"

olcTLSProtocolMin: 3.3 表示最低 TLS 1.2(3.3 是 OpenSSL 版本号记法)。

10.4 启用 636 监听(ldaps:///)

sudo sed -i 's|^SLAPD_SERVICES=.*|SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"|' /etc/default/slapd
grep '^SLAPD_SERVICES' /etc/default/slapd
sudo systemctl restart slapd

实测回显:

SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"

确认 389/636 双监听:

ss -ltn | grep -E ':389|:636'

实测回显:

LISTEN 0      2048         0.0.0.0:389        0.0.0.0:*          
LISTEN 0      2048         0.0.0.0:636        0.0.0.0:*          
LISTEN 0      2048            [::]:389           [::]:*          
LISTEN 0      2048            [::]:636           [::]:*          

10.5 本机验证 ldaps 与 StartTLS

ldaps(636 直连 TLS):

LDAPTLS_CACERT=/etc/ldap/tls/ca.crt ldapsearch -LLL -x -H ldaps://ldap01.lab.local -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn

实测回显:

dn: dc=lab,dc=local

StartTLS(389 明文端口上升级 TLS,-ZZ 表示升级失败即报错):

LDAPTLS_CACERT=/etc/ldap/tls/ca.crt ldapsearch -LLL -x -ZZ -H ldap://ldap01.lab.local -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn

实测回显:

dn: dc=lab,dc=local

两条通道都通。LDAPTLS_CACERT 指向自签 CA 让客户端信任服务器证书;不指定会因证书不受信而失败(远程实测见 10.6)。

10.6 远程客户端验证(第二台机器)

在一台同内网的客户端机器(Ubuntu 22.04,装好 ldap-utils)上,先写 hosts 解析并放 CA 证书:

echo "10.89.63.2 ldap01.lab.local" | sudo tee -a /etc/hosts
sudo cp lab-ca.crt /etc/ssl/certs/lab-ca.crt

ldaps 远程查询:

LDAPTLS_CACERT=/etc/ssl/certs/lab-ca.crt ldapsearch -LLL -x -H ldaps://ldap01.lab.local -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn

实测回显:

dn: dc=lab,dc=local

StartTLS 远程查询:

LDAPTLS_CACERT=/etc/ssl/certs/lab-ca.crt ldapsearch -LLL -x -ZZ -H ldap://ldap01.lab.local -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn

实测回显:

dn: dc=lab,dc=local

对照组:同一命令去掉 CA 信任(证书不受信):

ldapsearch -LLL -x -H ldaps://ldap01.lab.local -D "cn=admin,dc=lab,dc=local" -w q1w2e3r4 -b dc=lab,dc=local -s base dn

实测回显:

ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

⚠️ 排障要点:-1 Can't contact LDAP server 不一定是网络不通。自签证书场景下「客户端不信任 CA」「证书 SAN 不含目标主机名」「服务端没监听 636(见 11.4)」都表现为 -1,按「网络 → 端口监听 → 证书信任链」顺序排查。

10.7 复制边界说明

OpenLDAP 的复制基于 syncprov overlay(RFC 4533 syncrepl),支持主从(refreshOnly/refreshAndPersist)与多主(mirrormode/multiprovider)。本篇为单机形态,不部署复制;模块加载与配置路径的实测演示见本专栏《OpenLDAP 2.5.20 配置参数详解》篇模块一节,多节点复制集群属于进阶形态,需按生产拓扑另行规划。

十一、常见问题(FAQ)

Q1:为什么安装完域不是我指定的,而是跟着主机名走? slapd 的安装脚本在 debconf 未预置答案时,会用 hostname -f 推导默认域:主机名 ldap01.lab.local → 推导域 lab.local → dc=lab,dc=local;主机名不带域(如只叫 server01)时会得到 dc=nodomain。规避方法:要么主机名先改成目标域下的 FQDN 再装,要么按 4.2 预置 debconf 答案。重配按方案 B 走 dpkg-reconfigure。

Q2:dpkg-reconfigure 报 MDB_KEYEXIST: Key/data pair already exists 怎么办? 实测报错原文:

    => mdb_tool_entry_put: id2entry_add failed: err=-30799
    => mdb_tool_entry_put: txn_aborted! MDB_KEYEXIST: Key/data pair already exists (-30799)
    slapadd: could not add entry dn="dc=lab,dc=local" (line=1): txn_aborted! MDB_KEYEXIST: Key/data pair already exists (-30799)

原因:重配向导的「Move old database?」答了 No(或预置 slapd/move_old_database 为 false),旧库未迁移走,新建目录时同一后缀的条目已存在导致 slapadd 撞主键。解决:重跑 dpkg-reconfigure,把 move_old_database 预置为 true 或交互时选 Yes。

Q3:重配完 ldapwhoami 还报 Invalid credentials (49)? 重配把 /var/lib/ldap 与 slapd.d 重建后,必须等 slapd 以新配置重启:确认 systemctl restart slapd 已执行且 systemctl is-active slapd 为 active 再验证。旧进程持有旧口令哈希是 49 的常见原因。

Q4:配了证书但 ldaps 连不上(-1),389 正常? 先看监听:ss -ltn | grep 636。实测发现 /etc/default/slapd 默认 SLAPD_SERVICES="ldap:/// ldapi:///" 不含 ldaps:///,636 根本没监听——配了 olcTLS* 也不会自动开 636。按 10.4 在 SLAPD_SERVICES 加入 ldaps:/// 后 restart,再用 ss 确认双监听。

Q5:客户端报 -1 但服务端看日志没有连接记录? TLS 握手失败发生在 LDAP 协议建立之前,服务端可能无任何应用层日志。按序核对:hosts/域名解析 → 证书 SAN 是否包含所连主机名 → 客户端 LDAPTLS_CACERT 或 TLS_CACERT 是否指向签发该证书的 CA → 证书是否过期(openssl x509 -noout -dates)。

Q6:安装/重配后 /var/backups 下出现 slapd-<版本> 目录是什么? dump_database 策略(默认 when needed)在重配/升级前自动把旧配置与数据 dump 成 LDIF 备份。注意两点:它是回滚材料,别删;同时重装时若它存在且 move_old_database 为 true,会被用于自动恢复(这正是实测中「purge 重装后域还是 lab.local」的原因——备份自动回来了)。想要全新空目录装机,先 rm -rf /var/backups/slapd-* 再装。

Q7:ldapvi 能用吗? Ubuntu 22.04 universe 仓库有 ldapvi 1.7-10build4(apt install ldapvi)。它是交互式编辑器,把搜索结果拉进终端编辑器改完批量回写。边界:必须有 TTY 与 TERM 环境,实测无终端环境时报 TERM environment variable not set. 直接退出;脚本/自动化场景一律用 ldapmodify(命令详解见本专栏《OpenLDAP 2.5.20 常用 CLI 命令详解》篇)。

十二、卸载与清理

彻底卸载 slapd 与 ldap-utils(保留备份目录):

sudo systemctl stop slapd
sudo apt-get purge -y slapd ldap-utils

实测回显(输出节选):

Removing ldap-utils (2.5.20+dfsg-0ubuntu0.22.04.1) ...
Purging configuration files for slapd (2.5.20+dfsg-0ubuntu0.22.04.1) ...
Removing slapd configuration... done.

连带清理数据目录、配置目录与 debconf 记录(如需彻底重来):

sudo rm -rf /var/lib/ldap /etc/ldap/slapd.d
echo PURGE | sudo debconf-communicate slapd

如需全新重装(不被旧备份恢复),先清备份:

sudo rm -rf /var/backups/slapd-*

清理自签证书目录(如不再用):

sudo rm -rf /etc/ldap/tls

之后按第四章重新安装即为全新目录。

十三、参考链接