LDAP服务原理详解(原创)

Directory Services(目录服务)

我们知道,当局域网的规模变的越来越大时,为了方便主机管理,我们使用DHCP来实现IP地址、以太网地址、主机名和拓扑结构等的集中管理和统一分配。同样,如果一个局域网内有许多的其它资源时,如打印机、共享文件夹等等,为了方便的定位及查找它们,一种集中定位管理的方式或许是较好的选择,DNS和NIS都是用来实现类似管理的方法。

对于局域网内的一个用户来讲,工作等其它应用需要,我们必须凭帐号登录主机、用帐号收发E-mail,甚至为了管理需要公司还需要维护一个电子号码簿来存储员工的姓名、地址、电话号码等信息。随着时间的增长,我们会为这些越来越多的帐号和密码弄的头晕脑胀。同时,如果一个员工离开,管理员就不得不翻遍所有的记录帐号信息的文件把离职员工的信息删除。这些将是一个繁琐而效率低下的工作。那么,如果能将此些帐号信息等统一到一个文件中进行管理,无疑会大大提高员工及管理员的工作效率。目录服务(LDAP是其实现的一种)正是基于这些应用实现的。

LDAP

LDAP是Lightweight Directory Access Protocol的缩写,顾名思义,它是指轻量级目录访问协议(这个主要是相对另一目录访问协议X.500而言的;LDAP略去了x.500中许多不太常用的功能,且以TCP/IP协议为基础)。目录服务和数据库很类似,但又有着很大的不同之处。数据库设计为方便读写,但目录服务专门进行了读优化的设计,因此不太适合于经常有写操作的数据存储。同时,LDAP只是一个协议,它没有涉及到如何存储这些信息,因此还需要一个后端数据库组件来实现。这些后端可以 是bdb(BerkeleyDB)、ldbm、shell和passwd等。

LDAP目录以树状的层次结构来存储数据(这很类同于DNS),最顶层即根部称作“基准DN”,形如"dc=mydomain,dc=org"或者"o= mydomain.org",前一种方式更为灵活也是Windows AD中使用的方式。在根目录的下面有很多的文件和目录,为了把这些大量的数据从逻辑上分开,LDAP像其它的目录服务协议一样使用OU (Organization Unit),可以用来表示公司内部机构,如部门等,也可以用来表示设备、人员等。同时OU还可以有子OU,用来表示更为细致的分类。

LDAP中每一条记录都有一个唯一的区别于其它记录的名字DN(Distinguished Name),其处在“叶子”位置的部分称作RDN;如dn:cn=tom,ou=animals,dc=mydomain,dc=org中tom即为 RDN;RDN在一个OU中必须是唯一的。

因为LDAP数据是“树”状的,而且这棵树是可以无限延伸的,假设你要树上的一个苹果(一条记录),你怎么告诉园丁它的位置呢?当然首先要说明是哪一棵树(dc,相当于MYSQL的DB),然后是从树根到那个苹果所经过的所有“分叉”(ou,呵呵MYSQL里面好象没有这 DD),最后就是这个苹果的名字(uid,记得我们设计MYSQL或其它数据库表时,通常为了方便管理而加上一个‘id’字段吗?)。好了!这时我们可以清晰的指明这个苹果的位置了,就是那棵“歪脖树”的东边那个分叉上的靠西边那个分叉的再靠北边的分叉上的半红半绿的……,晕了!你直接爬上去吧!我还是说说LDAP里要怎么定义一个字段的位置吧,树(dc=waibo,dc=com),分叉(ou=bei,ou=xi,ou= dong),苹果(cn=honglv),好了!位置出来了:
  dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=waibo,dc=com
LDAP的 可扩展性和灵活性

LDAP 协议既是跨平台的也是基于标准的。这意味着几乎在任何计算机平台上运行的任何应用程序都可以从LDAP目录获取信息。另外,无论什么服务器操作系统、文件系统或平台对于客户机都是无关紧要的。

LDAP目录几乎可以存储所有类型的数据:电子邮件地址、DNS 信息、NIS 映射、安全性密钥、联系人信息列表和计算机名等。如果需要专门的组织单元或项,则可以根据具体实现来定制控制给定字段可以保存哪种信息的规则(称为模式,稍后将详细讨论)。

大多数 LDAP 服务器的安装和配置相对比较简单,并且可以在很少或没有维护的情况下运行多年,而且很容易为特定类型的访问而进行最优化。

可以容易地配置 LDAP 目录来复制部分或所有目录树(使用推(push)或拉(pull)方法)。这可以使系统管理员不必担心出现单点故障的情况。

