在Linux上建立LDAP服务器
2012-06-12 15:33:03

你的网络在规模和复杂性方面正处于成长期。一路传播每件事物、发展壮大每件事物然后再丢弃每件事物将占用了它一生的时间。当你痛苦的双手抱头,试图弄清楚 的时候,你的用户不知道从哪里发现了你的秘密电话号码,他用无穷无尽的问题和要求来纠缠你——这就是我发现它的地方;我并不想记住一打不同的密码;没有工 作应该是这样子的。

一、LDAP的基本概念以及LDAP的用途
 LDAP能做什么
 LDAP不能做什么
 到数据库或者不到数据库
 根和层
 易于升级
 ACIs的和ACLs
 用户认证
 一块卓越的奶酪

LDAP能做什么
 简要地说,LDAP提供了访问、认证和授权的集中管理。他是很容易自定义的并且能够:
 ·用户和用户组管理集中化
 ·信息存储集中化
 ·设置安全和访问控制
 ·安全委托读取和修改权
 ·服务于几乎所有平台
 ·有效地缩放

LDAP不能做什么
 ·成为一个负载过重的关联或交互数据库
 ·成为一个文件系统
 ·在许多范围内跳过高层结构
LDAP协议跨平台、网络意识强、并且基于标准。市场上现在有来自于各个投资商的各种各样的LDAP实现。本系列将主要讨论Linux 上的OpenLDAP 。

到数据库或者不到数据库
现在我们来当一回书生(请戴上你的讨厌胡须和书生用的袖珍保护套)。LDAP——轻型目录访问协议——是一个协议,不是一个数据库。它可访问一种特殊类型 的数据库,这种数据库为了快速阅读而最优化。使用LDAP可得到相关的静态信息,如公司目录、用户数据、消费者数据、密码和安全钥匙。 OpenLDAP使用了Sleepycat Berkeley DB。说了这么多,我可不是一个老夫子,我只是很满意调用它来运转数据库并且对它所作的工作很满意。

LDAP 不是一个好的选择,尽管有时你需要快速而频繁的修改——例如为了零售后台。它不是一个关联数据库如Oracle、 mySQL 或者 Postgres。实际上,它的结构与关联数据库有着天壤之别。与其将信息存储在行列中,并且设置一组固定的索引和字段,还不如将数据储存在属性类型/属 性值对中。这种结构为设计记录提供了巨大的灵活性。例如:一份特殊的用户记录不必重新设计整个数据库就可以添加一种新的类型。任何类型的文本或者二进制数 据都可以储存。

根和层
LDAP目录遵循熟悉的Unix文件系统结构——树的顶部有根目录,由根目录分支成许多子目录。典型设计就是一个公司只有一个主要的根目录。然后根据部 门、位置、功能,雇员的好坏等等对你来说有用和有意义的任何事物来组织子目录。这不但是组织主目录的一个很好的整理方法,它还允许你使用一种精确的、受约 束的方式授予对中心数据池的特殊部分的访问权。

下一步就是采用一种明智的方式分布比特。任何单独的子目录都可复制到其他地方——例如复制到它从属的部门所在的服务器。在任何你喜欢的时间间隔内,对主目 录的更新可同步进行,它为用户提供冗余和更快访问,而且使得主服务器上的紧张程度降低。
更新可以根据指示开始进行——或者,如果你需要一个使用术语的理由,那就用"push" 或者 "pull."吧。例如:财政部可先更新他们的目录,然后将更新推进到主服务器上——再次,节省了管理部门许多单调的而且不必要的劳动。它还保存了带宽和 系统资源。

易于升级
关于LDAP的分布式特征真正灵活的是你可以从小的开始。你可以采用一种限制性的方式来实现一个LDAP目录,对他进行测试和悬挂,然后在空闲时间内轻而易举地将它放大并迁移更多的功能把它上面。

ACIs的和ACLs
LDAP 访问控制范例(ACIs),共同形成了一个访问控制清单(ACL),它允许非常细粒度的控制。下面是几个简单例子:
 ·用户可以修改他们自己的个人信息——例如家庭住址、电话扩充、工作email等等——但是其他人不可以。
 ·某个特殊用户的所有信息可保存在单独的记录中,但是对单项的访问完全是可以配置的。
 ·给与经理确切级别的阅读权和对于他们小组的读/写权利。它满足的一个特殊需要就是给与经理充分的访问权,以监督项目文件和报告,但是不给钱。
 ·允许小组或者小组领导判断哪个人可以得到哪种他们控制下的资源访问权。我绝对不喜欢被次要的琐事如共享文档和项目目录所纠缠,放权给群众好了。
 ·将密码和用户名以及其他敏感数据置于勤奋的系统管理员的严格控制之下。

