域内LDAP学习
域内LDAP学习
LDAP基础
LDAP全称是Lightweight Directory Access Protocol,轻量目录访问协议。顾名思义,LDAP是设计用来访问目录数据库的一个协议。
目录服务数据库也是一种数据库,这种数据库相对于我们熟知的关系型数据库(比如MySQL,Oracle),主要有以下几个方面的特点。
它成树状结构组织数据,类似文件目录一样。
它是为查询、浏览和搜索而优化的数据库,也就是说LDAP的读性能特别强,但是写性能差,而且还不支持事务处理、回滚等复杂功能。
为了能够访问目录数据库,必须设计一台能够访问目录服务数据库的协议,LDAP是其中一种实现协议。
一些基本概念:
目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。比如图中的每个圆圈都是一条记录。
DN,RDN:比如说第一个叶子条目,他有一个唯一可区分的名称DN:uid=bob,ou=people,dc=acme,dc=org
。
有个DN之外,还有个RDN,他与目录结构无关,比如之前咱们提过的uid=bob,ou=people,dc=acme,dc=org
,他的RDN就是uid=bob。
微软的目录服务数据库就是Active Directory
如果我们想访问域内的Active Directory,有两种办法
1.域内的每一台域控都有一份完整的本域的Active Directory,可以通过连接域控的389/636端口(636端口是LDAPS)来进行连接查看修改。
2.如果用户知道某个对象处于哪个域,也知道对象的标识名,那么通过上面第一种方式搜索对象就非常容易。但是考虑到这种情况,不知道对象所处的域,我们不得不去域林中的每个域搜索。为了解决这个问题,微软提出全局编录服务器(GC,Global Catalog), 全局编录服务器中除了保存本域中所有对象的所有属性外,还保存林中其它域所有对象的部分属性,这样就允许用户通过全局编录信息搜索林中所有域中对象的信息。也就是说如果需要在整个林中进行搜索,而不单单是在具体的某个域进行搜索的时候,可以连接域控的3268/3269端口。
活动目录在域内是同步的,一般来说连接哪个dc都是一样的。
Naming Context
微软将Active Directory划分为若干个分区(这个分区我们称为Naming Context,简称NC),每个Naming Context都有其自己的安全边界。
Active Directory预定义了三个Naming Context
Configuration NC(Configuration NC)
配置NC,林配置信息的主要存储库,包含有关站点,服务,分区和Active DirectorySchema 的信息,并被复制到林中的每个域控制器。配置NC的根位于配置容器中,该容器是林根域的子容器。
RDN | 说明 |
---|---|
CN=DisplaySpecifiers | 定义了Active Directory管理单元的各种显示格式 |
CN=Extended-Rights | 扩展权限对象的容器 |
CN=ForestUpdates | 包含用于表示森林状态和与域功能级别更改的对象 |
CN=Partitions | 包含每个Naming Context,Application Partitions以及外部LDAP目录引用的对象 |
CN=Physical Locations | 包含位置对象,可以将其与其他对象关联 以表示该对象的位置。 |
CN=Services | 存储有关服务的配置信息,比如文件复制服务 |
CN=Sites | 包含所有站点拓扑和复制对象 |
CN=WellKnown Security Principals | 包含常用的外部安全性主题的对象,比如Anonymous,Authenticated Users,Everyone等等 |
LDAP中的类和继承
域内每个条目都是类的实例。而类是一组属性的集合。
假如以下面这个dc为例CN=WIN-LOU=Domain Controllers,DC=xxx,DC=xxx
,这个dc就是Active Directory里的一个条目
同时也是Computer
类的实例,其中包含了多个属性,而在它的objectClass
属性中可以看到他是哪个类的实例(最后一个,上面都是他的父类)
由此也可以看出类是可继承的。子类继承父类的所有属性,Top类是所有类的父类。在objectClass
属性中保存了类继承关系。
而在Windows Server 2008之前默认不对objectClass 属性进行索引。
对象类的每个实例还具有一个objectCategory属性,该属性是一个单值属性。并且建立了索引。其中包含对象是其实例的类或其父类之一的专有名称.
创建对象时,系统会将其objectCategory属性设置为由其对象类的defaultObjectCategory
属性指定的值。无法更改对象的objectCategory属性。如果在目录中已经索引了ObjectClass ,或者所有域控制器都在运行Windows Server 2008或更高版本,则可以随意使用 objectClass。
adfind:
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(objectCategory="CN=Person,CN=Schema,CN=Configuration,DC=test,DC=com")"
类有三种类型
-
结构类(Structural)
结构类规定了对象实例的基本属性,每个条目属于且仅属于一个结构型对象类。前面说过域内每个条目都是类的实例,这个类必须是结构类。只有结构类才有实例。比如说前面说过的Computer类。
-
抽象类(Abstract)
抽象类型是结构类或其他抽象类的父类,它将对象属性中公共的部分组织在一起。跟面对对象里面的抽象方法一样,他没有实例,只能充当结构类或者抽象类的父类。比如说top 类。注意抽象类只能从另一个抽象类继承。
-
辅助类(Auxiliary)
辅助类型规定了对象实体的扩展属性。虽然每个条目只属于一个结构型对象类,但可以同时属于多个辅助型对象类。注意辅助类不能从结构类继承
Schema NC(Schema NC)
包含Schema 信息,该Schema 信息定义Active Directory中使用的类,对象和属性。与域NC和配置 NC 不同,模式 NC 不维护容器或组织单位的层次结构。相反,它是具有 classSchema ,attributeSchema 和 subSchema 对象的单个容器。
Domain NC(DomainName NC)
域内重点关注的信息就在这个NamingContext里面
每个域都有一个域Naming Context,不同的域内有不同的域Naming Context,其中包含特定于域的数据。这个域Naming Context(的根由域的专有名称(DN)表示,比如corp.test.local
域的DN将为dc=corp,dc=test,dc=local
。之前我们说过,域内的所有计算机,所有用户的具体信息都存在Active Directory底下,具体来说,就是在Active Directory的这个Naming Context里面。
RDN | 说明 |
---|---|
CN=Builtin | 内置本地安全组的容器,包括管理员,域用户和账号操作员等等 |
CN=Computers | 机器用户的容器,包括加入域的所有机器 |
OU=Domain Controllers | 域控制器的容器,包括域内所有域控 |
CN=ForeignSecurityPrincipals | 代表域中来自森林外部域的组中的成员 |
CN=Keys | Server 2016之后才有,关键凭证对象的默认容器 |
CN=Managed Service Accounts | 托管服务帐户的容器。 |
CN=System | 各种预配置对象的容器。包括信任对象,DNS对象和组策略对象 |
CN=TPM Devices | 可信平台模块(TPM)密钥的恢复信息的容器。 |
CN=Users | 用户和组对象的默认容器 |
搜索Active Directory
通过查询目录,可以直接收集到要求的数据。查询目录需要指定两个要素
BaseDN 过滤规则
BaseDN
BaseDN指定了这棵树的根。
比如指定BaseDN为DC=test.DC=local
就是以DC=test.DC=local
为根往下搜索
BaseDN为CN=Users,DC=test.DC=local
就是以CN=Users,DC=test.DC=local
为根往下搜索
过滤规则
LDAP 搜索过滤器语法有以下子集:
- 用与号 (&) 表示的 AND 运算符。
- 用竖线 (|) 表示的 OR 运算符。
- 用感叹号 (!) 表示的 NOT 运算符。
- 用名称和值表达式的等号 (=) 表示的相等比较。
- 用名称和值表达式中值的开头或结尾处的星号 (*) 表示的通配符。
下面举几个例子
-
(uid=testuser)
匹配 uid 属性为testuser的所有对象
-
(uid=test*)
匹配 uid 属性以test开头的所有对象
-
(!(uid=test*))
匹配 uid 属性不以test开头的所有对象
-
(&(department=1234)(city=Paris))
匹配 department 属性为1234且city属性为Paris的所有对象
-
(|(department=1234)(department=56*))
匹配 department 属性的值刚好为1234或者以56开头的所有对象。
一个需要注意的点就是运算符是放在前面的,跟我们之前常规思维的放在中间不一样
关于查询目录还有一些高级点的用法,比如 LDAP 控件,位掩码等。
组
在域内,我们无时无刻不在跟组打交道,比如我们熟悉的域管,就是一个组。按照用途来分,组分为通讯组和安全组。对于通讯组,我们接触的比较多的就是邮件组,将若干个人划分到一个通讯组,给这个通讯组发件,那组内用户都能收到。
安全组是权限的集合
举个例子,运维需要对公司的网络进行管理,需要一些特殊的管理权限,我们就可以设置个组,对组配置权限。然后将运维拉近组里面,组里面的运维就拥有了该权限。安全组可以根据作用范围划分为
-
全局组 (Global group)
-
通用组(Universal group)
-
域本地组(Domain Local group)
所有的组都是group
类的实例,
我们可以用(objectClass=group)
或者(objectCategory=group)
来过滤组。
查询所有组
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(objectCategory=group)"
查询所有全局组
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(&(objectcategory=group)(grouptype:AND:=2))" -dn
查询域内所有通用组
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(&(objectcategory=group)(grouptype:AND:=8))" -dn
查询域内的所有安全组,(包括全局组,通用组,域本地组)
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(&(objectcategory=group)(grouptype:AND:=2147483648))" -dn
查询域内的所有通讯组(包括全局组,通用组,域本地组)
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(&(objectcategory=group)(!(grouptype:AND:=214748648)))" -dn
查询域内系统创建的群组
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(&(objectcategory=group)(grouptype:AND:=1))" -dn
组范围
组类型 | 可以授予权限 | 可包含 | 可包含于 | 成员是否在全局编录复制 |
---|---|---|---|---|
全局组 | 在同一林中或信任域或林中的任何域上。 | 来自同一域的帐户。 来自同一域的其他全局组 | 来自同一林中任何域的通用组。 来自同一域的其他全局组。 来自同一林中任何域或任何信任域的域本地组。 | 无 |
通用组 | 在同一林或信任林中的任何域上。 | 来自同一林中任何域的帐户。 来自同一林中任何域的全局组。 来自同一林中任何域的其他通用组。 | 同一林中的其他通用组。 在同一个林或信任林中域本地组。 | 是 |
域本地组 | 在同一个域中 | 来自任何域或任何受信任域的帐户。 来自任何域或任何受信任域的全局组。 来自同一林中任何域的通用组。 来自同一域的其他域本地组。 | 来自同一域的其他域本地组 | 无 |
- 域本地组(Domain Local group)
顾名思义,就是本域内的本地组。不适用于林,适用于本域。可包含林内的账户,通用组,全局组。其他域内的通用组要在本域拥有权限,一般都是加入这个域的域本地组。比如说一个林里面,只有林根域有Enterprise Admins
这个组,这是个通用组。然后其他子域 的域本地组Administrators
会把林根域的Enterprise Admins
加进里面,所以林根域的Enterprise Admins
组用户才在整个林内具备管理员权限。如果想要一个只允许访问同一个域中的资源的组,那么使用域本地组即可。
- 通用组(Universal group)
上面已经简单提过了通用组,典型例子是Enterprise Admins
这个组。在林的场景下比较有用。组内成员会在GC内复制。如果你想要一个可以访问林中任何东西的组,并且可以在林中包含任何账户,请使用通用组。
- 全局组 (Global group)
全局组比较复杂,前面说了。在单域内用域本地组,在林中使用通用组。全局组应该说是一种比较折中的方案,他可以在林中使用,但是只能包含本域内的账户。全局组的使用范围是本域以及受信任关系的其他域。最为常见的全局组是Domain Admin,也就是我们常说的域管。因为全局组只能包含本域内账户,因此来自一个域的账户不能嵌套在另一个域中的全局组中,这就是为什么来自同一个域的用户不符合在外部域中的域管的成员资格(由于其全局范围的影响)。
常见组:
- Administrators
域本地组。具备系统管理员的权限,拥有对整个域最大的控制权,可以执行整个域的管理任务。Administrators包括Domain Admins
和Enterprise Admins
。
- Domain Admins
全局组。我们常说的域管组。默认情况下,域内所有机器会把Domain Admins加入到本地管理员组里面。
- Enterprise Admins
通用组。在林中,只有林根域才有这个组,林中其他域没有这个组,但是其他域默认会把这个组加入到本域的Administrators里面去。
- Domain Users
全局组。包括域中所有用户帐户,在域中创建用户帐户后,该帐户将自动添加到该组中。默认情况下,域内所有机器会把Domain Users加入到本地用户组里面,也就是为什么默认情况底下,啥都不配置。域用户可以登录域内任何一台普通成员机器。
组织单位 OU
组织单位(Organization Unit),简称OU,是一个容器对象,将域中的对象组织成逻辑组,帮助网络管理员简化管理组。组织单位包含下列类型的对象:用户,计算机,工作组,打印机,安全策略,其他组织单位等。可以在组织单位基础上部署组策略,统一管理组织单位中的域对象。 在企业域环境里面,我们经常看到按照部分划分的一个个OU。
ou与容器的区别:
组织单位(OU)是专用容器,与常规容器的区别在于管理员可以将组策略应用于OU,然后系统将其下推到OU中的所有计算机。您不能将组策略应用于容器。需要注意的是Domain Computers
是一个普通容器,而Domain Controllers
是一个OU,因此可以可以将组策略应该于Domain Controllers
,不可以将组策略应用于Domain Computers
。
ou与组的区别:
组织单位跟组是两个完全不同的概念。很多人经常会把这两个弄混。组是权限的集合。OU是管理对象的集合。举个前面举过的例子,运维需要对公司的网络进行管理,需要一些特殊的管理权限,我们就可以设置个组,对组配置权限。然后将运维拉近组里面,组里面的运维就拥有了该权限。比如我们需要对财务部里面的用户进行统一管理,那我们可以设置个OU,然后把财务部的用户拉近这个OU,这样就可以进行集中管理,比如说下发组策略。说通俗点,组是管理的集合,OU是被管理的集合。
ou委派:
考虑这样一种需求,如果我们想允许某个用户把其他用户拉近OU,而不赋予这个用户域管权限,我们可以在这个OU给这个用户委派 添加成员的权限。组织单位的委派其实就是赋予某个域内用户对OU的某些管理权限。这些权限体现在ACL里面。
查询ou:
adfind.exe -b "DC=test,DC=com" -s subtree -bit -f "(objectclass=OrganizationalUnit)" -dn
查询ou中的账户,直接指定baseDN即可
adfind.exe -b "OU=Admins,DC=test,DC=com" -s subtree -bit -dn