说实话,第一次被 Linux 系统拒绝六位纯数字密码的时候,我差点以为是终端卡了:输入passwd,敲了一串123456,系统回了一句BAD PASSWORD: The password is shorter than 8 characters。这个提示第一次见会有点懵,但搞清楚之后你会发现,它并不是 Linux 在故意给你找别扭,而是 PAM(可插拔认证模块)在背后执行了一套默认的密码复杂度策略。这篇文章给你讲明白一条完整的链路:是谁拦下你的纯数字短密码,怎么修改配置把它放开,放开了之后又会带来哪些安全代价,以及万一改出问题怎么快速收场。
1. 默认策略到底是谁在执行:PAM 密码检查链路拆解
1.1 你执行 passwd 之后发生了什么
在大多数 Linux 发行版上,普通用户执行passwd、管理员执行passwd 用户名时,真正去改/etc/shadow的操作并不会立刻发生。passwd命令会先走一遍 PAM 堆栈,堆栈里堆着一串认证或策略模块,这些模块全部认可之后,密码才会落盘到/etc/shadow。
PAM 的配置文件一般放在/etc/pam.d/下,跟passwd这个服务对应的文件就叫/etc/pam.d/passwd。你可以执行下面这个命令看一下:
cat /etc/pam.d/passwd比较常见的内容结构类似这样:
#%PAM-1.0 @include common-password或者在某些发行版上会直接写:
password requisite pam_pwquality.so retry=3 password sufficient pam_unix.so obscure use_authtok sha512 shadow这两行是核心:第一行是“密码质量检查”,第二行才是真正把密码写入 shadow 文件的模块。如果你的系统上有@include common-password这种写法,那就说明passwd服务把公共的密码策略文件引了进来,真正设规则的地方是那个被引用的公共文件,比如/etc/pam.d/common-password或/etc/pam.d/system-auth。
1.2 pwquality 和 cracklib,到底是谁在管复杂度
不同发行版的密码策略模块有两个名字:pam_pwquality.so和pam_cracklib.so。你可以理解成pam_pwquality是较新、功能更完整的一版,pam_cracklib是老一代的替代品。大部分系统现在用的是pam_pwquality,但早期系统或者精简系统里依然能看到pam_cracklib的身影。
这两个模块主要负责检查新密码的长度、字符种类、连续重复、字典词匹配等风险项。默认参数通常包括:
minlen=8:最少 8 位;dcredit=0:默认不强制数字个数;ucredit=0:默认不强制大写字母个数;lcredit=0:默认不强制小写字母个数;ocredit=0:默认不强制特殊字符个数;difok=3:新密码与旧密码至少要有几个字符不同;dictcheck:拒绝明显的字典词和数字序列。
所以当你输入123456时,首先是minlen=8这一关就把你挡死了。即使你把minlen调低,123456这种连续数字序列也有可能被词典检查那一关拦下来。这些都是后面配置时要一起处理的问题。
1.3 配置文件与 PAM 参数:谁说了算
pam_pwquality模块的规则有两个来源:一是/etc/security/pwquality.conf这个专门放策略参数的配置文件;二是写在 PAM 堆栈里那一行pam_pwquality.so后面的参数。
优先级的规则是:PAM 堆栈里显式写的参数优先于pwquality.conf里的同名参数。比如你在堆栈里写minlen=8,那配置文件里写minlen = 6也不会生效。因此排查“我改了配置怎么还是不能设短密码”时,第一件事就得去翻 PAM 堆栈那一行,而不是只盯着配置文件。
2. 动手前的盘查:检查模块、认清入栈文件、做好备份
2.1 先确认系统用的是哪一套策略模块
在改任何配置之前,先用一条组合命令把当前系统所有涉及密码策略的文件和模块位置打印出来:
grep -R "pam_pwquality\|pam_cracklib" /etc/pam.d/这条命令会帮你定位到所有引用了密码质量模块的文件。不同发行版结果不太一样:
- 有的只在
/etc/pam.d/common-password里出现; - 有的集中在
/etc/pam.d/system-auth和/etc/pam.d/password-auth; - 还有一些可能散落在
login、sshd、gdm-password等具体服务文件里。
接着确认模块文件本身是否存在:
ls -l /lib/security/pam_pwquality.so 2>/dev/null || ls -l /lib/*/security/pam_pwquality.so 2>/dev/null如果提示找不到文件,说明系统里根本没有装密码质量检查模块,那你需要先安装对应包。Debian 系一般叫libpam-pwquality,Red Hat 系一般叫pam_pwquality或pam。没有这个模块,PAM 堆栈里的pam_pwquality.so配置行会直接报错,导致passwd根本无法使用。
2.2 别被“改 passwd 文件”这句话带偏
很多人搜资料时会看到“修改 /etc/pam.d/passwd”,然后照着改了,结果发现根本不生效。原因很简单:很多发行版的/etc/pam.d/passwd里写的只是@include common-password,真正起作用的规则在公共堆栈文件里。
所以在改之前,你要做的是:
- 先
cat /etc/pam.d/passwd确认引用关系; - 再打开被引用的
common-password或system-auth; - 如果同时存在
system-auth和password-auth,建议两个都改,因为图形登录、控制台登录、SSH 登录各自走的文件不一样,但在多数系统里都会归到这两套公共堆栈上。
打开之后,重点看两样东西:pam_pwquality.so这一行带了哪些参数,以及pam_unix.so后面有没有obscure这个选项。obscure会让pam_unix自己也做一些简单的弱口令判断,有时候pam_pwquality都放行了,结果又被它拦一道。
2.3 修改前备份三个文件
这一步不能省。密码策略文件一旦写错,轻则改不了密码,重则整个系统无法登录,特别是你人在远程操作的时候更危险。我习惯这样备份:
cp /etc/security/pwquality.conf /etc/security/pwquality.conf.bak cp /etc/pam.d/system-auth /etc/pam.d/system-auth.bak 2>/dev/null || true cp /etc/pam.d/common-password /etc/pam.d/common-password.bak 2>/dev/null || true备份完成后再开始改。如果后续改崩了,直接拷贝备份文件回去就能恢复,这是最稳妥的保底方案。
3. 真正放开六位纯数字密码:完整配置与验证流程
3.1 用 pwquality.conf 实现“一次放开”
大多数发行版都默认配置了/etc/security/pwquality.conf,模块会在加载时读取它。在文件末尾追加以下内容:
minlen = 6 dcredit = 0 ucredit = 0 lcredit = 0 ocredit = 0 difok = 0 minclass = 0 maxrepeat = 0 maxclassrepeat = 0 dictcheck = 0逐个解释这些参数的意义:
| 参数 | 值 | 作用 |
|---|---|---|
minlen | 6 | 允许的最短密码长度为 6 位 |
dcredit | 0 | 不要求必须包含数字,也不把数字当作长度奖励 |
ucredit | 0 | 不要求大写字母 |
lcredit | 0 | 不要求小写字母 |
ocredit | 0 | 不要求特殊字符 |
difok | 0 | 新密码可以不和旧密码有差异 |
minclass | 0 | 不要求密码涵盖多少种字符类别 |
maxrepeat | 0 | 允许连续重复字符,比如111111 |
maxclassrepeat | 0 | 允许整串密码都是同一类别字符 |
dictcheck | 0 | 不检查密码是否命中字典词或常见序列 |
这里最容易被忽略的是dictcheck = 0。如果你只把minlen改成 6,不加这一行,输入123456时有可能会被词典检查拦截,报错提示变成BAD PASSWORD: it is based on a dictionary word之类的信息。
还容易踩坑的是dcredit的正负号。我见过不少人从网上拷贝配置,看到的是dcredit = -1,那个值是“至少包含 1 位数字”的意思。你想放行纯数字密码,应该用0,不是-1。
3.2 如果系统不支持配置文件,直接改 PAM 行
有些精简系统或者自定义 PAM 堆栈的系统里,pam_pwquality.so那一行参数是写死的,配置文件里写了也不读。这时就需要直接编辑 PAM 堆栈,把模块参数加在那一行上。找到pam_pwquality.so那一行,改成:
password requisite pam_pwquality.so retry=3 minlen=6 dcredit=0 ucredit=0 lcredit=0 ocredit=0 minclass=0 difok=0 maxrepeat=0 maxclassrepeat=0 dictcheck=0如果你用的是老系统,模块是pam_cracklib.so,就把模块名换成对应的:
password requisite pam_cracklib.so retry=3 minlen=6 dcredit=0 ucredit=0 lcredit=0 ocredit=0 difok=0cracklib没有dictcheck参数,它内部会直接调用词典检查,所以老系统想放行123456可能会有反复。这种情况下最有效的办法是换用pam_pwquality,或者在pwquality.conf里把dictcheck关掉,同时确保 PAM 行里没有覆盖dictcheck的显式参数。
3.3 改完配置后,实测验证两个层面
配置改完不需要重启机器,PAM 配置是每次调用时重新读取的。但“能设置成功”和“能登进去”是两回事,所以我建议按下面的顺序验证:
第一步,设置密码:
passwd # 或者在管理员权限下 sudo passwd testuser输入两次六位纯数字密码,如果系统没有再弹BAD PASSWORD,说明策略这一关已经放行。但看到passwd: password updated successfully才算真正成功。
第二步,退出当前登录,用刚设置的纯数字密码重新登录一次:
su - testuser如果是从远程 SSH 测试,建议先保持当前的 root 会话不要断开,另开一个终端测试新密码登录,确认没问题再继续后续操作。
第三步,我还会顺便看一下/etc/shadow里对应用户的哈希是否更新了:
grep "^testuser:" /etc/shadow只要看到第二个字段不是空的哈希串,比如以$6$或$y$开头,就说明密码确实写进去了。这一步主要用于排查“系统提示成功但实际没写入”的异常情况。
4. 六位纯数字的安全账:熵值、破解速度和应用边界
4.1 先算一笔概率账
密码强度本质上是一个数学问题。六位纯数字,每一位有 10 种可能,组合总数就是 10 的 6 次方,也就是 100 万种。
100 万这个数字听起来不小,但在密码破解的场景里真的不算多。举个直观例子:如果攻击者每秒能尝试 10 次登录,理论上最坏情况只需要大约 28 小时就能把所有组合试完;如果每秒能尝试 100 次,几个小时就够。而本地拿到/etc/shadow哈希后,现代普通硬件跑哈希的速度早就超过每秒百万次,100 万种组合可能不到一秒就算完了。
所以六位纯数字密码本质上只适合安全性要求很低的场景,不能拿它硬扛暴力破解,更不能把这种配置用在暴露在公网的服务器上。
4.2 什么场景下才适合放开六位数字
根据我实际接触过的项目,比较合理的应用场景有这几类:
- 局域网内部测试机,物理环境可控,没有外人能接触;
- 嵌入式开发板、树莓派这类临时设备,主要为了方便调试;
- 批量初始化设备的临时账号,配合“首次登录必须改密”机制使用;
- 完全没有联网、只在本机控制台使用的环境。
不符合这些前提的场景,我不建议放开。尤其是根账号密码、SSH 登录密码、数据库账号密码,这些一旦用了六位纯数字,风险是非常明确的。
4.3 即便要放行,也建议保留最后一道保险
如果你确实需要在生产环境或者准生产环境暂时放行六位数字密码,我建议至少保证一点:这个密码只能一次性使用,用户下一次登录后必须强制修改。实现方式很简单:
chage -d 0 用户名执行这条命令后,该用户下次登录会被强制要求先设置新密码。这样你既完成了初始密码的下发,又不会让弱密码长期留在系统里。这个做法在批量开账号时很实用,既能照顾运维习惯,也能给安全审计一个交代。
5. 放行后容易翻车的细节:不生效、图形界面和应急恢复
5.1 改了半天还是不生效,按优先级排查这几处
第一次改这种配置的人,十个里有七八个会碰到“我改了,但passwd还是拒绝”。按我踩过的坑,最常见的原因排序如下:
第一,PAM 堆栈里的显式参数把配置文件顶掉了。比如system-auth里写的是pam_pwquality.so minlen=8,配置文件里写了minlen = 6也没用。解决办法就是直接改 PAM 行,把minlen=8改成minlen=6。
第二,改错了文件。passwd服务引用的公共堆栈,和你跑去改的某个无关配置文件不匹配。所以每次改完,我都用grep -R "pam_pwquality" /etc/pam.d/再扫一遍,确认改的位置确实在passwd引用的链路上。
第三,pam_unix.so后面的obscure参数没有处理。如果你在common-password或system-auth里看到这一行:
password sufficient pam_unix.so obscure use_authtok sha512 shadow里面的obscure会让pam_unix自己做一轮旧式复杂度检查,效果和pam_cracklib的检查部分重合。要彻底放行,可以把obscure从这一行去掉。这类问题很隐蔽,因为错误提示里不会告诉你具体是哪个模块拦下来的。
第四,系统里同时有多个公共堆栈。system-auth和password-auth各有一份,你只改了一个,但登录或改密时走的是另一个。两边都要检查。
5.2 命令行可以了,图形界面还不行
还有一类情况比较烦:passwd命令已经能成功设置六位数字密码了,但用户到图形登录界面点“修改密码”或者通过系统设置里的“用户”面板去改,还是会被拒绝。
这通常是因为桌面的“用户”管理走的是账户管理服务,它在改密时又套了一层自己的策略判断,这个策略依赖/etc/security/pwquality.conf。你前面只改了 PAM 堆栈,没改这个配置文件,桌面端自然不认。对策很简单:桌面端也统一在pwquality.conf里做一遍同样的放行设置,两边保持一致。
如果实在搞不定桌面这条链路,我的建议是干脆让用户统一用命令行passwd修改,或者管理员用sudo passwd 用户名直接帮他改。策略上允许放行之后,命令行方式是可控且稳定的。
5.3 配置改崩了,远程无法登录怎么救
这是最不希望碰到但必须提前准备的情况。PAM 文件里语法错误、模块参数非法,轻则改密失败,重则 SSH 登录时直接被拒。
我的应急预案只有两条原则:第一,改文件前保证手里已经打开了一个 root 终端,并且这个终端不是靠密码登录的,最好是通过密钥登录的 SSH 会话;第二,备份文件要放在手边,一旦发现有问题,立刻把备份覆盖回去。
如果系统已经被 PAM 问题锁在门外,而你还有物理控制台或者带外管理口,登录后执行:
cp /etc/pam.d/system-auth.bak /etc/pam.d/system-auth然后重启相关服务或重新登录即可。没有带外条件的时候,整台机器就只能强制重启进入单用户模式恢复,成本会高很多,所以备份和双会话是绝对不能省的。
6. 如果一定要用六位数字,这些配套措施能挽回一点安全分
6.1 给登录过程加上失败锁定
弱密码最怕的是被暴力破解,那就给暴力破解加一道闸。比较直接的办法是用失败锁定模块,在认证堆栈里加一行类似下面的配置:
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=300 auth required pam_faillock.so authfail audit deny=5 unlock_time=300具体加入的位置和系统认证堆栈有关,不同发行版差别很大,这里只摆出最核心的思路:同一用户连续登录失败 5 次后,锁定 5 分钟。这个机制能把在线暴力破解的效率压得非常低。即使不知道完整堆栈配置长什么样,用fail2ban这类工具也可以实现类似效果,看护 SSH 登录日志并自动封禁来源 IP。
6.2 能不用密码登录的服务就不要用密码
这句话听起来有点绕,但放在这里特别实际。如果你的服务器主要服务是 SSH,并且你担心六位数字密码太弱,最简单的做法是把 SSH 改成只允许密钥登录:
PermitRootLogin prohibit-password PubkeyAuthentication yes PasswordAuthentication no这样密码只作为本地控制台的一种备用认证方式,外部网络攻击面就大大缩小了。纯数字密码再弱,只要它不出现在网络登录流程里,风险就可控很多。
6.3 我个人的经验:放行策略要写进部署脚本,不要靠手改
最后说一个我自己的习惯。这种“放行六位数字密码”的配置,往往不是只改一台机器,而是要给一批设备做统一初始化。与其每次手动去改文件,不如把改配置、设密码、强制首次改密写成一条命令或者一个部署脚本,保持每一台设备的行为一致。
脚本大概长这样:
#!/bin/bash set -e PWQ=/etc/security/pwquality.conf cp "$PWQ" "$PWQ.bak" cat >> "$PWQ" <<'EOF' minlen = 6 dcredit = 0 ucredit = 0 lcredit = 0 ocredit = 0 difok = 0 minclass = 0 maxrepeat = 0 maxclassrepeat = 0 dictcheck = 0 EOF # 设置初始密码并强制首次登录修改 echo "testuser:123456" | chpasswd chage -d 0 testuser注意,chpasswd在很多系统上同样会走 PAM 策略检查,所以它必须放在pwquality.conf修改完成之后执行。脚本跑完以后,我再手动执行一次passwd验证一下,确认输出里不再有BAD PASSWORD,整套流程才算真正收工。
六位纯数字密码这件事,关键不在于系统允不允许,而在于你要清楚自己正在用它换什么。放行了方便,省了复杂度,就要提前想好防暴力破解的补丁打在哪个环节上。把这些配套措施都安排明白了,再用它,我心里才算踏实。