用户认证
LDAP支持SASL (简单认证和安全层),它合并了Kerberos、GSSAPI、和 DIGEST-MD。添加LDAP用户认证到一个现有的网络上一点也不可怕。有几个非常好的设备可用来迁移PADL软件(见Resources)提供的、 你现有的用户和密码数据。

一块卓越的奶酪
推荐在专注的、卓越的服务器上运行OpenLDAP。在一个更小的、低要求的网络上你可以侥幸不使用共享服务器。在文档化的过程中,你可以看到许多对 slapd和slurpd的引用。Slapd是 LDAP daemon程序,而slurpd 则处理复制。

二、服务器配置和LDAP纪录的创建过程
 简单的方法
 从源代码安装
 配置slapd.conf
 类型/值对
 I B CN U

简单的方法
明智的系统管理员会先查看相关的文件;OpenLDAP 打包后可能会运行的很好(或者产生不可知的后果)。我只求方便——如果你的其他版本能够提供一个容易的方法,就用它好了。RPM 也可从rpmfind.net处获得,rpmfind.net详细地列出了所有需要的附带软件包。

当然Debian运行的也很好。apt-get做这个工作也不错;聪明的 bit能够找到软件包的名字。 Debian用户希望ldap-utils;slapd,即OpenLDAP;以及libdb4.1获得Sleepycat DB。这三个组件足够你用的了。apt-get可带你完成最小配置,并且自动启动slapd,即LDAP服务器 监控程序。

从源代码安装
  基本安装至少需要两个tarball:
  ·Berkeley Sleepycat DB
  ·OpenLDAP tarball
Berkeley DB必须在OpenLDAP之前安装。OpenLDAP没有它不能建立。(如何安装Berkeley DB请看Resources)
OpenLDAP tarball 不足2兆,那就是说即使我们拨号下载,也是很轻松的。本文中使用的稳定版为openldap-stable-20030709.tgz。我喜欢将它放在 /usr/src/目录下,并在此解包:
root@windbag:/usr/src# tar xfz openldap-stable.tgz
这就创建了openldap-2.1.22 目录:
root@windbag:/usr/src# cd openldap-2.1.22
现在就有了README、INSTALL、 LICENSE、 ANNOUNCEMENT、以及COPYRIGHT 文档。先花点时间看看这些文档,看他们里面有什么重要信息。要快速查看编译选项,请键入:
root@windbag:/usr/src# ./configure --help
这个阅读相当吸引人,它的默认项标记清楚,选项能够自我说明。现在我们来看看默认项。输入下列三个命令:
# ./configure
# make depend
# make
每个命令输入完都会出现许多东西;放心的等待吧。等他们都完成之后,运行简单的内建测试脚本对他们进行校验:
# make test
如果出错的话,我建议你放弃它,另外向你推荐OpenLDAP.org (见 Resources)。如果运行良好,最后一个步骤就是真正的安装新创建的二进制文件和man界面。在OpenLDAP根目录下运行:
# make install
请注意'make install'的输出;它包含许多有用信息。为了详细阅读,将它导入文件内:
# make install | tee openldap-install.txt

配置slapd.conf
这是用于我们新OpenLDAP 服务器的主要配置文件。它可以放在任何层数的虚拟目录内——我个人喜欢在安装软件后运行updatedb,这样我能迅速的找到需要的东西。在我的 Libranet 系统上,它是/etc/ldap/slapd.conf。

小心保护该文件。最好备份一下。原来的文件包含有用的默认值。为了安全起见,默认许可为600(只有root用户才能读写该文件)。
slapd.conf 定义了三种类型的信息:整体设置,与指定后端相关的设置,与指定数据库相关的设置。这个bit相当重要,如果运行正确的话能够帮你减少麻烦:后端和数据库 指令优先于整体设置,数据库指令优先于后端指令。

空白行和注释可以忽略。以空白开头的行是上一行的继续——这个小技巧可让你浏览时不至于毫无头绪。更多的空白可用于指令中:指令可以有参数,甚至多个参数。这些参数使用空白隔开。带有空白的参数必须附上双引号:如"loud argument." 包含双引号或者反斜线符号的参数退出时必须使用反斜线:如 "really "loud" argument," 。

