Linux LDAP 集成
大约 9 分钟约 2616 字
Linux LDAP 集成
简介
LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)用于集中管理用户认证和授权。在 Linux 环境中集成 LDAP(如 OpenLDAP 或 Active Directory),可以实现统一账户管理和单点登录,避免在每台服务器上重复创建和维护用户账号。
LDAP 的核心思想是将用户、组、权限等信息存储在一个集中的目录树(DIT,Directory Information Tree)中,所有服务器通过 LDAP 协议查询这个目录来验证用户身份。当员工入职或离职时,只需在 LDAP 中添加或删除一个条目,所有服务器的访问权限就会自动更新。
LDAP 目录树结构
dc=example,dc=com (根节点,代表域名 example.com)
├── ou=People (人员组织单元)
│ ├── uid=zhangsan (用户条目)
│ ├── uid=lisi
│ └── uid=wangwu
├── ou=Group (组组织单元)
│ ├── cn=linux-admins (组条目)
│ ├── cn=developers
│ └── cn=readonly
├── ou=Services (服务账户)
│ ├── cn=nginx-ldap
│ └── cn=app-ldap
└── ou=Policies (策略)
└── cn=password-policyLDAP 与传统认证的对比
传统方式:
每台服务器独立管理用户
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Server A │ │ Server B │ │ Server C │
│ user1 │ │ user1 │ │ user1 │ ← 重复创建
│ user2 │ │ user2 │ │ user2 │
└──────────┘ └──────────┘ └──────────┘
LDAP 方式:
集中管理,所有服务器查询同一个目录
┌──────────┐
│ LDAP │
│ user1 │
│ user2 │
└──────────┘
↑ ↑ ↑
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Server A │ │ Server B │ │ Server C │
└──────────┘ └──────────┘ └──────────┘特点
实现
OpenLDAP 服务端安装与配置
# 安装 OpenLDAP
yum install -y openldap-servers openldap-clients
# 初始化配置
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown ldap:ldap /var/lib/ldap/DB_CONFIG
# 启动并设置开机自启
systemctl enable --now slapd
# 验证服务运行
systemctl status slapd
netstat -tlnp | grep 389 # 默认 LDAP 端口
netstat -tlnp | grep 636 # LDAPS(加密)端口
# 查看当前 LDAP 目录内容
ldapsearch -x -H ldap://localhost -b "dc=example,dc=com"# 设置管理员密码
# 生成密码哈希
SLAPPWD=$(slappasswd -s "YourStrongPassword")
echo "管理员密码哈希: ${SLAPPWD}"
# 修改管理员密码(通过 ldapmodify)
ldapmodify -Y external -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: ${SLAPPWD}
EOF# 创建基础目录结构(DIT)
ldapadd -x -D "cn=admin,dc=example,dc=com" -W <<EOF
# 根节点
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Corp
# People 组织单元
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
# Group 组织单元
dn: ou=Group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group
# Services 组织单元
dn: ou=Services,dc=example,dc=com
objectClass: organizationalUnit
ou: Services
EOF# 创建组和用户
# 先创建组
ldapadd -x -D "cn=admin,dc=example,dc=com" -W <<EOF
dn: cn=linux-admins,ou=Group,dc=example,dc=com
objectClass: posixGroup
cn: linux-admins
gidNumber: 10001
dn: cn=developers,ou=Group,dc=example,dc=com
objectClass: posixGroup
cn: developers
gidNumber: 10002
dn: cn=readonly,ou=Group,dc=example,dc=com
objectClass: posixGroup
cn: readonly
gidNumber: 10003
EOF
# 创建用户
ldapadd -x -D "cn=admin,dc=example,dc=com" -W <<EOF
dn: uid=zhangsan,ou=People,dc=example,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: shadowAccount
uid: zhangsan
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/zhangsan
loginShell: /bin/bash
userPassword: {SSHA}hashed_password_here
sn: Zhang
cn: Zhang San
mail: zhangsan@example.com
dn: uid=lisi,ou=People,dc=example,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: shadowAccount
uid: lisi
uidNumber: 10002
gidNumber: 10002
homeDirectory: /home/lisi
loginShell: /bin/bash
userPassword: {SSHA}hashed_password_here
sn: Li
cn: Li Si
mail: lisi@example.com
EOF
# 生成用户密码
slappasswd -s "UserPassword123"
# 将输出的 {SSHA}xxx 替换到上面的 userPassword 字段# 将用户添加到组
ldapmodify -x -D "cn=admin,dc=example,dc=com" -W <<EOF
dn: cn=linux-admins,ou=Group,dc=example,dc=com
changetype: modify
add: memberUid
memberUid: zhangsan
EOF
# 查询用户
ldapsearch -x -H ldap://localhost \
-b "ou=People,dc=example,dc=com" \
"(uid=zhangsan)"
# 查询组成员
ldapsearch -x -H ldap://localhost \
-b "ou=Group,dc=example,dc=com" \
"(cn=linux-admins)"
# 修改用户密码
ldappasswd -x -H ldap://localhost \
-D "cn=admin,dc=example,dc=com" -W \
-S uid=zhangsan,ou=People,dc=example,dc=com
# 删除用户
ldapdelete -x -D "cn=admin,dc=example,dc=com" -W \
"uid=zhangsan,ou=People,dc=example,dc=com"Linux 客户端集成(SSSD)
SSSD(System Security Services Daemon)是现代 Linux 推荐的 LDAP 客户端方案,它提供了身份认证、授权和缓存功能。
# 安装 SSSD
yum install -y sssd sssd-ldap oddjob-mkhomedir
# 配置 /etc/sssd/sssd.conf
cat > /etc/sssd/sssd.conf <<'EOF'
[sssd]
config_file_version = 2
services = nss, pam, ssh
domains = example.com
debug_level = 3
[domain/example.com]
# LDAP 服务器配置
id_provider = ldap
auth_provider = ldap
ldap_uri = ldap://ldap.example.com
ldap_search_base = dc=example,dc=com
ldap_user_search_base = ou=People,dc=example,dc=com
ldap_group_search_base = ou=Group,dc=example,dc=com
# TLS 加密(生产环境必须)
ldap_id_use_start_tls = true
ldap_tls_cacert = /etc/openldap/cacerts/ca.crt
ldap_tls_reqcert = demand
# 缓存配置
cache_credentials = true
enumerate = false # 不枚举所有用户(提升性能)
entry_cache_timeout = 5400 # 缓存超时(秒)
offline_credentials_expiration = 604800 # 离线凭据过期(7天)
# 密码策略
ldap_pwd_policy = shadow
chpass_provider = ldap
# 访问控制(可选)
access_provider = simple
simple_allow_groups = linux-admins, developers
EOF
# 设置正确的文件权限(SSSD 要求严格)
chmod 600 /etc/sssd/sssd.conf
chown root:root /etc/sssd/sssd.conf
# 启动 SSSD
systemctl enable --now sssd
systemctl status sssd
# 配置 NSS(Name Service Switch)
# 确认 /etc/nsswitch.conf 包含 sss
cat /etc/nsswitch.conf | grep -E "passwd|group|shadow"
# passwd: files sss
# group: files sss
# shadow: files sss
# 配置 PAM
authconfig --enablesssd --enablesssdauth --update
# 自动创建家目录
authconfig --enablemkhomedir --update
# 或者使用 pam_mkhomedir.so
echo "session required pam_mkhomedir.so skel=/etc/skel/ umask=0022" >> /etc/pam.d/system-auth
# 测试
id zhangsan
getent passwd zhangsan
getent group linux-admins
su - zhangsanActive Directory 集成
使用 realmd 工具可以让 Linux 服务器快速加入 Windows Active Directory 域。
# 安装 realmd 和相关依赖
yum install -y realmd sssd oddjob-mkhomedir adcli sssd-ad
# 安装 Kerberos 客户端
yum install -y krb5-workstation
# 配置 DNS(AD 域名必须可解析)
echo "nameserver 192.168.1.10" >> /etc/resolv.conf
echo "search example.com" >> /etc/resolv.conf
# 测试 DNS 解析
dig _ldap._tcp.example.com SRV
# 发现 AD 域
realm discover example.com
# 输出示例:
# example.com
# type: kerberos
# realm-name: EXAMPLE.COM
# domain-name: example.com
# configured: no
# server-software: active-directory
# client-software: sssd
# required-package: oddjob-mkhomedir
# required-package: sssd
# required-package: adcli
# required-package: samba-common-tools
# 加入域(需要域管理员凭据)
realm join --user=admin example.com
# 输入管理员密码
# 验证加入成功
realm list
id zhangsan@example.com
id administrator@example.com
# 配置 SSH 仅允许特定组登录
# 方法 1:通过 SSSD 访问控制
# /etc/sssd/sssd.conf 添加:
# access_provider = simple
# simple_allow_groups = linux-admins@EXAMPLE.COM
# 然后重启 SSSD
systemctl restart sssd
# 方法 2:通过 sshd_config
echo "AllowGroups linux-admins" >> /etc/ssh/sshd_config
systemctl restart sshd
# 方法 3:通过 PAM 访问控制
echo "account required pam_access.so" >> /etc/pam.d/sshd
echo "+ : (linux-admins) : ALL" >> /etc/security/access.conf
# 离开域
realm leave example.com
realm leave --user=admin example.comLDAP 查询与过滤
# LDAP 过滤器语法
# (attribute=value) 等于
# (attribute>=value) 大于等于
# (attribute<=value) 小于等于
# (attribute=*value*) 包含
# (!(attribute=value)) 不等于
# (&(cond1)(cond2)) AND
# (|(cond1)(cond2)) OR
# (cn=*) 所有有 cn 属性的条目
# 常用查询示例
# 查找所有用户
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=People,dc=example,dc=com" \
"(objectClass=posixAccount)"
# 查找特定用户
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=People,dc=example,dc=com" \
"(uid=zhangsan)"
# 查找属于特定组的用户
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=People,dc=example,dc=com" \
"(memberOf=cn=linux-admins,ou=Group,dc=example,dc=com)"
# 查找邮箱包含 example.com 的用户
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=People,dc=example,dc=com" \
"(mail=*@example.com)"
# 组合查询:查找开发组中姓张的用户
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=People,dc=example,dc=com" \
"(&(cn=Zhang*)(memberOf=cn=developers,ou=Group,dc=example,dc=com))"TLS 加密配置
# 生成自签名证书(测试环境)
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/openldap/certs/ldap.key \
-out /etc/openldap/certs/ldap.crt \
-subj "/CN=ldap.example.com/O=Example Corp"
# 配置 OpenLDAP 启用 TLS
ldapmodify -Y external -H ldapi:/// <<EOF
dn: cn=config
changetype: modify
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/ldap.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/ldap.key
EOF
# 重启 slapd
systemctl restart slapd
# 验证 TLS
openssl s_client -connect ldap.example.com:636 -showcerts
# 客户端配置 TLS
# 将 CA 证书复制到客户端
scp /etc/openldap/certs/ldap.crt client:/etc/openldap/cacerts/
# 测试 LDAPS 连接
ldapsearch -x -H ldaps://ldap.example.com \
-b "dc=example,dc=com" \
-d 1OpenLDAP 主从复制
# 在主节点配置 syncrepl
ldapmodify -Y external -H ldapi:/// <<EOF
dn: olcOverlay=syncprov,olcDatabase={2}hdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov
olcSyncProvSessionlog: 100
EOF
# 在从节点配置复制
ldapmodify -Y external -H ldapi:/// <<EOF
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl: rid=001
provider=ldap://master.example.com
bindmethod=simple
binddn="cn=admin,dc=example,dc=com"
credentials=YourPassword
searchbase="dc=example,dc=com"
scope=sub
schemachecking=on
type=refreshAndPersist
retry="30 5 300 5"
interval=00:00:05:00
EOF
# 验证复制状态
ldapsearch -x -H ldap://slave.example.com \
-b "ou=People,dc=example,dc=com" \
"(objectClass=*)"优点
缺点
总结
LDAP 集成实现 Linux 服务器统一账户管理。SSSD 作为客户端缓存认证结果提升性能和可用性。生产环境必须部署 LDAP 高可用(主从复制)并启用 TLS 加密。建议保留本地 root 账户作为兜底,防止 LDAP 完全不可用时无法登录服务器。
关键知识点
- LDAP 数据以树形结构(DIT)组织,dc/ou/cn 定义层级
- SSSD 缓存认证结果,LDAP 不可用时使用缓存
- POSIX 属性(uidNumber/gidNumber)映射 Linux 用户权限
- TLS 加密是生产环境的基本要求
- realmd 是 Linux 加入 AD 域的最简便方式
项目落地视角
- 部署 OpenLDAP 主从复制保证高可用
- 保留本地 root 账户防止 LDAP 不可用时锁死
- 为 SSSD 配置合理的缓存超时时间
- 启用 TLS 加密认证传输
- 将 LDAP 认证纳入安全审计范围
常见误区
- 不启用 TLS 导致密码明文传输
- LDAP 服务器无备份导致数据丢失
- 忘记配置 mkhomedir 导致首次登录无家目录
- SSSD 缓存时间设置过长导致权限变更不生效
- 不做高可用导致 LDAP 单点故障影响所有服务器
进阶路线
- 学习 LDAP 复制(syncrepl)和多主架构
- 研究 FreeIPA 统一身份管理平台
- 了解 OAuth2/OIDC 替代 LDAP 的现代方案
- 学习 LDAP 与 SSH 密钥管理的集成
- 研究 LDAP 密码策略和过期管理
适用场景
- 多台服务器统一账户管理
- 企业 AD 域集成 Linux 服务器
- 团队权限统一管理
- DevOps 自动化运维的用户权限管理
落地建议
- 部署 LDAP 主从复制保证高可用
- 保留本地 root 账户作为兜底
- 启用 TLS 加密认证传输
- 使用 SSSD 缓存提升可用性
- 定期备份 LDAP 目录数据
排错清单
- 检查 SSSD 服务状态和日志(/var/log/sssd/)
- 用 ldapsearch 验证 LDAP 连接和查询
- 检查 TLS 证书是否正确配置
- 检查 DNS 解析是否正确
- 检查 /etc/nsswitch.conf 是否包含 sss
复盘问题
- LDAP 服务器宕机后,现有会话是否能继续工作?
- 密码策略(复杂度、过期)如何统一管理?
- 如何在不影响在线用户的情况下修改 LDAP 结构?
- SSSD 缓存过期时间设置是否合理?