可以通过 ACL(访问控制表,Access Control List)来控制对目录的访问。例如,管理员可以根据给定组或位置中的成员资格来限制谁可以看到哪些内容,或者给予特殊用户在其自己记录中修改所选字段的能力。ACL 提供极其细粒度的访问控制,而且 ACL 将这种控制与 LDAP 安装结合在一起,而不是与请求信息的客户机结合在一起。此外,可以容易地将 LDAP 与大多数现有的安全性层和/或认证系统(例如 SSL、Kerberos 和 PAM 等)集成在一起。

LDIF

LDIF(LDAP Interchange Format)是指存储LDAP配置信息及目录内容的标准文本文件格式,之所以使用文本文件来格式来存储这些信息是为了方便读取和修改,这也是其它大多数 服务配置文件所采取的格式。LDIF文件常用来向目录导入或更改记录信息,这些信息需要按照LDAP中schema的格式进行组织,并会接受schema 的检查,如果不符合其要求的格式将会出现报错信息。LDIF文件样例如下:

dn:cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org

objectClass:organizationalPerson

cn:stan

cn:czm

sn:czm

其中,以“#”号开头的为注释行;第二行起的行中,冒号左边为属性,右边是属性的值,这类同于编程中的变量及为其所赋的值,但属性可以被重复赋值。
注意:同一个属性可以有一个或者多个值,ldap在寻址时,可以根据同一个属性的不同值进行寻址,例如上例中可以根据cn属性的stan和czm进行寻址,这样速度更快。

objectClass

对象类由 LDAP 目录使用来定义给定类型的对象可以有哪些属性。对象类还定义项必须有什么属性,以及项可以有什么属性。所有对象类都从其父对象类继承需求,然后添加它们自己的需求。

对象类有五个组件:OID(对象标识)、唯一名称、父对象(SUP)、任何需要的属性(MUST)和允许的属性列表(MAY)。OID是由LDAP目录的内部数据库机制使用的数据标识符。从概念上讲,它们与IP地址相似,因为每个对象类都必须有一个唯一数字。并且象DNS和IP之间的关系那样,由创建它们的个人进行注册,并由这些人“拥有”。

在LDAP中objectClass分为三种:Abstract,Structural,AUXIALIARY。要定义一个Entry必须包含一个Structural类型的ObjectClass,

其他两个类型可包括0或多个。其中Top是一个顶级ObjectClass,里面定义了一个MUST Attribute:ObjectClass,于是也就决定了必须有

一个其它的Structural ObjectClass才能定义一个Entry.其中ObjectClass又可以存在继承关系,子ObjectClass会继承父ObjectClass中的

全部Attribute.该继承关系于Java中有点相似.

在LDAP中每一个ObjectClass都定义了一些Attribute,其Attribute仍然可以是ObjectClass。在这些Attriubte中分为两种类型MUST,MAY, MUST表示这个Entry必须包括的属性,MAY为可选。一个ObjectClass的Attribute也包括所有继承自父ObjectClass和自身定义的ObjectClass。

下面用一个类型进行说明:

objectclass ( 2.5.6.0 NAME 'top' ABSTRACT

MUST objectClass )

objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'

DESC 'RFC2247: domain component object'

SUP top AUXILIARY

MUST dc )

上面是两个objectclass的定义,其中top为ABSTRACT,dcObject为AUXILIARY,这两个类型都不能定义Entry.

下面这个LDIF文件在导入到LDAP时会出错:

dn: dc=java,dc=com

objectClass:dcObject

dc: java.com

要定义这个Entry必须找到一个STRUCTURAL类型的ObjectClass。

objectClasses: ( 2.5.6.4 NAME 'organization'

DESC 'RFC2256: an organization' SUP top STRUCTURAL

MUST o

MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory

$ x121Address $ registeredAddress $ destinationIndicator

$ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier

$ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber

$ street $ postOfficeBox $ postalCode $ postalAddress

$ physicalDeliveryOfficeName $ st $ l $ description ) )

这个objectClass的类型为STRUCTURAL,因此可以用来定义Entry.具体定义如下

dn: dc=java,dc=com

objectClass:dcObject

objectClass:organization

dc: java.com

o: java.com

Attribute

Attribute类同于编程语言中的变量,它可以被赋值,就像是可以存放一个单一类型信息的容器。官方声明了许多常用的 Attribute,如果其中没有你所需要的,你可以自己定义,但要避免重名。objectClass是一种特殊的Attribute,它包含其它用到的 Attribute以及它自身。常见的Attribute如下:

schema

LDAP中,schema用来指定一个目录中所包含的objects的类型 (objectClass)以及每一个objectClass中的各个必备(mandatory)和可选(optional)的属性 (attribute)。因此,Schema是一个数据模型,它被用来决定数据怎样被存储,被跟踪的数据的是什么类型,存储在不同的Entry下的数据之间的关系。schema 需要在主配置文件slapd.conf中指定,以用来决定本目录中使用到的objectClass。管理员可以自己设计制定schema,一般包括属性定 义(AttributeDefinition)、类定义(ClassDefinition)以及语法定义(SyntaxDefinition)等部分。