毫无疑问,在这里简单的安装对于slapd.conf 中的配置是不够的,下列东西应该足够让这个球滚动起来。如果你的slapd.conf没有包括标题如"Global Directives"和"Backend Directives," 你可以添加它们。重要的是依次添加下列三个部分:整体、后端、以及数据库。
在Global Directives下,添加日志级别的指令:
loglevel 256
在Backend Directives下,添加bdb:
backend bdb
在Database Directives下,添加:
database bdb
suffix "dc=freeoa,dc=net"
rootdn "cn=Manager,dc=freeoa,dc=net"
rootpw secret
directory "/var/lib/ldap"
我相信你能够找到需要修改以适应系统的bit。注意:域freeoa.net已经分裂成两个类型/值对。这件事以后再做,以防万一值需要修改或者值需要出现在另一个目录下。

类型/值对
尽管LDAP 非常灵活,还是有某些类型和值已经定义了,如访问级、数据库后端、和调试级。这一点请参考基本的(和优秀的)"OpenLDAP 2.1 Administrator's Guide" (再次见 Resources)。

I B CN U
不错,我们现在要指出在哪里可以找到所有这些缩写的意思。说不定你还可以用它们在你的朋友面前炫一把:
DN =贵宾名
O = 组织
OU = 组织单元
DC = 域组件
CN = 普通名
SN = 姓名
UID =用户ID

希望看起来像天才吗?请看文件core.schema,它标识了所有这些缩写(有二三十个那么多)。

这是启动slapd的好时机。依靠你的安装,它已经在运行了——首先检查ps ax|grep slapd 。如果没有运行,键入which slapd ,找出执行文件,然后无参数运行。安装程序应该自动配置启动文件,在引导时就开始运行,这样你就不必重复了。OpenLDAP是完全自我测试的;运行 /slapd–t ,确认你的slapd.conf 没有语法错误。

三、用户认证和创建单一登录
在这部分,我们将组装数据库,描述如何使用LDAP来实现单一登录。
 它能运行吗?
 修改slapd.conf
 添加条目
 .ldif的缺陷
 添加用户
 模式
 结论

我们先回顾一下第二部分中我们的slapd.conf 配置:
##Database Directives##
database bdb
suffix "dc=freeoa,dc=net"
rootdn "cn=Manager,dc=freeoa,dc=net"
rootpw secret
directory "/var/lib/ldap"
我们来详细讨论配置中的每一行。
  ·首先,确定用你的真实域取代"freeoa.net" 。
  ·rootdn 非常重要。这是你创建授权用户输入条目到数据库的地方。这里我称之为管理员(Manager)。你可以随便称呼它:管理员、老板、ldap最高统治者——你想称呼它什么,就称呼什么。
  ·rootpw 也是非常重要的。它是授权用户的(管理员的) 密码。现在,我们要使用明文密码。在上述的例子中,它为"secret";但是密码你可以随意设定。
  ·directory 是OpenLDAP存储实际数据库文件的地方,它在下一行。目录在启动slapd 之前必须存在。"/var/lib/ldap" 是安装者创建的一个常用目录,尽管你的Linux版本可能已经将它放在其他地方了。你也可以创建一个你自己选择的目录。但是,我们的目的是要找到它,而不 是只创建目录——查看更多细节,请参考 OpenLDAP Administrator's Guide 。

目录下已经安装了下列文件:
$ ls /var/lib/ldap
__db.001 __db.003 __db.005 id2entry.bdb objectClass.bdb
__db.002 __db.004 dn2id.bdb log.0000000001
 它能运行吗?

首先,检查slapd.conf 有无语法错误:
# slapd -t
然后,运行下列命令(不要写错了):
$ ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
他会返回几行费解的代码;看这行:
dn:
namingContexts: dc=freeoa,dc=net

修改slapd.conf
只要你修改了slapd.conf,就必须重新启动:
# /etc/init.d/slapd restart

添加条目
现在我们进入有趣的部分。手动创建条目有两个步骤。首先,创建一个.ldif 文件,然后使用命令ldapadd ,输入新的条目到数据库中。在.ldif 文件中——我们统统称之为test.ldif ——定义了你公司的一些属性:
##my company##
dn: dc=freeoa,dc=net
objectclass: dcObject
objectclass: organization
o: Tuxcomputing, inc.
dc: freeoa
dn: cn=Manager,dc=freeoa,dc=net
objectclass: organizationalRole
cn: Manager
 .ldif的缺陷
请确定你已经去除了首尾空白,以及空白行。尽管行结尾的尾空白可以告诉ldapadd:下一行是前一行的继续,但是任何首空白或者尾空白都会让ldapadd 相信这里什么都没有。请使用空白行分隔条目。

