在Ubuntu系统中,/etc/login.defs文件是控制用户密码策略的核心配置文件,它直接决定了密码最大使用天数、最小使用天数、过期警告天数以及账户禁用天数等关键安全参数。默认情况下,Ubuntu 20.04及以上版本的login.defs中PASS_MAX_DAYS设为99999,PASS_WARN_AGE设为7,这意味着密码几乎不会过期,用户只会在过期前7天收到提醒。如果你想让系统强制用户定期更换密码并提前收到警告,就需要手动修改这个文件中的对应参数。下面我会从参数含义、修改方法、验证方式到安全建议,把这个话题彻底讲透。

login.defs文件的核心参数详解

login.defs位于/etc/login.defs,它是shadow-utils软件包提供的全局用户配置文件。这个文件中与密码过期直接相关的参数有以下几个:

PASS_MAX_DAYS:密码最大有效天数,超过这个天数后用户必须修改密码。默认值99999,基本等于不过期。

PASS_MIN_DAYS:两次密码修改之间的最小间隔天数,防止用户频繁改回旧密码。默认值0,表示随时可以改。

PASS_WARN_AGE:密码过期前多少天开始向用户发送警告提示。默认值7天。

PASS_MIN_LEN:密码最小长度,默认在Ubuntu中通常是6,但实际生效可能受PAM模块影响。

INACTIVE:账户过期后禁用的天数。如果设为-1则表示不禁用,设为正数则在密码过期后该天数内未登录就锁定账户。

你可以用以下命令查看当前文件内容:

cat /etc/login.defs

输出中你会看到类似这样的行:

PASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_WARN_AGE   7

如何修改密码过期天数和警告设置

修改login.defs需要root权限,使用你熟悉的编辑器打开文件:

sudo vim /etc/login.defs

或者用nano:

sudo nano /etc/login.defs

找到对应参数行,去掉前面的注释符号#(如果有的话),然后改成你想要的值。比如你希望密码每90天过期、提前14天警告:

PASS_MAX_DAYS   90
PASS_MIN_DAYS   1
PASS_WARN_AGE   14

这里PASS_MIN_DAYS设为1是为了防止用户当天改密码后立即又改回来,强制至少间隔一天。

保存退出后,修改对新创建的用户立即生效。但对于已经存在的用户,需要用chage命令单独设置,因为login.defs只影响新建账户的默认值。

用chage命令针对现有用户设置密码策略

chage命令是管理用户账户过期信息的专用工具,它会把信息写入/etc/shadow文件。查看某个用户当前的密码策略:

sudo chage -l username

输出示例:

Last password change                                    : May 15, 2025
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change           : 0
Maximum number of days between password change           : 99999
Number of days of warning before password expires        : 7

要修改现有用户的密码过期策略,比如设为90天过期、14天警告:

sudo chage -M 90 -m 1 -W 14 username

参数说明:-M是最大天数,-m是最小天数,-W是警告天数。如果想让账户在密码过期后30天不登录就锁定:

sudo chage -I 30 username

如果想强制用户下次登录就必须改密码:

sudo chage -d 0 username

这会把"上次修改密码日期"设为epoch(1970-01-01),系统会认为密码已经过期。

login.defs与PAM模块的关系和区别

很多人容易混淆login.defs和PAM(Pluggable Authentication Modules)的作用。login.defs是shadow-utils包的配置文件,主要影响useradd、usermod等命令创建或修改用户时的默认行为。而PAM模块中的pam_unix.so才是在用户实际登录时强制执行密码策略的组件。

PAM的密码策略配置在/etc/pam.d/common-password文件中,Ubuntu系统典型内容如下:

password    requisite     pam_pwquality.so retry=3
password    [success=1 default=ignore]      pam_unix.so obscure use_authtok try_first_pass sha512
password    requisite     pam_deny.so
password    required      pam_permit.so

如果你想从PAM层面控制密码复杂度(比如最小长度、字符种类要求),需要修改pam_pwquality.so的参数。但密码过期天数这个逻辑,主要还是由login.defs的默认值和chage的实际设置来控制。

