PAM是Sun公司在1995年开发的,目前是linux/unix的核心认证框架,全称为可插拔认证模块,一般是开发比较关心
PAM已经提前整合了各类认证库,比如本地密码库,ssh密钥库。核心目的是将认证功能和应用程序解耦,无需内置复杂的认证逻辑,只需要调用PAM接口就可以实现多样化的身份验证需求
1 2 3 4 5 6 7 8
| 应用程序(sshd) → PAM核心库(libpam.so) → PAM配置文件/etc/pam.d/应用名 → PAM模块(pam_unix.so)
工作层次: 应用程序层:发起认证请求,如用户登录、sudo,执行PAM提供的标准api PAM核心库层:解析应用对应的PAM配置文件,按规则加载/执行PAM模块,协调模块执行顺序,汇总模块返回结果 配置文件层:定义"应用程序应使用哪些模块","模块执行顺序","模块结果如何影响整体认证" 模块层:实现具体认证功能
|
PAM配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| 存储路径/etc/pam.d/ 每个应用程序对应一个同名配置文件,如sshd对应/etc/pam.d/sshd
所有者/组必须为root:root 文件权限建议644
每条规则行的格式为: type control module-path module-arguments
比如: cat /etc/pam.d/crond auth include system-auth account required pam_access.so account include system-auth session required pam_loginuid.so session include system-auth
type类型值: 1.auth 身份认证(你是谁) 典型模块pam_unix.so pam_ssh.so 用以比如sshd登录、su切换用户时使用
2.account 账户有效性检查(你有权限吗) 典型模块pam_unix.so pam_time.so 用以限制过期账户登录、工作时间登录
3.password 密码管理(修改密码等) 典型模块pam_cracklib.so pam_unix.so 用以比如passwd命令、首次登录强制修改密码
4.session 会话管理(登录、登出前辅助操作) 典型模块pam_cracklib.so pam_unix.so 用以记录登录日志、设置用户最大进程数
control控制标志:(定义结果联动逻辑) 核心作用,决定模块的执行结果如何影响当前和后续 1.required 模块必须成功,否则当前阶段失败,但会执行后续模块,比如核心认证模块
2.requisite 模块必须成功,否则终止当前阶段 用于关键校验
3.sufficient 模块成功则当前阶段直接通过,后续模块不再执行;失败就继续执行
4.option 模块结果不影响当前阶段
5.include 引入其他配置文件的所有规则
6.substack 引起其他配置文件的规则,但视为子栈,失败仅终止子栈,父栈继续执行
module-path模块路径:指定要加载的pam模块 常用内置模块: pam_unix.so 本地密码认证、账户检查、密码更新 pam_cracklib.so 密码强度检查 pam_tally2.so 登录失败次数限制 pam_time.so 登录时间限制 pam_listfile.so 用户、终端黑白名单控制
module-argument 模块参数: 为pam模块传递自定义参数,调整模块的执行规则,参数需与模块 pam_unix.so: unllok允许空密码、shadow读取/etc/shadow密码、use_authtok 复用前一模块密码 例: auth required pam_unix.so nullok (允许空密码登录)
pam_cracklib.so: retry=3 密码强度检查可重试3次 例: password requisite pam_cracklib.so retry=3 minlen=8
pam_tally2.so: deny=5 连续五次失败锁定 unlock_time=300 锁定300秒 even_deny_root 适用root 例: auth required pam_tally2.so deny=5 unlock_time=300
pam_time.so 依赖于/etc/security/time.conf的时间规则 例: account required pam_time.so
|
**通用配置文件common-*(**复用规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 系统默认在/etc/pam.d/提供4个通用配置文件,用于存储所有应用共享的认证规则,避免重复编写
1. common-auth common-account common-password 共享的password阶段规则 common-session 共享的session阶段规则
2.使用include复用 auth include common-auth
3.实例:auth-common
auth [success=1 default=ignore] pam_unix.so unllok_secure auth requisite pam_deny.so auth required pam_permit.so
pam_unix.so认证成功时跳过后续一个模块,失败则忽略 pam_deny.so 拒绝所有请求(当第一条失败后执行) pam_permit.so 允许认证,当第一条成功后执行
|
PAM的实战
配置密码复杂度策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| 查看当前使用的策略 cat /etc/pam.d/passwd
password substack system-auth -password optional pam_gnome_keyring.so use_authtok password substack postlogin 可以看到使用的password策略是system-auth
cat /etc/pam.d/system-auth ... password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
/etc/security/pwquality.conf
参数说明:
minlen = 12
difok = 7
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
minclass = 3
usercheck = 1
enforcing = 1
retry = 3
local_users_only = 0
enforce_for_root = 1
|
配置限制特定用户只能从特定IP登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ls /lib*/security/pam_access.so /lib64/security/pam_access.so
grep -r PAM /etc/ssh | grep -v '#' /etc/ssh/sshd_config.d/50-redhat.conf:UsePAM yes
vim /etc/pam.d/sshd 第一行插入(目的是,在sshd密码认证之前,对其做IP层面的限制) auth required pam_access.so
vim /etc/security/access.conf +:ws:ALL +:xhy:192.168.10.0/24 +:xhy:10.0.0.1 +:@wangsheng:10.0.0.0/24 -:ALL:ALL
|
基于PAM实现用户登录失败次数限制(防暴力破解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| find / -name pam_faillock.so /usr/lib64/security/pam_faillock.so
vim /etc/pam.d/password-auth 4 auth required pam_env.so 5 auth required pam_faillock.so preauth silent audit deny=5 unlock_time=120 6 auth sufficient pam_unix.so try_first_pass nullok 7 auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=120 8 auth required pam_deny.so 9 10 account required pam_unix.so 11 account required pam_faillock.so
12 password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= 13 password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow 14 password required pam_deny.so 15 16 session optional pam_keyinit.so revoke 17 session required pam_limits.so 18 -session optional pam_systemd.so 19 session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid 20 session required pam_unix.so
第5和7和11是新添加的 5:检查用户账户是否已被锁定,如果账户已锁定(之前失败5次),直接拒绝访问 7:记录失败次数,达到5次就锁定账户120秒 11:再次验证账号是否是锁定状态
|
| 参数 |
作用 |
示例 |
preauth |
在认证前检查账户是否已锁定 |
如果已锁定,直接拒绝 |
silent |
静默模式,不显示过多信息 |
避免给攻击者提示 |
audit |
记录详细日志到系统日志 |
便于审计和监控 |
deny=5 |
允许连续失败的次数 |
5次失败后锁定 |
unlock_time=120 |
锁定时间(秒) |
120秒=2分钟 |
authfail |
认证失败后执行 |
密码输入错误后计数器增加 |
配置用户会话资源限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| find / -name pam_limits.so /usr/lib64/security/pam_limits.so
vim /etc/pam.d/sshd session include pam_limits.so
vim /etc/security/limits.conf 配置文件格式: <username> <type> <item> <value>
<username>(适用对象) 用户名:如 john。 组名:格式为 @groupname,如 @developers。 通配符 *:代表默认限制,适用于所有未明确指定的普通用户
<type>(限制类型) soft:软限制。用户可以超过这个值,但不能超过 hard 限制。通常作为默认值,用户可以通过 ulimit 命令自行上调。 hard:硬限制。由系统管理员设定,是用户调优的物理上限。只有 root 用户可以增加硬限制。 -:表示同时设定 soft 和 hard 为相同的值。
<item>(限制资源项) nofile 单个进程可以打开的最大文件句柄数(最常用)。 nproc 该用户可以创建的最大进程数。 memlock 最大可锁定在内存中的地址空间 (KB)。 stack 最大栈大小 (KB)。 cpu 最大 CPU 时间(分钟)。 fsize 用户可创建的最大文件大小 (KB)。 maxlogins 该用户或组允许的最大并发登录数。 as 进程可占用的最大虚拟内存(地址空间)大小 (KB)。
<value>(限制值) 根据 <item> 的不同,单位可能是 KB、分钟或纯数字
|
配置示例(后面的规则会覆盖前面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| * hard core 0 * soft core 10000
* hard rss 500000 * hard data 200000 * hard stack 100000
* hard nproc * hard maxlogins 3
* soft nproc 1024 * hard nproc 4096 @staff hard nproc 10000
@dev hard nofile 5000
|
这里的limits.conf与ulimit与systemd(cgroup/sysctl)的区别
- ulimit只对当前 Shell 进程及其产生的子进程
- limits.conf(pam模块)在用户登录时,会自动帮你执行类似 ulimit 的操作
- sysctl设置的是整个系统的限制,不分用户
- systemd(cgroup)作用于具体的服务单元 (Service Unit)