最近遇到的一个需求,某集团二级分公司需要将集团公司提供的LDAP数据同步到本地自建的LDAP服务器上,要求全量覆盖当前集团公司LDAP上的数据信息,并且定期更新集团公司LDAP服务器上的增量数据。OK,下面开始记录操作过程。
openEuler 24.04 LTS SP2 (kernel 6.6.0-98.0.0.103)
Open LDAP 2.6.5-6
| 项目
|
说明 |
| LDAP Provider | 172.16.1.23 |
| Base DN
|
dc=example |
| USER DN | cn=example |
| 密码 | P@ssw0rd |
| 访问限制 | 仅LDAP协议(无SSH / 无直接远端 cn=config 修改权限) |
| 同步需求 | 单向: Provider -> Consumer(本地) |
openEuler 24.04系统,OpenLDAP相关软件分别为 openldap-servers 和 openldap-clients 默认放在BaseOS仓库中,无需额外配置就可直接使用,安装命令如下:

安装完成后,激活OpenLDAP服务随操作系统自动启动,操作如下
[root@ldap-server ~]# systemctl list-unit-files | grep slapd slapd.service disabled disabled [root@ldap-server ~]# systemctl enable --now slapd.service Created symlink /etc/systemd/system/openldap.service → /usr/lib/systemd/system/slapd.service. Created symlink /etc/systemd/system/multi-user.target.wants/slapd.service → /usr/lib/systemd/system/slapd.service. [root@ldap-server ~]# systemctl status slapd.service ● slapd.service - OpenLDAP Server Daemon Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; preset: disabled) Active: active (running) since Mon 2025-09-22 16:57:34 CST; 9s ago Docs: man:slapd man:slapd-config man:slapd-hdb man:slapd-mdb file:///usr/share/doc/openldap-servers/guide.html Process: 24525 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS) Process: 24539 ExecStart=/usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:/// (code=exited, status=0/SUCCESS) Main PID: 24541 (slapd) Tasks: 2 (limit: 43221) Memory: 2.8M () CGroup: /system.slice/slapd.service └─24541 /usr/sbin/slapd -u ldap -h "ldap:/// ldaps:/// ldapi:///"
安装完成后LDAP默认数据库存放在/var/lib/ldap中,建议需要为本次部署专门创建一个专用数据库文件存放目录
[ldap-server ~]# mkdir -p /var/lib/ldap/example [ldap-server ~]# chown -R ldap:ldap /var/lib/ldap/example [ldap-server ~]# chmod 750 /var/lib/ldap/example
准备工作完成后,开始编写本地LDAP数据库初始化文件 init_mdb.ldif
[ldap-server ~]# slappasswd -s P@ssw0rd
{SSHA}yXMZfhw69l3ZsvqOHGZM56BTDFhga9bL
[ldap-server ~]# vim init_mdb.ldif
dn: olcDatabase=mdb,cn=config
changetype: add
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbDirectory: /var/lib/ldap/example
olcSuffix: dc=example
olcRootDN: cn=example,dc=example
olcRootPW: {SSHA}yXMZfhw69l3ZsvqOHGZM56BTDFhga9bL
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by dn.base="cn=example,dc=example" write by * none
olcAccess: {1}to * by self write by dn.base="cn=example,dc=example" write by * read
olcLastMod: TRUE
olcDbCheckpoint: 512 30
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
init_mdb.ldif中重点在于olcSuffix和olcRootDN,出处oclSuffix采用了简写便于与远端的LDAP服务器保持一致。olcRootDN做了本地化调整,根据远端LDAP服务器信息做出了适当的本地化调整。
其次,为了遵守密码不能明文保存的安全规范,使用在正式开始编辑init_mdb.ldif文件前,使用了slappasswd 生成了密钥 P@ssw0rd 的hash值,并在olcRootPW字段中将这个hash值正式赋值给olcRootPW。
再次,olcDbDirectory字段是用于指定数据库文件的存放路径的,这里使用的是前面手动创建的新存放路径/var/lib/ldap/example
最后确认两个olcAccess中 dn.base中涉及的cn和dn关键字要与olcRootDN中保持一致。
保存好init_mdb.ldif文件后,可以开始初始化数据库了,初始化数据库命令如下:
[root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f init_mdb.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "olcDatabase=mdb,cn=config"
验证数据库是否创建成功
[root@ldap-server ~]# ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" "(olcDatabase=*)" dn olcDatabase
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# basewith scope subtree# filter: (olcDatabase=*)
# requesting: dn olcDatabase
#
# {-1}frontend, config
dn: olcDatabase={-1}frontend,cn=config
olcDatabase: {-1}frontend
# {0}config, config
dn: olcDatabase={0}config,cn=config
olcDatabase: {0}config
# {1}monitor, config
dn: olcDatabase={1}monitor,cn=config
olcDatabase: {1}monitor
# {2}mdb, config
dn: olcDatabase={2}mdb,cn=config
olcDatabase: {2}mdb
# {3}mdb, config
dn: olcDatabase={3}mdb,cn=configo
lcDatabase: {3}mdb
# search result
search: 2
result: 0 Success
# numResponses: 6
# numEntries: 5
通过返回结果可以看到现在多了一个{3}mdb,本地mdb数据库初始化完成
接下来导入LDAP字段所需的schema,默认情况下LDAP值会加载core.schema。openEuler 24.04的LDAP schema存放路径是/etc/openldap/schema
[root@ldap-server ~]# ll /etc/openldap/schema/ total 552 -r--r--r--. 1 root root 2036 Jul 11 2023 collective.ldif -r--r--r--. 1 root root 6191 Jul 11 2023 collective.schema -r--r--r--. 1 root root 1845 Jul 11 2023 corba.ldif -r--r--r--. 1 root root 8063 Jul 11 2023 corba.schema -r--r--r--. 1 root root 20619 Jul 11 2023 core.ldif -r--r--r--. 1 root root 20506 Jul 11 2023 core.schema -r--r--r--. 1 root root 12006 Jul 11 2023 cosine.ldif -r--r--r--. 1 root root 73995 Jul 11 2023 cosine.schema -rw-r--r--. 1 root root 22869 Mar 8 2022 dhcp.schema -r--r--r--. 1 root root 3594 Jul 11 2023 dsee.ldif -r--r--r--. 1 root root 3374 Jul 11 2023 dsee.schema -r--r--r--. 1 root root 4842 Jul 11 2023 duaconf.ldif -r--r--r--. 1 root root 10389 Jul 11 2023 duaconf.schema -r--r--r--. 1 root root 3500 Jul 11 2023 dyngroup.ldif -r--r--r--. 1 root root 3523 Jul 11 2023 dyngroup.schema -r--r--r--. 1 root root 3481 Jul 11 2023 inetorgperson.ldif -r--r--r--. 1 root root 6267 Jul 11 2023 inetorgperson.schema -r--r--r--. 1 root root 2979 Jul 11 2023 java.ldif -r--r--r--. 1 root root 13901 Jul 11 2023 java.schema -r--r--r--. 1 root root 2082 Jul 11 2023 misc.ldif -r--r--r--. 1 root root 2387 Jul 11 2023 misc.schema -r--r--r--. 1 root root 121865 Jul 11 2023 msuser.ldif -r--r--r--. 1 root root 113752 Jul 11 2023 msuser.schema -r--r--r--. 1 root root 1218 Jul 11 2023 namedobject.ldif -r--r--r--. 1 root root 1574 Jul 11 2023 namedobject.schema -r--r--r--. 1 root root 6809 Jul 11 2023 nis.ldif -r--r--r--. 1 root root 7640 Jul 11 2023 nis.schema -r--r--r--. 1 root root 3308 Jul 11 2023 openldap.ldif -r--r--r--. 1 root root 1514 Jul 11 2023 openldap.schema -r--r--r--. 1 root root 6904 Jul 11 2023 pmi.ldif -r--r--r--. 1 root root 20467 Jul 11 2023 pmi.schema
这里需要手动加载consine、nis、inetorgperson三个schema,操作命令如下:
[root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=cosine,cn=schema,cn=config" [root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=nis,cn=schema,cn=config" [root@ldap-server ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=inetorgperson,cn=schema,cn=config"
PS:如果有自定义的schema,请参考操作自行调整schema的存放路径和文件名
完成以上操作,本地LDAP前置准备就基本就绪,接下来导出远端LDAP上的全量数据后,导入到本地LDAP数据库当中。
参考以下命令进程操作,对远端的LDAP服务器上的数据进行全量导出
[root@ldap-server ~]# ldapsearch -H ldap://172.16.1.23:389 \ -D "cn=example" -w 'P@ssw0rd' \ -b "dc=example" -s sub '(objectClass=*)' "*" -LLL > full_raw.ldif
全量数据的本地导入存在两种方式,分别是离线导入和在线导入
参考以下命令进行操作,完成在线的全量数据导入
[root@ldap-server ~]# ldapadd -H ldap://127.0.0.1:389 \ -D 'cn=example,dc=example' -w 'P@ssw0rd' -f full_clean.ldif ……
参考以下操作命令,完成离线数据的全量导入
[root@ldap-server ~]# systemctl stop slapd [root@ldap-server ~]# slapadd -b 'dc=example' -l full_clean.ldif [root@ldap-server ~]# chown -R ldap:ldap /var/lib/ldap/example [root@ldap-server ~]# systemctl start slapd
参考以下操作命令,查询本地LDAP数据库中的数据是否存在
[root@ldap-server ~]# ldapsearch -H ldap://127.0.0.1:389 \ -x -b dc=example '(cn=Uxxxxxxxxxx)' cn uid
其中需要注意的地方是这里的cn和uid代换的问题,我们查询过远端的LDAP服务器上的数据,UID就是直接用cn标识的,所以在这里默认使用了cn=Uxxxxxxxxxx作为查询的条件,如果需要可以替换成uid=Uxxxxxxxx作为查询条件
通过上述操作,远端LDAP服务器上的全量数据已经被同步到本地LDAP服务器当中,接下来需要解决的是增量部分
增量同步需要使用到syncrepl refreshAndPersist,首先测试确认远端LDAP服务器接受DN访问是全DN还是短DN。
根据当前已知信息,测试方法如下:
1. 短DN,参考以下参数进行测试
[root@ldap-server ~]# ldapwhoami -H ldap://172.16.1.23:389 -D "cn=example" -w 'P@ssword01'
2. 全DN,参考以下参数进行测试
[root@ldap-server ~]# ldapwhoami -H ldap://172.16.1.23:389 -D "cn=example,dc=example" -w 'P@ssword01'
判断命令是否执行成功,可根据返回值进行判断。
返回值为 ldap_bind: Invalid credentials (49) 表示测试失败;
返回值为 dn:cn=Directory Manager,cn=Root DNs,cn=config 表示测试成功
接下来需要配置增量同步,编辑add_syncrepl.ldif文件
[root@ldap-server ~]# vim add_syncrepl.ldif
dn: olcDatabase={3}mdb,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl: rid=001
provider=ldap://172.16.1.23
type=refreshAndPersist
searchbase="dc=example"
bindmethod=simple
binddn="cn=example"
credentials=P@ssw0rd
schemachecking=on
retry="5 5 300 +"
timeout=3
-
add: olcUpdateRef
olcUpdateRef: ldap://172.16.1.23
其中olcSyncRepl参数说明如下:
rid: 取值范围001—999之间 一台机器上有多个同步源的,请按需配置这个值,不能重复
provider:上游LDAP服务器的URI
binddn:这个地方一定要注意,一定填入 ldapwhoami 命令返回正确测试结果的DN值,这里我测试返回的是短DN测试结果,所以这里我填入的是cn=example
retry:每两个数字为一对,表示一个阶段。以这里的为例
第一段 5 5 表示:当第一次发现同步失败后立即进入重试阶段,每隔5秒重试一次,连续重试5次。适用于短暂网络抖动、瞬时超时、对端 slapd reload 等;
第二段 300 + 表示:如果前 5 次快速重试仍未恢复,则进入“长间隔”阶段:以后永远每隔 300 秒(5 分钟)重试一次,直到成功为止。这里的 + 就代表无限循环的意思
credential 是访问密码的明文,如需要不暴露这个远端访问的密码,建议启用SASL机制或基于客户端证书的TLS机制来增加配置的安全性。
timeout 是在网络层面一次ldap操作(connect/search/add/modify/bind等)的等待超时时间,不是retry的间隔。
若timeout太小+网络延迟稍大,会造成频繁的“失败—>立即进入重试阶段”。
推荐:在同网段情况下timeout设置为范围建议3到5,跨网段可设置在5到8之前,首段retry间隔需 ≥ timeout 否则 retry设置没意义
参考以下命令执行更新
[root@ldap-server]# ldapmodify -Y EXTERNAL -H ldapi:/// -f add_syncrepl.ldif
执行完成后验证
[root@ldap-server]# ldapsearch -Y EXTERNAL -H ldapi:/// -b "olcDatabse={3}mdb,cb=config" olcSyncRepl
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <olcDatabase={3}mdb,cn=config> with scope subtree
# filter: (objectclass=*)
# requesting: olcSyncRepl
#
# {3}mdb, config
dn: olcDatabase={3}mdb,cn=config
olcSyncrepl: {0}rid=001 provider=ldap://10.3.11.23 type=refreshAndPersist sear
chbase="dc=dongfang" bindmethod=simple binddn="cn=dongfang" credentials=P@ssw
ord01 schemachecking=on retry="5 5 300 +" timeout=3
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
综上所述,本次需求操作所有相关配置完成。本地LDAP可以定时从远端LDAP服务器上同步最新数据
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70042155/viewspace-3096268/ ,如需转载,请注明出处,否则将追究法律责任。