需要特别注意:如果你只改了login.defs但没有改PAM中pam_unix.so的参数,某些情况下密码过期策略可能不会被严格执行。检查pam_unix.so是否包含相关参数:

grep pam_unix /etc/pam.d/common-password

确保pam_unix.so行没有被注释掉,并且包含sha512等加密方式。

企业级安全建议:密码策略的最佳实践

根据等保2.0和CIS Benchmark的建议,生产环境中的密码策略应该满足以下标准:

密码最大有效期不超过90天(高安全场景建议60天)。

密码最小有效期至少1天,防止循环使用旧密码。

过期警告天数设为14天,给用户充足的准备时间。

账户锁定策略:密码过期后30天内未登录则禁用账户。

密码最小长度至少12位,包含大小写字母、数字和特殊字符。

在Ubuntu上实现这些策略,除了修改login.defs,还需要配合PAM的pwquality模块。编辑/etc/security/pwquality.conf:

minlen = 12
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1

dcredit=-1表示至少1个数字,ucredit=-1至少1个大写,ocredit=-1至少1个特殊字符,lcredit=-1至少1个小写。

批量设置所有用户密码策略的方法

如果你管理的服务器有几十甚至上百个用户,逐个用chage设置显然不现实。可以写一个简单的脚本批量处理:

#!/bin/bash
# 批量设置所有普通用户的密码策略
for user in $(awk -F: '$3>=1000 && $3<60000 {print $1}' /etc/passwd); do
    echo "Setting policy for $user"
    chage -M 90 -m 1 -W 14 -I 30 "$user"
done

这个脚本会遍历所有UID在1000到60000之间的普通用户(排除系统账户),统一设置90天过期、1天最小间隔、14天警告、30天锁定。保存为set_policy.sh后执行:

sudo bash set_policy.sh

执行后可以用以下命令抽查几个用户确认生效:

sudo chage -l user1
sudo chage -l user2

常见问题排查和注意事项

修改login.defs后新用户自动继承新策略,但如果你发现新用户的密码策略还是旧值,检查是否有其他配置文件覆盖了默认值。某些情况下/etc/default/useradd也会影响useradd的行为,查看一下:

cat /etc/default/useradd

如果里面有INACTIVE或其他参数设置,可能会与login.defs产生冲突,以login.defs为准。

另外,如果系统启用了LDAP或AD域认证,本地的login.defs可能对域用户不生效,需要在域控端统一设置密码策略。

还有一个容易忽略的点:root用户的密码策略默认不受login.defs约束。要单独设置root的密码过期:

sudo chage -M 90 -m 7 -W 14 root

root的PASS_MIN_DAYS建议设长一些,比如7天,避免管理员频繁被强制改密码影响运维工作。

验证修改是否真正生效

修改完成后,创建一个测试用户来验证:

sudo useradd -m testuser
sudo passwd testuser

然后查看测试用户的策略:

sudo chage -l testuser

确认PASS_MAX_DAYS、PASS_WARN_AGE等参数是否符合预期。同时用testuser登录一次,系统应该会在接近过期时弹出警告信息。警告信息通常显示在登录时的终端提示中,内容类似"Your password will expire in X days"。

如果你想模拟密码即将过期的场景来测试警告是否正常工作,可以手动把测试用户的密码过期日期改成几天后:

sudo chage -d $(date -d "+5 days" +%Y-%m-%d) testuser

然后用testuser登录,应该能看到"Your password will expire in 5 days"的提示。

总结

Ubuntu系统中login.defs是密码过期策略的基础配置文件,但它只定义默认值,真正对现有用户生效需要配合chage命令。安全加固不是改一个参数就完事,需要login.defs、chage、PAM的pwquality模块三者协同配合。建议在生产环境中将密码最大天数控制在60到90天之间,警告天数设为14天,同时配合密码复杂度要求和账户锁定策略,才能构建一套完整的密码安全体系。定期用脚本审计所有用户的密码策略状态,是运维人员应该养成的习惯。