linux强密码策略关键在于pam_pwquality.so模块配置,而非login.defs参数;需在common-password或system-auth中添加requisite行,设minlen=12、四类字符各至少1个、difok=5、maxrepeat=3、reject_username及enforce_for_root,并配合pam_pwhistory.so和login.defs实现生命周期与历史限制。

配置 PAM 模块实现强密码复杂度与过期策略,关键不是堆参数,而是理清模块职责、加载顺序和生效范围。真正起效的密码强度由 pam_pwquality.so 控制,而 /etc/login.defs 中的 PASS_MIN_LEN 在启用 PAM 后完全失效——这是最常踩的坑。
确认并启用 pam_pwquality.so 模块
现代系统(RHEL 8+/Ubuntu 20.04+)默认用它替代老旧的 pam_cracklib.so。先检查是否安装:
- RHEL/CentOS:运行
yum install libpwquality或dnf install libpwquality - Debian/Ubuntu:运行
apt install libpwquality-tools - 验证模块存在:
ls /lib/security/pam_pwquality.so或/lib64/security/pam_pwquality.so
然后编辑对应 PAM 配置文件:
- Ubuntu/Debian → 修改
/etc/pam.d/common-password - RHEL/CentOS → 修改
/etc/pam.d/system-auth
在 password 段中添加或修正这一行(位置要靠前,且类型必须是 requisite):
理解核心参数的真实含义
这些参数不是孤立生效,而是相互影响:
-
minlen=12是基础长度,但若同时设了ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1,实际密码往往需更长才能满足全部字符类要求 -
difok=5表示新旧密码至少 5 个字符不同,不是“最多相同 5 个” -
maxrepeat=3禁止连续 4 个及以上相同字符(如aaaa被拒,aaabbb允许) -
reject_username会拒绝包含用户名(含大小写反转)的密码,但对 root 默认不生效,必须加enforce_for_root
注意:minlen 不是绝对下限。如果某类字符未达标,模块会自动抬高最低长度——例如设 minlen=12 且四类字符各要 1 个,但用户只输字母数字,那实际要求可能达 14 位以上。
配置密码生命周期与历史复用限制
仅管住“怎么设密码”不够,还得管住“什么时候能改”和“能不能反复用旧密码”:
- 在
/etc/login.defs中设置全局默认值:PASS_MAX_DAYS 90(90 天强制更新)PASS_MIN_DAYS 7(改密后 7 天内不可再改)PASS_WARN_AGE 7(到期前 7 天登录时提醒) - 在同一 PAM 文件中,在
pam_pwquality.so行之后添加:password [success=1 default=ignore] pam_unix.so use_authtok sha512 shadowpassword required pam_pwhistory.so remember=24 use_authtok - 首次启用需手动创建记录文件:
sudo touch /etc/security/opasswd && sudo chmod 600 /etc/security/opasswd
验证与避免常见失效场景
策略修改后无需重启服务,但以下情况会导致不生效:
- 把配置写在
auth或account段——密码复杂度只在password栈中触发 - 用了
required但前面已有模块失败,导致整个栈提前终止 - SSH 登录不拦弱密码——因为 SSH 走的是
auth栈,而复杂度校验必须在password栈(即passwd命令)里做 - root 用户没加
enforce_for_root,默认不受约束
测试建议:新开终端执行 passwd,输入弱密码观察是否被拒;用 pwscore 工具评分验证规则效果(如 echo "MyPass123!" | pwscore)。