下一步就是添加test.ldif 文件到ldap:
# ldapadd -x -D "cn=Manager,dc=freeoa,dc=net" -W -f test.ldif
想了解不同标记代表的含义请参考man ldapadd 。ldap 要求你输入LDAP密码,然后才批准添加条目。如果你不幸得到"ldap_bind: Invalid credentials (49)"错误,就表示你要么给出了错误的"cn="条目,要么给出了错误的密码。

只有普通名(cn)和密码在slapd.conf中都正确,才不会出现任何关于他们的任何莫名其妙的信息。 注意:我们稍候会删除这些。(虽然创建新数据库时需要他们,稍候我们添加更强的授权时就会替换它们。)我们看看现在我们的数据库看起来像什么:
# ldapsearch -x -b 'dc=freeoa,dc=net' '(objectclass=*)'
它会显示数据库中的每一条。

添加用户
好,现在让我们使用users.ldif 文件,添加一些真正的用户:
#Tux Entry
dn: cn=Tux P Tuxedo,dc=freeoa,dc=net
cn: Tux P Tuxedo
cn: Tux Tuxedo
objectClass: person
sn: Tuxedo
# ldapadd -x -D "cn=Manager,dc=freeoa,dc=net" -W -f users.ldif
Enter LDAP Password:
adding new entry "cn=Tux P Tuxedo,dc=freeoa,dc=net"
# ldapsearch -x -b 'dc=freeoa,dc=net' '(objectclass=*)'
# extended LDIF
#
# LDAPv3
# base with scope sub
# filter: (objectclass=*)
# requesting: ALL
#
# freeoa.net
dn: dc=freeoa,dc=net
objectClass: top
objectClass: dcObject
objectClass: organization
o: Tuxcomputing, Inc.
# Tux P Tuxedo, freeoa.net
dn: cn=Tux P Tuxedo,dc=freeoa,dc=net
cn: Tux P Tuxedo
cn: Tux Tuxedo
objectClass: person
sn: Tuxedo
太棒了!他真的有用,它真的有用!注意:原来的.ldif 文件内不能有条目,因为它必须只包含新条目。如果ldapadd 找到任何现有的条目,它就会停止,不推进更多的条目。

Debian 的差别
如果你使用apt-get安装OpenLDAP,,dpkg将自动配置它,安装root域、公司以及授权的ldap管理员和密码。你也可以在 slapd.conf中创建另外一个LDAP管理员/密码组,就像我们前面做过的一样,任意使用其中一个。

模式
我们容易混淆的主要地方是schema 和object classes。在slapd.conf中可以看到:
# Schema and objectClass definitions
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema

这些文件包含用在你LDAP记录中的属性。花点时间读读这些属性。我知道这是一个痛苦的练习,但是理解模式就是理解如何使用LDAP的关键。
现在是时候提到一个用于LDAP的GUI 前端GQ LDAP Client。他对于观察不同属性之间的关系大有帮助。优秀Web站点LDAPman Schema Reference 也是你观察时一个很有价值的工具。

结论
好,看起来好像我们还需要不止一篇LDAP文章。在part 4 中,我们将进行加密,认证真正的用户。我们将使用一些详细的配置范例来包装此文(和此系列)。

四、如何保护我们OpenLDAP服务器的安全
 密码散列
 加密
 生成TLS证书
 重写slapd.conf
 迁移用户数据
 结论
 Resources

密码散列
我们不想将rootpw 存储在服务器上的明文内,所以我们改用散列。有几种普遍使用的散列方法可通过slappasswd 命令来实现,包括SHA、SSHA、MD5、和CRYPT在内。CRYPT最差,不要用它。SSHA是默认方法,MD5也不错。使用slappasswd 可以生成一个很好的散列rootpw:
$ slappasswd
New password:
Re-enter new password:
{SSHA}Lr7P++EoH6GpIS4GZ36vkV4R422RuW7R
现在复制粘贴这个很好的新散列到/etc/ldap/slapd.conf内:
rootpw {SSHA}Lr7P++EoH6GpIS4GZ36vkV4R422RuW7R
这可以是一个永久设置,很适合用在小型的简单的LAN上。 更好的解决方案就是创建一个LDAP记录,该记录定义了LDAP管理员,还为LDAP管理员使用slapd.conf中的ACLs (access control lists)定义了访问权限。请看OpenLDAP管理员的指南中的重要章节chapter on ACLs ——它是我看到的关于ACLs的最好的指南。

