用脑思考,用心琢磨,用行动证实 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

CentOS、Ubuntu下配置LDAP服务器及相关概念和原理简单介绍

环境配置 memory 发布于November 13, 2017 标签: CentOS, Linux

1. 目录服务

目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。

目录服务是由目录数据库和一套访问协议组成的系统。类似以下的信息适合储存在目录中:

企业员工信息,如姓名、电话、邮箱等;
公用证书和安全密钥;
公司的物理设备信息,如服务器,它的IP地址、存放位置、厂商、购买时间等;
LDAP是轻量目录访问协议(Lightweight Directory Access Protocol)的缩写,LDAP是从X.500目录访问协议的基础上发展过来的,目前的版本是v3.0。与LDAP一样提供类似的目录服务软件还有ApacheDS、Active Directory、Red Hat Directory Service 。

2. LDAP特点

LDAP的结构用树来表示,而不是用表格。正因为这样,就不能用SQL语句了
LDAP可以很快地得到查询结果,不过在写方面,就慢得多
LDAP提供了静态数据的快速查询方式
Client/server模型,Server 用于存储数据,Client提供操作目录信息树的工具
这些工具可以将数据库的内容以文本格式(LDAP 数据交换格式,LDIF)呈现在您的面前
LDAP是一种开放Internet标准,LDAP协议是跨平台的Interent协议

3. LDAP组织数据的方式

1.png

4. 基本概念

在浏览LDAP相关文档时经常会遇见一些概念,下面是常见概念的简单解释。

4.1 Entry

条目,也叫记录项,是LDAP中最基本的颗粒,就像字典中的词条,或者是数据库中的记录。通常对LDAP的添加、删除、更改、检索都是以条目为基本对象的。

dn:每一个条目都有一个唯一的标识名(distinguished Name ,DN),如上图中一个 dn:"cn=baby,ou=marketing,ou=people,dc=mydomain,dc=org" 。通过DN的层次型语法结构,可以方便地表示出条目在LDAP树中的位置,通常用于检索。

rdn:一般指dn逗号最左边的部分,如cn=baby。它与RootDN不同,RootDN通常与RootPW同时出现,特指管理LDAP中信息的最高权限用户。

Base DN:LDAP目录树的最顶部就是根,也就是所谓的“Base DN",如"dc=mydomain,dc=org"。

4.2 Attribute

每个条目都可以有很多属性(Attribute),比如常见的人都有姓名、地址、电话等属性。每个属性都有名称及对应的值,属性值可以有单个、多个,比如你有多个邮箱。

属性不是随便定义的,需要符合一定的规则,而这个规则可以通过schema制定。比如,如果一个entry没有包含在 inetorgperson 这个 schema 中的objectClass: inetOrgPerson,那么就不能为它指定employeeNumber属性,因为employeeNumber是在inetOrgPerson中定义的。

LDAP为人员组织机构中常见的对象都设计了属性(比如commonName,surname)。下面有一些常用的别名:

4.3 ObjectClass

对象类是属性的集合,LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。

通过对象类可以方便的定义条目类型。每个条目可以直接继承多个对象类,这样就继承了各种属性。如果2个对象类中有相同的属性,则条目继承后只会保留1个属性。对象类同时也规定了哪些属性是基本信息,必须含有(Must 活Required,必要属性):哪些属性是扩展信息,可以含有(May或Optional,可选属性)。

对象类有三种类型:结构类型(Structural)、抽象类型(Abstract)和辅助类型(Auxiliary)。结构类型是最基本的类型,它规定了对象实体的基本属性,每个条目属于且仅属于一个结构型对象类。抽象类型可以是结构类型或其他抽象类型父类,它将对象属性中共性的部分组织在一起,称为其他类的模板,条目不能直接集成抽象型对象类。辅助类型规定了对象实体的扩展属性。每个条目至少有一个结构性对象类。

对象类本身是可以相互继承的,所以对象类的根类是top抽象型对象类。以常用的人员类型为例,他们的继承关系:
2.jpg

下面是inetOrgPerson对象类的在schema中的定义,可以清楚的看到它的父类SUB和可选属性MAY、必要属性MUST(继承自organizationalPerson),关于各属性的语法则在schema中的attributetype定义。

