PAM模块简介
- 1. 介绍
- 1.1 概念
- 1.2 验证过程简述
- 2. 配置文件介绍
- 2.1 PAM的模块类型
- 2.2 PAM的控制标记
- 2.3 PAM的模块路径
- 3. 验证机制
- 3.1 login的验证机制流程
- 3.2 pam相关文件
- 4. 示例
- 4.1 ssh远程登录控制
- 4.2 禁止账号间使用su命令切换
- 4.3 限制root从tty1,tty2,tty5登录
1. 介绍
1.1 概念
在过去,我们想要对一个使用者进行认证 (authentication),得要要求用户输入账号密码, 然后透过自行撰写的程序来判断该账号密码是否正确。也因为如此,我们常常得使用不同的机制来判断账号密 码, 所以搞的一部主机上面拥有多个各别的认证系统,也造成账号密码可能不同步的验证问题! 为了解决这个问题,便有了 PAM (Pluggable Authentication Modules, 嵌入式认证模块)
的机制!
PAM 可以说是一套应用程序编程接口 (Application Programming Interface, API),他提供了一连串的 验证机制,只要使用者将验证阶段的需求告知 PAM 后, PAM 就能够回报使用者验证的结果 (成功或失败)。由于 PAM 仅是一套验证的机制,又可以提供给其他程序所呼叫引用,因此不论你使用什么程序,都可以使用 PAM 来进行验证,如此一来,就能够让账号密码或者是其他方式的验证具有一致的结果!也让程序设计师方便处理验证的问题!
PAM 是一个独立的 API 存在,只要任何程序有需求时,可以向 PAM 发出验证要求的通知, PAM 经过一连串的验证后,将验证的结果回报给该程序,然后该程序就能够利用验证 的结果来进行可登入或显示其他无法使用的讯息。 这也就是说,你可以在写程序的时候将 PAM 模块的功能加入,就能够利用 PAM 的验证功能。 因此目前很多程序都会利用 PAM
1.2 验证过程简述
PAM 藉由一个与程序相同文件名的配置文件来进行一连串的认证分析需求。我们以 passwd 这个指令的呼叫 PAM 来说明。 当你执行 passwd 后,这支程序呼叫 PAM 的流程是:
-
- 用户开始执行 /usr/bin/passwd 这支程序,并输入密码;
-
- passwd 呼叫 PAM 模块进行验证;
-
- PAM 模块会到 /etc/pam.d/ 找寻与程序 (passwd) 同名的配置文件;
-
- 依据 /etc/pam.d/passwd 内的设定,引用相关的 PAM 模块逐步进行验证分析;
-
- 将验证结果 (成功、失败以及其他讯息) 回传给 passwd 这支程序;
-
- passwd 这支程序会根据 PAM 回传的结果决定下一个动作 (重新输入新密码或者通过验证!)
2. 配置文件介绍
PAM配置文件有下面两种写法:
- 1)写在/etc/pam.conf文件中,但centos6之后的系统中,这个文件就没有了。
- 2)将PAM配置文件放到/etc/pam.d/目录下,其规则内容都是不包含 service 部分的,即不包含服务名称,而/etc/pam.d 目录下文件的名字就是服务名称。如: vsftpd,login等,只是少了最左边的服务名列。如:/etc/pam.d/sshd
[root@node1 ~]# cat /etc/pam.d/sshd
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare
可以将pam配置文件分为四列:
第一列代表 模块类型
第二列代表 控制标记
第三列代表 模块路径
第四列代表 模块参数
下面我们来详细了解这些参数:
2.1 PAM的模块类型
Linux-PAM有四种模块类型,分别代表四种不同的任务,它们是:
认证管理(auth)
账号管理(account)
会话管理(session)
密码管理(password)
一个类型可能有多行,它们按顺序依次由PAM模块调用。
管理方式 | 说明 |
---|---|
auth | 是 authentication (认证) 的缩写,所以这种类别主要用来检验使用者的身份验证,这种类别通常是需要密码来检验的, 所以后续接的模块是用来检验用户的身份 |
account | account (账号) 则大部分是在进行 authorization (授权),这种类别则主要在检验使用者是否具有正确的权限,举例来说,当你使用一个过期的密码来登入时,当然就无法正确的登入了。 |
session | session 是会议期间的意思,所以 session 管理的就是使用者在这次登入 (或使用这个指令) 期间,PAM 所 给予的环境设定。 这个类别通常用在记录用户登入与注销时的信息!例如,如果你常常使用 su 或者是 sudo 指令的话, 那么应该可以在 /var/log/secure 里面发现很多关于 pam 的说明,而且记载的数据是『session open, session close』的信息 |
password | 使用用户信息来更新.如:修改用户密码. |
这四个验证的类型通常是有顺序的,不过也有例外就是了。 会有顺序的原因是:
- (1) 我们总是得要先 验证身份 (auth) 后
- (2) 系统才能够藉由用户的身份给予适当的授权与权限设定 (account)
- (3) 登入与注销期间的环境才需要设定, 也才需要记录登入与注销的信息 (session)。
- (4) 如果在运作期间需要 密码修订 时才给予(password)的类别。
这样说起来, 自然是需要有点顺序吧!
2.2 PAM的控制标记
PAM使用控制标记来处理和判断各个模块的返回值.(在此只说明简单的认证标记)
控制标记 | 说明 |
---|---|
required | 表示即使某个模块对用户的验证失败,也要等所有的模块都执行完毕后,PAM 才返回错误信息。这样做是为了不让用户知道被哪个模块拒绝。如果对用户验证成功,所有的模块都会返回成功信息。 |
requisite | 与required相似,但是如果这个模块返回失败,则立刻向应用程序返回失败,表示此类型失败.不再进行同类型后面的操作. |
sufficient | 表示如果一个用户通过这个模块的验证,PAM结构就立刻返回验证成功信息(即使前面有模块fail了,也会把 fail结果忽略掉),把控制权交回应用程序。后面的层叠模块即使使用requisite或者required 控制标志,也不再执行。如果验证失败,sufficient 的作用和 optional 相同 |
optional | 表示即使本行指定的模块验证失败,也允许用户接受应用程序提供的服务,一般返回PAM_IGNORE(忽略). |
include | 表示在验证过程中调用其他的PAM配置文件。在RHEL系统中有相当多的应用通过完整调用/etc/pam.d/system-auth来实现认证而不需要重新逐一去写配置项。这也就意味着在很多时候只要用户能够登录系统,针对绝大多数的应用程序也能同时通过认证。 |
substack | 与 include 类似,区别是,include 调用文件执行时有 die 或者 bad 则立即返回调用处,而 substack 则等待文件执行完。 |
还有一种比较复杂的格式为value = action的语法来设置控制标志,标志之间会以空格分开。格式如下:
value1 = action1 value2 = action2 ……
例如:
root@ubuntu:~# grep -v '^#' /etc/pam.d/login
...
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so
..
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_env.so readenv=1
session required pam_env.so readenv=1 envfile=/etc/default/locale
...
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
其中value可以是下列Linux PAM库的返回值:
success、open_err、symbol_err、service_err、 system_err、buf_err、perm_denied、auth_err、cred_insufficient、authinfo_unavail、user_unknown、maxtries、new_authtok_reqd、acct_expired、 session_err、cred_unavail、cred_expired、cred_err、no_module_data、conv_err、 authtok_err、authtok_recover_err、authtok_lock_busy、authtok_disable_aging、 try_again、ignore、abort、authtok_expired、module_unknown、bad_item和default。
最后一个(default)能够用来设置上面的返回值无法表达的行为。
actionN
可以是一个非负整数或者是下面的记号之一:ignore、ok、done、bad、die和reset
。如果是非负整数J,就表示需要忽略后面J个同样类型的模块。通过这种方式,系统管理者可以更加灵活地设置层叠模块,模块的层叠路径由单个模块的反应决定。
关于这几个记号的详细解释:
- ignore:如果使用层叠模块,那么这个模块的返回值将被忽略,不会被应用程序知道。
- bad:他表示这个返回码应该被看作是模块验证失败的标志。如果这个模块是层叠模块的第一个验证失败的模块,那么他的状态值就是整个层叠模块验证的状态值和结果。
- die:终止层叠模块验证过程,立刻返回到应用程序。
- ok:告诉PAM这个模块的返回值将直接作为所有层叠模块的返回值。也就是说,如果这个模块前面的模块返回状态是PAM_SUCCESS,那这个返回值就会覆盖前面的返回状态。注意:如果前面的模块的返回状态表示模块验证失败,那么不能使用这个返回值再加以覆盖。
- done:终止后续层叠模块的验证,把控制权立刻交回应用程序。
- reset:清除所有层叠模块的返回状态,从下一个层叠模块重新开始验证。
2.3 PAM的模块路径
模块路径.即要调用模块的位置. 如果是64位系统,一般保存在/lib64/security,如: pam_unix.so
同一个模块,可以出现在不同的类型中.它在不同的类型中所执行的操作都不相同.这是由于每个模块针对不同的模块类型,编制了不同的执行函数.
常用的PAM模块介绍
- pam_securetty.so: 限制系统管理员 (root) 只能够从安全的 (secure) 终端机登入;那什么是终端机?例如 tty1, tty2 等就是传统的终端机装置名称。那么安全的终端机设定呢? 就写在 /etc/securetty 这个文件中。你可以查阅一下该文 件, 就知道为什么 root 可以从 tty1~tty7 登入,但却无法透过 telnet 登入 Linux 主机了!
[root@node1 ~]# cat /etc/securetty console vc/1 ... vc/11 tty1 ... tty11 ttyS0 ttysclp0 sclp_line0 3270/tty1 hvc0 ... hvsi0 hvsi1 hvsi2 xvc0
- pam_nologin.so: 这个模块可以限制一般用户是否能够登入主机之用。**当 /etc/nologin 这个文件存在时,则所有一般使用者均无法再登入系统了!**若 /etc/nologin 存在,则一般使用者在登入时, 在他们的终端机上会将该文件的内容显示出来!所以,正常的情况下,这个文件应该是不能存在系统中的。 但这个模块对 root 以及已经登入系统中的一般账号并没有影响。 (注意喔!这与 /etc/nologin.txt 并不相同!)
- pam_selinux.so: SELinux 是个针对程序来进行细部管理权限的功能。由于 SELinux 会影响到用户执行程序的权限,因此我们利用 PAM 模块,将 SELinux 暂时关闭, 等到验证通过后, 再予以启动!
- pam_console.so: 当系统出现某些问题,或者是某些时刻你需要使用特殊的终端接口 (例如 RS232 之类的终端联机设备) 登入主机时, 这个模块可以帮助处理一些文件权限的问题,让使用者可以透过特殊终端接口 (console) 顺利的登入系统
- pam_loginuid.so: 我们知道系统账号与一般账号的 UID 是不同的!一般账号 UID 均大于 1000 才合理。 因此,为了验证使用者的 UID 真的是我们所需要的数值,可以使用这个模块来进行规范!
- pam_env.so: 用来设定环境变量的一个模块,如果你有需要额外的环境变量设定,可以参考 /etc/security/pam_env.conf 这 个文件的详细说明。
- pam_unix.so: 这是个很复杂且重要的模块,这个模块可以用在验证阶段的认证功能,可以用在授权阶段的账号许可证管理, 可以用在会议阶段的登录文件记录等,甚至也可以用在密码更新阶段的检验!非常丰富的功能! 这 个模块在早期使用得相当频繁!
- pam_pwquality.so: 可以用来检验密码的强度!包括密码是否在字典中,密码输入几次都失败就断掉此次联机等功能,都是这模块提供的! 最早之前其实使用的是 pam_cracklib.so 这个模块,后来改成 pam_pwquality.so 这个模块, 但此模块完全兼容于 pam_cracklib.so, 同时提供了 /etc/security/pwquality.conf 这个文件可以额外指定默认值!比较容易处理修改!
- pam_limits.so:定义使用系统资源的上限,root用户也会受此限制,可以通过/etc/security/limits.conf或/etc/security/limits.d/*.conf来设定
- pam_listfile.so:访问应用程的控制开关
3. 验证机制
3.1 login的验证机制流程
[root@node1 ~]# cat /etc/pam.d/login
#%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth substack system-auth
auth include postlogin
account required pam_nologin.so
account include system-auth
password include system-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
session optional pam_console.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include system-auth
session include postlogin
-session optional pam_ck_connector.so
[root@node1 ~]# cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth required pam_faildelay.so delay=2000000
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 1000 quiet_success
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 1000 quiet
account required pam_permit.so
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
-session optional pam_systemd.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
auth required pam_tally2.so deny=6 onerr=fail no_magic_root unlock_time=120
login 的 PAM 验证机制流程是这样的:
-
验证阶段 (auth):
(a)会先经过 pam_securetty.so 判断,如果使用者是 root 时,则会参考 /etc/securetty 的设定; (b)经过 pam_env.so 设定额外的环境变量; (c)透过 pam_unix.so 检验密码,若通过则回报 login 程序;若不通过则 (d)继续往下以 pam_succeed_if.so 判断 UID 是否大于 1000 ,若小于 1000 则回报失败,否则再往下 (e)以 pam_deny.so 拒绝联机
-
授权阶段 (account):
(a)先以 pam_nologin.so 判断 /etc/nologin 是否存在,若存在则不许一般使用者登入; (b)接下来以 pam_unix.so 及 pam_localuser.so 进行账号管理 (c)接下来以 pam_succeed_if.so 判断 UID 是否小于 1000 ,若小于 1000 则不记录登录信息。 (d)最后以 pam_permit.so 允许该账号登入。
-
密码阶段 (password):
(a)先以 pam_pwquality.so 设定密码仅能尝试错误 3 次; (b)接下来以 pam_unix.so 透过 sha512, shadow 等功能进行密码检验,若通过则回报 login 程序,若不通过则 (c)以 pam_deny.so 拒绝登入。
-
会议阶段 (session):
(a)先以 pam_selinux.so 暂时关闭 SELinux; (b)使用 pam_limits.so 设定好用户能够操作的系统资源; (c)登入成功后开始记录相关信息在登录文件中; (d)以 pam_loginuid.so 规范不同的 UID 权限; (e)开启 pam_selinux.so 的功能。
总之,就是依据验证类别 (type) 来看,然后先由 login 的设定值去查阅,如果出现『 include system-auth 』 就转到 system-auth 文件中的相同类别,去取得额外的验证流程就是了。然后再到下 一个验证类别,最终将所有的验证跑完! 就结束这次的 PAM 验证啦!
3.2 pam相关文件
- /etc/pam.d/*:每个程序个别的 PAM 配置文件;
- /lib64/security/*:PAM 模块文件的实际放置目录;
- /etc/security/*:其他 PAM 环境的配置文件;
- /usr/share/doc/pam-*/:详细的 PAM 说明文件。
- /etc/securetty 会影响到 root 可登入的安全终端机
- /etc/nologin 会影响到一般 使用者是否能够登入
- /etc/security/limits.conf 资源限制
#范例一:vbird1 这个用户只能建立 100MB 的文件,且大于 90MB 会警告
[root@study ~]# vim /etc/security/limits.conf
vbird1 soft fsize 90000
vbird1 hard fsize 100000
#账号 限制依据 限制项目 限制值
# 第一字段为账号,或者是群组!若为群组则前面需要加上 @ ,例如 @projecta
# 第二字段为限制的依据,是严格(hard),还是仅为警告(soft);
# 第三字段为相关限制,此例中限制文件容量,
# 第四字段为限制的值,在此例中单位为 KB。
# 若以 vbird1 登入后,进行如下的操作则会有相关的限制出现!
[vbird1@study ~]$ ulimit -a
....(前面省略)....
file size (blocks, -f) 90000
....(后面省略)....
[vbird1@study ~]$ dd if=/dev/zero of=test bs=1M count=110
File size limit exceeded
[vbird1@study ~]$ ll --block-size=K test
-rw-rw-r--. 1 vbird1 vbird1 90000K Jul 22 01:33 test
# 果然有限制到了
#范例二:限制 pro1 这个群组,每次仅能有一个用户登入系统 (maxlogins)
[root@study ~]# vim /etc/security/limits.conf
@pro1 hard maxlogins 1
# 如果要使用群组功能的话,这个功能似乎对初始群组才有效喔!而如果你尝试多个 pro1 的登入时,
# 第二个以后就无法登入了。而且在 /var/log/secure 文件中还会出现如下的信息:
# pam_limits(login:session): Too many logins (max 1) for pro1
这个文件挺有趣的,而且是设定完成就生效了,你不用重新启动任何服务的!
但是 PAM 有个特殊的地方,由于他是在程序呼叫时才予以设定的,因此你修改完成的数据, 对于已登入系统中的用户是没有效果的,要等他再次登入时才会生效
4. 示例
4.1 ssh远程登录控制
在/etc/pam.d/sshd文件中添加一条:
[kevin@node1 ~]$ head -2 /etc/pam.d/sshd
#%PAM-1.0
auth required pam_listfile.so item=user sense=allow file=/etc/sshdusers onerr=succeed
添加两个用户kevin和grace
[root@centos6-test06 ~]# useradd kevin
[root@centos6-test06 ~]# passwd kevin
[root@centos6-test06 ~]# useradd grace
[root@centos6-test06 ~]# passwd grace
编辑file指定的文件,添加上一个用户kevin(这一步是关键)
[root@centos6-test06 ~]# echo "kevin" >/etc/sshdusers //文件/etc/sshdusers是在上面添加到/etc/pam.d/sshd中定义的
然后验证,发现使用kevin账号能正常ssh登录,使用grace账号就不能正常ssh登录了!
kevin@localhost's password:
Last failed login: Fri Apr 14 18:35:27 CST 2023 from localhost on ssh:notty
There were 2 failed login attempts since the last successful login.
[kevin@node1 ~]$ exit
logout
Connection to localhost closed.
[root@node1 ~]# ssh -p22 grace@localhost
grace@localhost's password:
Permission denied, please try again.
注:此处如果root也使用ssh远程连接,也会受到pam_listfile.so限制的。
注意:
如果发生错误,Linux-PAM 可能会改变系统的安全性。这取决于你自己的选择,你可以选择不安全(开放系统)和绝对安全(拒绝任何访问)。通常,Linux-PAM 在发生错误时,倾向于后者。任何的配置错误都可能导致系统整个或者部分无法访问。配置 Linux-PAM 时,可能遇到最大的问题可能就是 Linux-PAM 的配置文件/etc/pam.d/*被删除了。如果发生这种事情,你的系统就会被锁住。有办法可以进行恢复,最好的方法就是用一个备份的镜像来恢复系统,或者登录进单用户模式然后进行正确的配置。
4.2 禁止账号间使用su命令切换
su的缺点
- 1)不安全su工具在多人参与的系统管理中,并不是最好的选择,su只适用于一两个人参与管理的系统,毕竟su并不能让普通用户受限的使用;超级用户root密码应该掌握在少数用户手中。
- 2)麻烦:需要把root密码告知每个需要root权限的人。
可以在/etc/pam.d/su文件里设置禁止用户使用su命令
[root@node1 ~]# head -6 /etc/pam.d/su
#%PAM-1.0
auth sufficient pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth sufficient pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth required pam_wheel.so use_uid
默认的状态下是允许所有用户间使用su命令进行切换的!(或者两行都注释也是运行所有用户都能使用su命令)
如果开启第二行auth,表示只有root用户和wheel组内的用户才可以使用su命令。
如果注释第一行,开启第二行,表示只有wheel组内的用户才能使用su命令,root用户也被禁用su命令。
4.3 限制root从tty1,tty2,tty5登录
在/etc/pam.d/login中添加如下一行
auth required pam_securetty.so
在/etc/pam.d/securetty中将tty1,tty2,tty5注释
之后使用root用户再次登录,就会出现
这么做其实并不是只限制root用户,也可以将其它用户用此方法来限定,当系统安装完成后,使用此方法来增强一下安全性。