加密
OpenLDAP 默认采用明文在网络上传送信息,包括密码和注册在内。加密可以防止中途截取和窃听。加密需要以下工具:
OpenSSL
Cyrus SASL

这些在你的系统上应该有。如果没有,不妨先骂它两句,然后访问你的安装盘或者你的版本的Web站点,找到他们。在Debian上,寻找 libssl和libsasl;在基于RPM的系统上,寻找openssl、 cyrus-sasl、和cyrus-sasl-md5。(如果你在这一点上偏执的话,那就去吧。 LDAP相当复杂,所以偏执也是一种可以接受的正常行为。)

生成TLS证书
首先我们必须生成一张服务器证书。这是一张自我生成的仅供slapd 使用的证书。如果你不需要安装“认证机构”认证其他证书,也不需要某种信任的第三组织认证机构,如Thawte,这个方法够用了。

在包含slapd.conf 的目录下运行下列命令。他将会产生一个新的X509 证书,不需要密码。他还将证书命名为slapd_cert.pem,密码命名为slapd_key.pem,并给与它一年的使用期限:
root@windbag:/etc/ldap/# openssl req -new -x509 -nodes -out slapd_cert.pem -keyout slapd_key.pem -days 365
Generating a 1024 bit RSA private key
...........++++++
...................++++++
writing new private key to 'slapd_key.pem'

然后它会向你提出一串问题。不要怕,一一回答他的问题好了。所有这两个文件都必须属于ldap 用户,该用户在Red Hat上称为'ldap.' (在Debian上叫做'root.')现在设定你的权限—— slapd_cert.pem 必须是全世界易懂的,slapd_key.pem 只有ldap 用户才可以读,不允许任何人写入。

重写slapd.conf
接下来我们需要告诉slapd 到哪里找到这些文件:
database bdb
# The base of your directory in database #1
suffix "dc=freeoa,dc=net"
rootdn "cn=Metest,dc=freeoa,dc=net"
rootpw {SSHA}Lr7P++EoH6GpIS4GZ36vkV4R422RuW7R
# Where the database file is physically stored for database #1
directory "/var/lib/ldap"
#Specify ciphers
TLSCipherSuite HIGH:MEDIUM:+SSLv2:+SSLv3
#TLS keyfile locations
/etc/ldap/slapd_cert.pem
/etc/ldap/slapd_key.pem
你知道哪种密码采用哪种方式命名吗?首先看看你的your OpenSSL支持什么:
$ openssl ciphers -v

他将会产生一个长长的、让人印象深刻的列表。上面例子中使用的术语是通配符。HIGH 表示使用密码长度超过128位(MEDIUM = 128 bits)的所有密码。我相信我们都不想使用LOW,它只有56和64位那么长。(参考 OpenSSL.org,以找到更多此类信息)
现在我们需要重新启动ldap监控程序。在Red Hat上,键入:
# /etc/init.d/ldap restart
在 Debian上键入:
# /etc/init.d/slapd restart

迁移用户数据
PADL软件还提供了几种可爱的脚本来减轻组装LDAP目录的琐事。他们抽取了你现有的用户数据,创建更好的LDAP目录条。请在他们的站点上寻找“迁移 工具”。然后,你需要编辑migrate_common.ph, 将你指定的网络设置包括进来。

使用/etc/services 或者/etc/protocols 可能会打乱LDAP服务器,产生异常,这是毫无意义的。对于Linux来说这些异常是相当静态的,普遍的;你不需要让LDAP为他们所用。我们从迁移 /etc/passwd 和 /etc/group开始。我建议备份/etc/passwd和 /etc/group,然后在副本(migrate_group.pl, migrate_passwd.pl)上先运行恰当的脚本。

他将会产生.ldif文件,检查该文件,确认他们是按你希望的方式完成。脚本使用起来轻而易举:
# migrate_passwd.pl /etc/passwd passwd.ldif
然后,采用平常的方式通过ldapadd添加.ldif文件到数据库内:
# ldapadd -x -D "cn=Manager,dc=freeoa,dc=net" -W -f passwd.ldif

结论
OpenLDAP是一个重要的程序。他也是非常复杂的。希望本系列能够帮助你获得最初的速度冲击,你现在已经有了可以运行的服务器,你可用它来进行测试或 者学习。在Resources中,我列出了我能找到的最有用的资源,他们可帮助你理解最难的LDAP组件:模式、ACLs,和加密。我还建议你寻找你的Linux版本中包括的有用文档,因为每个版本安装和配置OpenLDAP以及其他设备如TLS和SASL的方法大不相同。