# inetOrgPerson
# The inetOrgPerson represents people who are associated with an
# organization in some way.  It is a structural class and is derived
# from the organizationalPerson which is defined in X.521 [X521].
objectclass     ( 2.16.840.1.113730.3.2.2
    NAME 'inetOrgPerson'
        DESC 'RFC2798: Internet Organizational Person'
    SUP organizationalPerson
    STRUCTURAL
        MAY (
                audio $ businessCategory $ carLicense $ departmentNumber $
                displayName $ employeeNumber $ employeeType $ givenName $
                homePhone $ homePostalAddress $ initials $ jpegPhoto $
                labeledURI $ mail $ manager $ mobile $ o $ pager $
                photo $ roomNumber $ secretary $ uid $ userCertificate $
                x500uniqueIdentifier $ preferredLanguage $
                userSMIMECertificate $ userPKCS12 )
        )

4.4 Schema

对象类(ObjectClass)、属性类型(AttributeType)、语法(Syntax)分别约定了条目、属性、值,他们之间的关系如下图所示。所以这些构成了模式(Schema)——对象类的集合。条目数据在导入时通常需要接受模式检查,它确保了目录中所有的条目数据结构都是一致的。
3.jpg
schema(一般在/etc/openldap/schema/目录)在导入时要注意前后顺序。

4.5 backend & database

ldap的后台进程slapd接收、响应请求,但实际存储数据、获取数据的操作是由Backends做的,而数据是存放在database中,所以你可以看到往往你可以看到backend和database指令是一样的值如 bdb 。一个 backend 可以有多个 database instance,但每个 database 的 suffix 和 rootdn 不一样。openldap 2.4版本的模块是动态加载的,所以在使用backend时需要moduleload back_bdb指令。

bdb是一个高性能的支持事务和故障恢复的数据库后端,可以满足绝大部分需求。许多旧文档里(包括官方)说建议将bdb作为首选后端服务(primary backend),但2.4版文档明确说hdb才是被首先推荐使用的,这从 2.4.40 版默认安装后的配置文件里也可以看出。hdb是基于bdb的,但是它通过扩展的索引和缓存技术可以加快数据访问,修改entries会更有效率,有兴趣可以访问上的链接或slapd.backends。

另外config是特殊的backend,用来在运行时管理slapd的配置,它只能有一个实例,甚至无需显式在slapd.conf中配置。

4.6 TLS & SASL

分布式LDAP 是以明文的格式通过网络来发送信息的,包括client访问ldap的密码(当然一般密码已然是二进制的),SSL/TLS 的加密协议就是来保证数据传送的保密性和完整性。

SASL (Simple Authenticaion and Security Layer)简单身份验证安全框架,它能够实现openldap客户端到服务端的用户验证,也是ldapsearch、ldapmodify这些标准客户端工具默认尝试与LDAP服务端认证用户的方式(前提是已经安装好 Cyrus SASL)。SASL有几大工业实现标准:Kerveros V5、DIGEST-MD5、EXTERNAL、PLAIN、LOGIN。

Kerveros V5是里面最复杂的一种,使用GSSAPI机制,必须配置完整的Kerberos V5安全系统,密码不再存放在目录服务器中,每一个dn与Kerberos数据库的主体对应。DIGEST-MD5稍微简单一点,密码通过saslpasswd2生成放在sasldb数据库中,或者将明文hash存到LDAP dn的userPassword中,每一个authid映射成目录服务器的dn,常和SSL配合使用。参考将 LDAP 客户端配置为使用安全性

EXTERNAL一般用于初始化添加schema时使用,如ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif。

CentOS安装

安装之前查一下

find / -name openldap*

centos6.4默认安装了LDAP,但没有装ldap-server和ldap-client

于是yum安装

yum install -y openldap openldap-servers openldap-clients

或者

yum install -y openldap*

不建议编译源码包,有依赖比较麻烦

网上很多人说在安装openladp之前,需要先安装Berkeley,作为ladp的存储方案,这个不是必须的,可以不装!

安装以后进行配置

cp /usr/share/openldap-servers/slapd.conf.obsolete /etc/openldap/slapd.conf
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
mv /etc/openldap/slapd.d{,.bak}

然后通过vi修改slapd.conf,步骤如下:

找到语句:

suffix "dc=my-domain,dc=com"

将其改为:

suffix "dc=example,dc=com"

2.该语句设置LDAP管理员的DN

找到语句:

rootdn "cn=Manager,dc=my-domain,dc=com"

将其改为:

