Carry の Blog Carry の Blog
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • OpenClaw
  • Hermes Agent
  • Claude Code
  • MySQL8-SOP手册
  • MySQL实战45讲学习笔记
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carry の Blog

好记性不如烂键盘
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • OpenClaw
  • Hermes Agent
  • Claude Code
  • MySQL8-SOP手册
  • MySQL实战45讲学习笔记
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 工作笔记

    • 实用linux命令-nc
    • 实用linux命令-lsof
    • 实用linux命令-ss
    • Bash 备忘清单
    • Ansible 备忘清单
    • linux 文件的权限和属性
    • GPT分区使用 `parted` 扩展分区的操作流程
    • 实用linux命令-sed
    • VSCode快捷键备忘录
    • 实用linux命令-curl
  • K8S

  • Nginx

  • 监控

  • 网络安全

  • 其他

  • Docker

  • Linux笔记
  • 网络安全
Carry の Blog
2022-03-10
目录

LDAP统一认证管理

版本说明

本文写于 2022-03。
LDAP 统一认证的架构思路(集中账号 + 各服务对接同一目录)未变,经 2026-07 复核仍适用。

# 1. 十几台服务器,每个人的账号密码要同步十几遍

团队几个人、几十台服务器,最原始的做法是每台机器各建一遍本地用户。新人入职建 N 遍账号,离职要在 N 台机器上逐一删除——只要漏一台,就是一个长期存在的越权入口。这类事故的根因往往不是"密码强度不够",而是"账号生命周期管理"本身就没有单点。LDAP(轻量目录访问协议)统一认证要解决的就是这个问题:账号只在一处创建/禁用,所有服务器实时认这一份数据。

# 2. 为什么选 LDAP 而不是自己写同步脚本

用 rsync/ansible 同步 /etc/passwd 也能"看起来"解决多机账号一致的问题,但有两个致命缺陷:

  • 非实时:同步脚本按 cron 跑,离职当天到下次同步之间,旧账号依然能登录。
  • 无法即时吊销会话:本地账号一旦登录建立了 SSH 会话,删除本地用户也不会踢掉已存在的连接;LDAP + PAM 方案里,禁用目录里的账号,配合较短的认证缓存周期,能把"权限收回"的窗口压缩到分钟级。

LDAP 的额外收益是目录结构化——按 OU(组织单元)分组、按 groupOfNames 做权限组,做批量策略("运维组只能登 A/B/C 机器")比维护一堆 /etc/sudoers 片段清晰得多。

# 3. 部署与接入:准备 → 执行 → 验证

# 3.1 准备:确定目录结构

dc=example,dc=com
├── ou=People        # 用户账号
├── ou=Groups         # 权限组
└── ou=Hosts          # (可选)按主机做访问控制
1
2
3
4

# 3.2 执行:安装 OpenLDAP 服务端

apt install slapd ldap-utils -y
dpkg-reconfigure slapd    # 交互式设置 domain、admin 密码
1
2

添加一个用户条目(LDIF 格式):

# user.ldif
dn: uid=alice,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: alice
cn: Alice
sn: Alice
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/alice
loginShell: /bin/bash
userPassword: {SSHA}<hash>
1
2
3
4
5
6
7
8
9
10
11
12
13
ldapadd -x -D "cn=admin,dc=example,dc=com" -W -f user.ldif
1

# 3.3 执行:客户端接入(各服务器)

apt install libnss-ldap libpam-ldap ldap-utils -y
# 交互式配置里填写:LDAP server URI、Base DN、bind DN
1
2

/etc/nsswitch.conf 追加 ldap 数据源:

passwd: files ldap
group:  files ldap
shadow: files ldap
1
2
3

/etc/pam.d/common-auth 中确保 pam_ldap.so 生效于 pam_unix.so 之前或之后(按需决定本地账号与目录账号的优先级)。

# 3.4 验证

# 服务端:确认条目已写入
ldapsearch -x -b "dc=example,dc=com" "(uid=alice)"

