CentOS系统的密码安全核心就两件事:一是密码必须足够复杂,不能用"123456"这种弱口令;二是密码必须定期更换,不能一个密码用到天荒地老。具体怎么做?通过修改/etc/login.defs和/etc/pam.d/system-auth文件,配合chage命令和pam_pwquality模块,就能把密码复杂度策略和过期轮换全部配置到位。下面我把每一步操作、每个参数含义、常见坑全部讲清楚。
一、为什么CentOS默认密码策略不够用
CentOS 7和CentOS 8默认的密码策略非常宽松。默认情况下,密码最短只有5位(CentOS 7),不强制要求大小写混合、数字、特殊字符,密码过期时间也很长甚至不强制过期。这意味着如果你装完系统不手动加固,攻击者用字典暴力破解几乎没有门槛。现实中大量服务器被入侵,第一步就是弱口令爆破。所以装完系统第一件事,就是把密码策略拉满。
二、密码复杂度策略配置——pam_pwquality模块详解
CentOS 7和CentOS 8都使用pam_pwquality(CentOS 7中叫pam_cracklib)来控制密码复杂度。配置文件路径是/etc/security/pwquality.conf(CentOS 7对应/etc/pam.d/system-auth中的pam_cracklib行)。
先看推荐的配置参数,直接编辑文件:
vim /etc/security/pwquality.conf
推荐写入以下内容:
# 密码最小长度,建议12位以上 minlen = 12 # 密码中至少包含一个小写字母 lcredit = 1 # 密码中至少包含一个大写字母 ucredit = 1 # 密码中至少包含一个数字 dcredit = 1 # 密码中至少包含一个特殊字符 ocredit = 1 # 密码中最多允许连续相同字符数 maxrepeat = 3 # 密码不能与用户名相同或包含用户名 usercheck = 1 # 密码不能是字典中的常见词 dictcheck = 1 # 新密码不能与旧密码太相似 difok = 8 # 拒绝使用字典中的词 enforcing = 1
每个参数解释一下:minlen=12意味着密码至少12个字符,这是目前安全基线的最低要求。lcredit、ucredit、dcredit、ocredit分别要求小写、大写、数字、特殊字符各至少一个。maxrepeat=3防止出现"aaa"这种连续重复。difok=8表示新密码和旧密码至少要有8个字符不同,防止用户只是改个数字就算换密码。enforcing=1是强制模式,不设这个值策略不生效。
CentOS 7用户需要改的是/etc/pam.d/system-auth文件,找到pam_cracklib.so那一行,改成类似这样:
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 difok=8
注意CentOS 7里lcredit=-1表示"至少需要1个小写字母",负数是"至少",正数是"最多允许额外的"。这和pwquality.conf的正数写法逻辑相反,别搞混了。
三、密码过期轮换策略——chage命令与login.defs配置
密码过期策略分两层:一层是系统级默认值,在/etc/login.defs里设置;另一层是针对具体用户的单独设置,用chage命令。
先改系统级默认配置:
vim /etc/login.defs
关键参数修改如下:
# 密码最长有效天数,建议90天 PASS_MAX_DAYS 90 # 密码最短有效天数,防止用户改了马上又改回来,建议1天 PASS_MIN_DAYS 1 # 密码过期前多少天开始警告用户,建议14天 PASS_WARN_AGE 14 # 密码过期后账户锁定天数,建议7天 INACTIVE 7
PASS_MAX_DAYS=90意味着用户最多90天必须换一次密码。PASS_MIN_DAYS=1防止用户刚换完密码立刻又换回去绕过历史记录。PASS_WARN_AGE=14是提前两周提醒用户要换密码了。INACTIVE=7是密码过期后7天不改就锁定账户。
对于已经存在的用户,需要用chage命令单独设置:
# 查看当前用户密码过期信息 chage -l username # 设置密码最长90天、最短1天、过期前14天警告 chage -M 90 -m 1 -W 14 username # 强制用户下次登录必须修改密码 chage -d 0 username # 锁定某个用户(比如离职员工) chage -E 2024-12-31 username
chage -d 0这个命令非常实用,设置后用户下次登录会被强制要求修改密码,适合新用户首次登录或者管理员想强制全员换密码的场景。
四、root账户的特殊加固
root账户是最高权限,必须单独加强。首先建议禁止root远程登录,改用普通用户登录后sudo提权。如果必须允许root登录,至少做到:
# 查看root密码过期状态 chage -l root # 给root设置严格的过期策略 chage -M 60 -m 7 -W 10 -I 3 root
这里-I 3表示账户被锁定3次后就永久禁用(需要配合pam_tally2或faillock模块)。-M 60表示root密码60天必须换一次,比普通用户更短。
另外在/etc/securetty中限制root只能从特定终端登录,在/etc/ssh/sshd_config中设置PermitRootLogin prohibit-password(只允许密钥登录,禁止密码登录)。
五、密码历史记录——防止重复使用旧密码
很多人换密码就是把"Password1!"改成"Password2!",这种换法等于没换。需要配置密码历史记录,让系统记住用户最近用过的密码,不允许重复使用。
在/etc/pam.d/system-auth中添加或修改:
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok remember=12
remember=12表示记住最近12次密码,新密码不能和这12次中任何一次相同。CentOS 8默认用的是sha512加密,比CentOS 7的sha512更安全。如果你还在用md5,赶紧换掉,md5已经被证明不安全了。
六、登录失败锁定策略——防暴力破解
光有密码复杂度还不够,还得防暴力破解。CentOS 8用faillock,CentOS 7用pam_tally2。配置登录失败锁定:
# CentOS 8 vim /etc/security/faillock.conf # 添加: deny = 5 unlock_time = 1800 # 在/etc/pam.d/system-auth和system-auth-ac中添加: auth required pam_faillock.so preauth silent deny=5 unlock_time=1800 auth sufficient pam_faillock.so authfail deny=5 unlock_time=1800 account required pam_faillock.so # CentOS 7 vim /etc/pam.d/system-auth # 添加: auth required pam_tally2.so deny=5 unlock_time=1800 even_deny_root account required pam_tally2.so
deny=5表示连续输错5次密码就锁定账户,unlock_time=1800表示锁定30分钟后自动解锁。even_deny_root确保root也受这个限制。
七、验证配置是否生效
配置完了必须验证。创建一个测试用户试一下:
useradd testuser passwd testuser # 尝试设置一个弱密码,比如"abc",看系统是否拒绝 # 然后设置一个符合策略的密码,比如"Abc@2024#Test!"
然后用chage -l testuser查看过期策略是否正确,用chage -l root看root的策略。再故意输错几次密码测试锁定是否生效。这些验证步骤不能省,配置错了等于没配。
八、常见问题与避坑指南
第一,改完配置不要立刻把自己锁在外面。建议先开一个备用终端窗口测试,确认没问题再关掉旧的。第二,如果你用的是LDAP或AD统一认证,本地的/etc/login.defs和pam配置可能不生效,需要在认证服务器端统一配置。第三,密码策略太严会导致用户把密码写在便利贴上贴显示器旁边,反而更不安全,所以要在安全性和可用性之间找平衡,一般12位复杂度+90天过期是比较合理的基线。
第四,CentOS 7和CentOS 8的配置文件路径和模块名称有差异,不要把CentOS 8的配置直接复制到CentOS 7上用,会报错。第五,修改完PAM配置后如果系统无法登录,可以通过单用户模式进入修复,不要慌。
九、总结与建议
CentOS密码安全不是改一个文件就完事的,它是一套组合拳:pam_pwquality管复杂度,login.defs管过期周期,chage管具体用户,faillock管暴力破解,密码历史管重复使用。这五个层面缺一不可。建议企业环境中把这些配置做成Ansible脚本或基线模板,新服务器上线自动应用,避免人工配置遗漏。同时配合SSH密钥认证、防火墙策略、定期审计日志,才能真正把CentOS服务器的安全水位拉上去。