rootdn "cn=Manager,dc=example,dc=com"

3.设置LDAP管理员的口令

找到语句:

rootpw secret

将其改为:

rootpw 你的密码

口令也可以用明文 也可以用 slappasswd 生成

配置文件修改之后分下权限

chown ldap.ldap /etc/openldap/*
chown ldap.ldap /var/lib/ldap/*

新建目录

mkdir /etc/openldap/cacerts

然后重启下系统(一定要重启)

然后开启服务

service slapd start
chkconfig slapd on

默认的启动端口是389,因为1024以下端口需要用root才能绑定,当然也可以修改端口

slapd -f /etc/openldap/slapd.conf -h ldap://3891

等服务启动以后可以导入一些初始数据 新建文件example.ldif

dn:dc=example,dc=com
objectclass:dcObject
objectclass:organization
o:Example, Inc.
dc:example

dn:cn=Manager,dc=example,dc=com
objectclass:organizationalRole
cn:Manager

然后通过命令导入

/usr/bin/ldapadd -x -W -D "cn=Manager,dc=example,dc=com" -f example.ldif

提示输入密码 既是manager的密码
然后导入成功

Ubuntu安装

1.1 准备编译环境和依赖包

# apt-get install build-essential
# apt-get install libssl-dev

下载openldap-2.4.31.tgz和db-5.1.29.NC.tar.gz并解压:

# cd /usr/local/src
src# wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-2.4.31.tgz
# wget http://download.oracle.com/berkeley-db/db-5.1.29.NC.tar.gz
# tar -zxf openldap-2.4.31.tgz
# tar -zxf db-5.1.29.NC.tar.gz
# cd db-5.1.29.NC/build_unix/
# ../dist/configure --prefix=/usr/local/berkeleydb-5.1
# make && make install

建议人工指定--prefix,默认会安装到/usr/local/BerkeleyDB.5.1。上面的make过程会比较长,另外如果gcc版本在4.7及以上,可能会出现如下warning,可以忽略:

../src/dbinc/atomic.h:179:19: warning: conflicting types for built-in function
 ‘__atomic_compare_exchange’ [enabled by default]

1.2 安装openldap
设置一些环境变量,修改/etc/profile/etc/bash.bashrc

export BERKELEYDB_HOME="/usr/local/berkeleydb-5.1"
export CPPFLAGS="-I$BERKELEYDB_HOME/include"
export LDFLAGS="-L$BERKELEYDB_HOME/lib"
export LD_LIBRARY_PATH="$BERKELEYDB_HOME/lib"
export LDAP_HOME="/usr/local/openldap-2.4"
export PATH="$PATH:$BERKELEYDB_HOME/bin:$LDAP_HOME/bin:$LDAP_HOME/sbin:$LDAP_HOME/libexec"

其实只要在后面编译openldap时能找到lib和include下的库就行了,不止上面设置环境变量一种办法,解决办法还有直接复制对应的库文件到/usr/lib/usr/include,或修改/etc/ld.so.conf.d,选其一即可。

编译安装:

openldap-2.4.31# ./configure --prefix=/usr/local/openldap-2.4
# make depend
# make
# make install

出错提示解决:
如果没设置CPPFLAGS,上面的configure过程可能会提示configure: error: BDB/HDB: BerkeleyDB not available
如果提示

configure: error: MozNSS not found - please specify the location to the NSPR and NSS header files 
in CPPFLAGS and the location to the NSPR and NSS libraries in LDFLAGS (if not in the system location)

configure: error: no acceptable C compiler found in $PATH

请检查第一步的依赖是否已经安装,查看openldap解压目录下的README看到REQUIRED SOFTWARE。

2 配置
2.1 基本配置
/usr/local/openldap-2.4目录结构:

bin/      --客户端工具如ldapadd、ldapsearch
etc/      --包含主配置文件slapd.conf、schema、DB_CONFIG等
include/
lib/
libexec/  --服务端启动工具slapd
sbin/     --服务端工具如slappasswd
share/
var/      --bdb数据、log存放目录

2.1.1 配置root密码

# slappasswd 
New password: 
Re-enter new password: 

2.1.2 修改后的slapd.conf

include        /usr/local/openldap-2.4.31/etc/openldap/schema/core.schema
include        /usr/local/openldap-2.4.31/etc/openldap/schema/cosine.schema
include        /usr/local/openldap-2.4.31/etc/openldap/schema/inetorgperson.schema
pidfile        /usr/local/openldap-2.4.31/var/run/slapd.pid
argsfile    /usr/local/openldap-2.4.31/var/run/slapd.args
loglevel 256
logfile  /usr/local/openldap-2.4.31/var/slapd.log 
database    bdb
suffix        "dc=mydomain,dc=net"
rootdn        "cn=root,dc=mydomain,dc=net"
rootpw        你生成的密码填这儿
directory    /usr/local/openldap-2.4.31/var/openldap-data
index    objectClass    eq

根据自己的需要加入schema,suffix一般填入域名,rootdn处是管理ldap数据的管理员用户,rootpw便是使用slappasswd生成的加密密码。

2.1.3 启动slapd服务

# /usr/local/openldap-2.4.31/libexec/slapd

会自动使用/etc/openldap/slapd.conf作为配置文件启动,并写入/usr/local/openldap-2.4.31/var/run/slapd.args中。这里有个问题未解决,配置loglevel和logfile但始终都看不到记录的日志,启动时加入-d 256能正常输出到屏幕上。

2.1.4 测试数据
编辑一个添加entries的文件test.ldif:

dn: dc=mydomain,dc=net
objectClass: dcObject
objectClass: organization
dc: mydomain
o: mydomain.Inc

dn: cn=root,dc=mydomain,dc=net
objectClass: organizationalRole
cn: root

dn: ou=itsection,dc=mydomain,dc=net
ou: itsection
objectClass: organizationalUnit

dn: cn=sean,ou=itsection,dc=mydomain,dc=net
ou: itsection
cn: user2
sn: password2222
objectClass: inetOrgPerson
objectClass: organizationalPerson

插入数据:

查看(匿名)
# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts

添加(读入密码)
# ldapadd -x -D "cn=root,dc=mydomain,dc=net" -W -f test.ldif

验证
# ldapsearch -x -b 'dc=mydomain,dc=net' '(objectClass=*)'

或手动添加条目
# ldapadd -x -D "cn=root,dc=mydomain,dc=net" -W
Enter LDAP Password: 
dn:cn=Angelababy,ou=itsection,dc=mydomain,dc=net
cn:Angelababy
sn:baby  
objectClass:inetOrgPerson
objectClass:organizationalPerson

adding new entry "cn=baby,ou=itsection,dc=mydomain,dc=net"

到这里,一个简易版的LDAP服务就搭建好了,下面介绍一些额外的高级配置。

配置安全的ssl加密传输

在某些应用环境下可能需要加密传输ldap里的信息,配置TLS难点在于证书的生成。
2.2.1 自签署ssl证书

(1) 生成根密钥
# cd /etc/ssl/demoCA/
# openssl genrsa -out private/cakey.pem 2048

(2) 生成根证书,位于/etc/ssl/demoCA/下(CentOS位于/etc/pki/CA)
# openssl req -new -x509 -key private/cakey.pem -out cacert.pem

(3) 初始化CA
demoCA# mkdir private newcerts
# touch newcerts index.txt serial
# echo "00" > serial

(4) 在ldap服务器上生成ssl密钥(可以是/tmp/certs下)
# openssl genrsa -out ldap.key

(5) 为ldap生成证书签署请求(所填写内容尽量与第2步相同)
    Common Name填写主机名或域名,password留空
# openssl req -new -key ldap.key -out ldap.csr

(6) ca根据请求签发证书,得到.crt证书文件
# openssl ca -in ldap.key -out ldap.crt

如果在你的环境中已经有一个证书授权中心CA,那么只需要在ldap服务器上使用openssl生成密钥.key和签署请求.csr(第4、5步),然后将.csr发给CA服务器来生成证书.crt(第6步)。

2.2.2 在slapd.conf中加入TLS
可以是其它能访问的位置

# mkdir $OPENLDAP_HOME/etc/openldap/cacerts
# cp cacert.pem $OPENLDAP_HOME/etc/openldap/cacerts
# cp ldap.crt $OPENLDAP_HOME/etc/openldap/
# cp ldap.key $OPENLDAP_HOME/etc/openldap/

/etc/openldap/slapd.conf中加入以下信息

TLSCACertificateFile /usr/local/openldap-2.4/etc/openldap/cacerts/cacert.pem
TLSCertificateFile /usr/local/openldap-2.4/etc/openldap/ldap.crt
TLSCertificateKeyFile /usr/local/openldap-2.4/etc/openldap/ldap.key

2.2.3 重新启动slapd

# killall slapd     关闭slapd standalone daemon
# ./libexec/slapd -h 'ldap://0.0.0.0:389/ ldaps://0.0.0.0:636/ ldapi:///'
或只监听636加密端口
# ./libexec/slapd -h 'ldaps://0.0.0.0:636/'

如果是正式环境使用加密的话,389端口前的IP换成127.0.0.1。

2.2.4 验证
ldapsearch
使用自带的ldapsearch或ldapadd客户端工具来连接slapd,需要设置ldap.conf或~/.ldaprc文件中的TLS_CACERT为信任的根证书才能使用,否则会提示

TLS certificate verification: Error, self signed certificate in certificate chain
TLS trace: SSL3 alert write:fatal:unknown CA

所以在在使用ldapsearch的服务器上修改/etc/ldap/ldap.conf:(man ldap.conf)

BASE    dc=mydomain,dc=net
URI     ldaps://apptest.mydomain.net:636
TLS_CACERT /usr/local/openldap-2.4/etc/openldap/cacerts/cacert.pem

当然也可以TLS_REQCERT never来信任根证书

ldapsearch -x -D "cn=root,dc=mydomain,dc=net" -W -LLL

或写全

ldapsearch -x -b 'dc=mydomain,dc=net' '(objectClass=*)' -H ldaps://apptest.mydomain.net:636 -D "cn=root,dc=mydomain,dc=net" -W

需要注意的是,URI后的 Server name 必须与签署证书使用的 Common name 一致。另外在ldap server本地执行ldapsearch默认使用的客户端配置文件是$LDAP_HOME/etc/openldap/ldap.conf。

相关推荐

添加新评论

网站状态

  • 栏目分类:49个
  • 发布文章:1308篇
  • 用户评论:687条
  • 开博至今:3976天

正则速查

[abc] 匹配中括号中的单个字符,如a或b或c
[^abc] 匹配除了a、b、c等字符的其他单个字符
[a-z] 匹配一个字符范围,如a到z
[a-zA-Z] 匹配一个字符范围,如a-z 或 A-Z
^ 匹配行的开始
$ 匹配行的结束
\A 匹配一个字符串的开始
\z 匹配一个字符串的结束
. 匹配任意单个字符
\s 匹配空白字符,如空格,TAB
\S 匹配非空白字符
\d 匹配一个数字
\D 匹配非数字
\w 匹配一个字母
\W 匹配非字幕
\b 匹配字符边界
(...) 引用所有括号中的内容
(a|b) a或者b
a? 零个或多个a
a* 零个或多个a
a+ 1个或多个a
a{3} 3次重复的a
a{3,} 3次或3次以上重复的a
a{3,6} 3到6次重复的a

修正符

/g 查找所有可能的匹配
/i 不区分大小写
/m 多行匹配
/s 单行匹配
/x 忽略空白模式
/e 可执行模式,PHP专有
/A 强制从目标字符串开头匹配
/D 使用$限制结尾字符,则不允许结尾有换行
/U 只匹配最近的一个字符串;不重复匹配

最新回复

  • memory: 这是我3年前玩过一次,当时因为安装完后,发现日常办公还好,但是好...
  • sdf: 想问一下,激活工具激活后,后面会出现提示要再次重新激活吗?
  • memory: 你要用碗装我吗?还是要我把扔的扔进你碗里???!!! &^_^&
  • 薛才杰: 同感,快扔到我的碗里来。。。
  • memory: 要说明一下,在大陆及香港的云主机或VPS,都是不支持的。原因都懂...
  • 历史趣谈LishiQtan: 很好的文章,值得收藏
  • memory: 现在回头看,,,这么烂的代码,也是醉了.
  • memory: 有空试试apache的
  • 脚踏实地: rInfo数组是怎么来的
  • 朋友们: 我都是这么建站的
  • memory: 明眼人.
  • 上官元恒: $lunarInfo数组是怎么来的,这是重点
  • memory: 你知道的太多了...
  • yjl: 这个肯定解决的不是空间的问题,可能是复用的问题,有可能是“站群”的问题
  • Smithd994: Hello! This post could not be wr...
  • memory: controll文件assign ,然后模板文件中直接foreach
  • mike: 你好,yaf怎么使用循环输出数据到模板中