LDAP V3中在x.500标准的基础上定义了一个包含了网络中大多常见对象的schema,这些对象包括国家、所在地、组织、人员、小组以及设备等。同时,LDAP V3中可以很方便的从目录中提取出schema,它正是一条记录中关于属性的声明部分。

对象标识符

对象标识符( Object Identifiers)是被LDAP内部数据库引用的数字标识。Attribute的名字是设计为方便人们读取的,但为了方便计算机的处理,通常使用一组数字来标识这些对象,这类同于SNMP中的MIB2。例如,当计算机接收到dc这个Attribute时,它会将这个名字转换为对应的OID: 1.3.6.1.4.1.1466.115.121.1.26。

几点体会

重大误解

很多所谓基于LDAP实现的认证都是使用目录来存储加密(多数是MD5)后的密码而已.但是这种密码很好被暴力破解.于是你的系统的安全状态有退回到未 shadow过的/etc/passwd时代.在介绍目录服务的书籍中提到/etc/passwd也算是一种目录.我们不能说一个文本文件是用来做认证的吧?

很多LDAP的实现和应用都不使用LDAP来作验证.如微软的活动目录.还有斯坦福大学的目录都使用了kerberos.配置好的Windows域控制器本身就是一个Kerberos KDC.而斯坦福的目录也采用了Hedimal的Kerberos实现来做KDC和一个Windows 的KDC.这样的理由很明显的.如果要通过过LDAP目录来实现一个十分安全的认证信息的存储要借助大量的外围协议.还不如直接使用这些协议本身.长话短说,我们应该让目录存储它改存储的东西.

产品选择

产品的选择取决于你部署目录服务的目的以及内容.如果活动目录提供给你的那些的功能足够你的需要.那么采用活动目录好了.因为他一开始就将安全实现的很好(操作系统安全不在讨论之列).而且配置简单.而且和客户端(windows)兼容的较好.

如果你想在深入研究LDAP协议.或者要实现一个高度自定义的目录.那么选择OpenLDAP吧!

安全措施.

尽量少将安全敏感的信息存储在目录中.如果非存不可.一定要编辑ACL严格的控制访问权限如userPassword等.多数情况下目录服务还要主要是给其他的服务提供数据存储.这样的话应该让每个服务器绑定到不通的DN,同时在ACL中赋予他们较高的权限.而不能让所有的服务都使用rootdn来绑定.

目录结构的设计

虽然目录结构的设计可以比较灵活.但比较有经验的设计可以使你的目录结构更加合理,而且可以给你带来意想不到的好处.尽量参照前人实现的产品一吸收好的思想.分析微软的设计,在目录中建立分组的目录树是明智的做法.这样每个帐户的memberof属性的值他所属的组的DN,这样就可以方便的将基于组的访问控制列表也实现在目录结构中.相象如果活动目录中用户的memberof属性是"Aministrators"而不是"CN= Administrators,CN=Builtin,DC=example,DC=edu,DC=cn"的话会给微软带来多少麻烦?尽量的将更多的数据以树的形式组织,同时在字段中使用更多的DN代替单一的数值,可以最大限度的发挥目录服务的潜力.
AD和LDAP的关系

Active Directory应该是LDAP的一个应用实例,而不应该是LDAP本身。比如:windows域控的用户、权限管理应该是微软公司使用LDAP存储了一些数据来解决域控这个具体问题,

只是AD顺便还提供了用户接口,也可以利用Active Directory当做LDAP服务器存放一些自己的东西而已。比如LDAP是关系型数据库,微软自己在库中建立了几个表,每个表都定义好了字段。显然这些表和字段都是根据微软自己的需求定制的,而不是LDAP协议的规定。然后微软将LDAP做了一些封装接口,用户可以利用这些接口写程序操作LDAP,使得Active Directory也成了一个LDAP服务器。

总之:Active Directory = LDAP服务器+LDAP应用(Windows域控)。Active Directory先实现一个LDAP服务器,然后自己先用这个LDAP服务器实现了自己的一个具体应用(域控)

参考至:http://doc.linuxpk.com/2293.html
​​​ http://doc.linuxpk.com/2583.html​​​ http://doc.linuxpk.com/2586.html
http://doc.linuxpk.com/28400.html
http://bbs.chinaunix.net/thread-889055-1-1.html
http://hi.baidu.com/dongyuejiang/item/d2af278125f05d5d26ebd9a0
http://linux.chinaitlab.com/special/ldap/Index.html
本文原创,转载请注明出处
如有错误,欢迎指正