Linux不支持“50%相似度”等模糊匹配,实际应使用pam_pwquality.so的difok=N(如difok=5)强制新旧密码至少N位字符不同,并配合minclass=4、reject_username、maxrepeat=2及pam_pwhistory.so的remember参数协同生效。

Linux 本身没有直接支持“相似度 50%”这种模糊匹配的原生 PAM 模块。PAM 不做字符串编辑距离(如 Levenshtein)或语义相似性计算,所有主流发行版的 pam_pwquality.so 或 pam_pwhistory.so 均不提供百分比相似度控制参数。
但你可以通过已有机制实质性降低新旧密码雷同风险,效果远优于“50%相似度”这种不可控指标:
✅ 实际可行的核心控制:用 difok 强制字符差异数量
pam_pwquality.so 提供 difok=N 参数——它表示新密码中至少有 N 个字符不能与旧密码相同位置上的字符一致(逐位比对,区分大小写)。这不是概率或比例,而是硬性字符数门槛,更可靠、可验证。
例如:
password requisite pam_pwquality.so difok=5 minlen=12 ...
→ 用户改密时,新密码必须在至少 5 个位置上与旧密码不同(比如旧密码 Abc123!xyz789,新密码不能只把末尾 9 改成 0 就过关)。
-
difok=5对 12 位密码 ≈ 42% 字符变动,已覆盖多数弱变更场景 - 若要求更高,可设
difok=6或difok=8,配合minlen=14更稳妥
⚠️ 注意:
difok只在用户有旧密码哈希且 PAM 能读取时生效;首次设密码或旧密码未被历史模块记录时,该检查跳过。
✅ 配合其他策略堵住“换汤不换药”漏洞
单靠 difok 不够?再加这几条,基本杜绝常见相似套路:
-
reject_username:禁止密码含用户名(正向/反向/大小写变形) -
maxrepeat=2:禁连续 3 个相同字符(防aaa→bbb这类“伪变更”) -
minclass=4:强制四类字符各至少 1 个(大写、小写、数字、特殊符),旧密码若缺某类,新密码必须补上 → 必然引入新字符类型 -
enforce_for_root+remember=24:确保 root 也受历史记录约束,避免绕过
✅ 确保 difok 生效的关键前提
- 模块必须放在
common-password或system-auth的password类型行中,且在pam_unix.so或pam_pwhistory.so之前(否则可能被跳过) - 旧密码哈希需已存在:
/etc/security/opasswd文件存在且权限为600,由pam_pwhistory.so自动维护 - 用户已成功改密过至少一次(首次设密无“旧密码”可比,
difok不触发)
✅ 不要尝试的“伪方案”
- ❌ 修改
/etc/security/pwquality.conf单独设difok:不生效,必须在 PAM 配置行中显式声明 - ❌ 使用
pam_cracklib.so:老旧模块,difok行为不稳定,且不支持minclass等关键参数 - ❌ 写自定义脚本拦截
passwd:破坏 PAM 流程,易导致认证链断裂或锁死账户
真正安全的密码策略,靠的是确定性规则组合,而不是无法落地的模糊指标。difok + minclass + reject_username + remember 四者协同,比任何“50%相似度”都更严格、更可审计、更难绕过。


















