基于 LDAP 的 PAM 验证
参考资料:
https://wiki.debian.org/LDAP/PAM
https://wiki.debian.org/LDAP/NSS
https://wiki.samba.org/index.php/Nslcd
一、前言
Linux 可以通过 PAM
(Pluggable Authentication Modules, 可插入认证模块)来提供认证功能,不少系统服务认证是通过 pam 来进行。 pam 的配置文件放在 /etc/pam.d/
目录下, 其中以 common 开关的配置文件是通用认证,里面通过 pam_unix.so
模块来进行认证,该模块读取 /etc/passwd 、 /etc/shadow 等系统配置信息,做到与系统账号同步。
通过 debian 的 wiki 可以知道,目前有两个包可以实现 pam_ldap 功能的,分别是 libpam-ldap
和 libpam-ldapd
(注意,后面这个包名称后面多了个'd')
其中, 后者(libpam-ldapd
)是更新的解决方案,但是前者配置上比较简单。
二、libpam-ldap (无法调通,放弃,仅做记录)
安装
apt install libpam-ldap
与 libpam-ldap
相关的几个配置文件:
- /etc/ldap/ldap.conf (系统级 ldap 配置文件)
- /etc/pam_ldap.conf
安装完毕后,该包会修改 /etc/pam.d/
目录下的几个 common 开头的配置文件,加入跟 pam_ldap.so
相关的配置。首先使用 pam_unix.so
进行本地验证,未通过时通过 pam_ldap.so
进行远程验证。
理论上来说,此时应该可以使用 ldap 进行登录,然而在试验中一直报连不上服务器。搜索许久未找到解决方案,遂放弃。
三、libpam-ldapd (可以使用的方案)
libpam-ldapd
是新的解决方案,它使用 nslcd
作为服务后端,而 nslcd
也是 libnss-ldapd
的服务后端。
安装
apt install libpam-ldapd # 同时会安装 nslcd libnss-ldapd 等包,而且只安装 libnss-ldapd 时也会安装 libpam-ldapd 包。debian 把它们做成了相互依赖。
与 libpam-ldapd
相关的几个配置文件:
- /etc/ldap/ldap.conf (系统级 ldap 配置文件)
- /etc/nslcd.conf (nslcd 配置文件)
- /etc/nsswitch.conf (nsswitch 配置文件)
同样的,安装完毕后,程序也会修改 /etc/pam.d/
目录下的几个 common 开头的配置文件,加入跟 pam_ldap.so
相关的配置。不知道该 pam_ldap.so
跟上一个包里的 pam_ldap.so
是不是同一个,不过机制是同样的机制。但是这里还运用到了 NSS
。
1. nsswitch 配置
nsswitch (Name Service Switch,名称服务开关)是 linux 系统给各应用实现名称解析的通用框架,名称解析流程为:
应用程序 --> nsswitch(配置文件(查询顺序)) --> 对应库文件 --> 解析库 --> 完成解析
系统级的解析也是通过该框架完成,如 passwd ,在该配置上可以配置从哪里获取 passwd 信息。
这部分配置在安装软件的时候有图形界面进行设置,直接选择 passwd
, group
, shadow
就行了。
手动修改的话,编辑 /etc/nsswitch.conf
# 在每一项后面加上 ldap passwd: compat ldap group: compat ldap shadow: compat ldap
该修改的意思是,passwd、group、shadow 除了从对应的文件中获取数据外,还要从 ldap 中获取信息。
2. nslcd 配置
在安装软件的时候,这部分会要求填写 uri
, base
, 和 tls 证书。可以在安装完成后,再进行手动修改。
手动对 /etc/nslcd.conf
进行修改,仅使用以下配置即可(ldap 的配置按自己的需要进行填写):
uid nslcd gid nslcd # 按需填写 uri ldaps://ldapserver.com base ou=myou,dc=example,dc=com base group ou=unix,ou=groups,dc=example,dc=com # 按需填写 binddn CN=test,ou=myou,dc=example,dc=com bindpw <yourpassword> ssl on tls_reqcert allow # 需要先把自定义证书加到系统证书内 tls_cacertfile /etc/ssl/certs/ca-certificates.crt # for map # 按需填写 filter passwd (&(objectClass=user)(objectClass=person)(!(objectClass=computer))(uidNumber=*)) filter group (objectClass=group) filter shadow (&(objectClass=user)(objectClass=person)(!(objectClass=computer))(uidNumber=*)) map passwd uid sAMAccountName #map passwd homeDirectory unixHomeDirectory map passwd homeDirectory "/home/$sAMAccountName" map passwd gecos displayName #map passwd gidNumber primaryGroupID map passwd loginShell "/bin/bash" #map group uniqueMember member #map group gidNumber primaryGroupID
首先是配置 ldap 的 url、base dn、bind dn、证书等。
后面的 filter 和 map 主要是给 ldap 使用的,filter 指定搜索条件, map 指定属性映射关系。由于这里使用 windows AD ,因此要做相应的属性映射。 (部分unix需要的属性可参考: https://blogs.technet.microsoft.com/activedirectoryua/2016/02/09/identity-management-for-unix-idmu-is-deprecated-in-windows-server/)
3. 配置登录后自动创建 home 目录
手动创建或修改文件 /usr/share/pam-configs/mkhomedir
,内容如下:
Name: Create home directory during login Default: yes Priority: 900 Session-Type: Additional Session: required pam_mkhomedir.so umask=0077 skel=/etc/skel
然后运行命令 sudo pam-auth-update
进行更新 pam 即可。
4. 重启服务
修改完毕后,需要重启服务
systemctl restart nscd systemctl restart nslcd
5. 使用 getent 命令验证配置是否正确
getent - get entries from Name Service Switch libraries。 从某个解析库LIB中获的条目。该命令可以检测nsswitch配置是否正确。
使用方式:
getent passwd
该命令从 nsswitch 中获取 passwd 信息。如果配置正确,那么输出的结果除了本地的 passwd 信息外,还会包含 ldap 的账户信息。
(注意,这里能正确输出的前提是,ldap 中相应的 uid 等信息要存在,后续往 ldap 中添加用户,至少要设置 uidNumber
gidNumber
Loginshell
属性。)
遇到过的问题
1. getent passwd 明明已经可以获取到用户信息,可是 ssh 就是连不上,报 Failed password 。几经周折,最后发现它还是对文件 /etc/ldap/ldap.conf
有依赖, nslcd.conf 中配置了 ssl on
,而 ldap.conf 中没有配置,因此在实际获取数据时,没有用正确的连接方式,因而获取不到数据。解决方法: 在 ldap.conf 和 nslcd.conf 中都加上 ssl on
。
2019-11-12 补充: 上面的解决方法不对。真正原因是 nscd 缓存未刷新,重启一下 nscd 服务即可, 命令 service nscd restart
。 ldap.conf 里面不需要设置 ssl on 。