# 客户端:确认 NSS 能解析到 LDAP 用户
getent passwd alice
# 应输出:alice:x:10001:10001::/home/alice:/bin/bash

# 客户端:确认 PAM 认证链路打通
su - alice
# 输入 LDAP 密码应能登录成功
1
2
3
4
5
6
7
8
9
10

# 4. 常见坑

症状:getent passwd alice 返回空,但 ldapsearch 明明能查到这个用户。 原因:/etc/nsswitch.conf 没有把 ldap 加进 passwd/group/shadow 三行,NSS 根本没有去查目录服务,只查了本地文件。 解药:确认三行都追加了 ldap,并重启 nscd(如果启用了缓存),否则旧的负缓存会让查询继续返回空。

症状:SSH 登录时密码正确却报 Permission denied,日志里是 pam_ldap: bind failed。 原因:客户端配置的 bind DN/密码用了匿名绑定,而服务端 ACL 限制了匿名用户不能读取 userPassword 属性。 解药:给客户端配一个专用的只读 bind 账号,或者在服务端 ACL 里对特定 bind DN 开放 userPassword 的读权限——不要图省事直接对匿名开放。

症状:离职当天禁用了 LDAP 账号,但离职员工的 SSH 会话还能继续操作。 原因:PAM/NSS 只在建立新会话时校验,已建立的 SSH 连接不会被动态踢掉。 解药:禁用账号的同时,要在关键机器上主动 pkill -u alice 或走堡垒机强制断连;长期方案是接入集中式会话管理(堡垒机/跳板机),而不是依赖 LDAP 单点。

# 5. 可复用的规则

  1. 账号的生命周期(创建/禁用/删除)只应该有一个源头,多机同步脚本是临时方案不是终态。
  2. LDAP 只解决"认证从哪来",不解决"已建立的会话何时失效"——两者要分别设计。
  3. 客户端 bind 账号权限要单独开一个只读专用账号,不要用匿名绑定或管理员账号。
  4. 上线前先按目录结构(People/Groups/Hosts)规划好 OU,后期批量授权全靠这层结构。

# 6. 延伸阅读

企业内网结合 VPN 做统一认证的完整方案见 企业中 Docker+Openvpn+LDAP+OTP 快速搭建 VPN;网络层访问控制见 Firewalld 总结。


# 7. Agent 可直接解析的元数据块

{
  "_meta": {
    "doc_version": "2026-07-29",
    "article_id": "ldap-unified-auth",
    "profile_context": "any",
    "estimated_setup_time": "45min"
  },
  "quick_start": {
    "step_1": "apt install slapd ldap-utils -y && dpkg-reconfigure slapd",
    "step_2": "ldapadd -x -D 'cn=admin,dc=example,dc=com' -W -f user.ldif",
    "step_3": "客户端: apt install libnss-ldap libpam-ldap -y,并在 /etc/nsswitch.conf 追加 ldap"
  },
  "safety_rules": [
    "客户端 bind 账号必须是只读专用账号,禁止使用匿名绑定读取 userPassword",
    "禁用账号不等于踢掉已有会话,需配合主动断连或堡垒机方案",
    "userPassword 存储必须使用 SSHA 等加盐哈希,禁止明文"
  ],
  "verification": {
    "check_server_entry": "ldapsearch -x -b 'dc=example,dc=com' '(uid=<user>)' 能查到条目",
    "check_nss": "getent passwd <user> 能返回该用户信息",
    "check_pam": "su - <user> 使用 LDAP 密码可登录成功"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

AI Agent 使用指南:

  • 当用户说"新服务器接入统一认证" → 执行 quick_start.step_3,再用 verification.check_nss/check_pam 确认
  • 当用户说"账号能查到但登不上" → 按第 4 节第二条排查 bind 权限与 ACL
#ldap
上次更新: 8/7/2026
最近更新
01
Browserless 使用笔记:把 Chrome 变成一个可以被并发调用的网络服务
08-07
02
ORDER BY 配合 LIMIT 触发的索引选择陷阱 原创
08-07
03
Nginx 运维知识地图:从配置基础到反向代理实战 原创
07-29
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式