linux服务器配置密码复杂度和有效期

表格17条

服务器未配置密码复杂度和密码有效期,可能会被设置为弱口令和长时间使用,恶意人员可能通过猜解或暴力破解口令非法登录。Web服务器 (172.22.3.2) 数据库服务器1 (172.22.3.129) 数据库服务器2 (172.22.3.130) 应用服务器 (172.22.3.131) Web服务器 (172.22.3.3) 数据库服务器 (172.22.3.133) 应用服务器1 (172.22.3.134) 应用服务器2 (172.22.3.135)建议Linux服务器在/etc/pam.d/system-auth配置文件中配置密码最小长度为8位,引用pwquality.so模块,配置密码必须由大小写字母、数字、特殊字符中三种或三种以上, 密码有效期为90天。

手动配置步骤:

一、安装必要的软件包
# 检查是否已安装 pwquality
rpm -qa | grep libpwquality
# 如果未安装,执行安装
yum install -y libpwquality

二、配置密码复杂度要求
1. 编辑 `/etc/pam.d/system-auth`
# 备份原文件
cp /etc/pam.d/system-auth /etc/pam.d/system-auth.bak.$(date +%F)
# 编辑文件
vim /etc/pam.d/system-auth

2. 修改 `password requisite` 行
找到类似这样的行:
password   requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=

**替换为:**
password   requisite     pam_pwquality.so try_first_pass retry=3 authtok_type= minlen=8 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1 minclass=3 enforce_for_root

同步修改 `/etc/pam.d/password-auth`
# 备份
cp /etc/pam.d/password-auth /etc/pam.d/password-auth.bak.$(date +%F)
# 直接复制 system-auth 的配置
cp /etc/pam.d/system-auth /etc/pam.d/password-auth

三、配置 pwquality 详细参数
# 编辑 `/etc/security/pwquality.conf`
# 备份
cp /etc/security/pwquality.conf /etc/security/pwquality.conf.bak.$(date +%F)
# 编辑文件
vim /etc/security/pwquality.conf

### 添加或修改以下内容:

# 密码最小长度 8 位
minlen = 8
# 至少包含 1 个小写字母(-1 表示至少 1 个)
#lcredit = -1
# 至少包含 1 个大写字母
#ucredit = -1
# 至少包含 1 个数字
#dcredit = -1
# 至少包含 1 个特殊字符
#ocredit = -1
# ✅ 不强制要求每种字符类型,只要求至少 3 种即可
# 至少包含 3 种字符类型(小写、大写、数字、特殊字符)
minclass = 3
# 新密码中最多有 3 个字符与旧密码相同
difok = 3
# 禁止使用用户名
usercheck = 1
# 禁止使用字典单词
dictcheck = 1


四、配置密码有效期 90 天
### 方法 1:修改 `/etc/login.defs`(全局默认)
# 备份
cp /etc/login.defs /etc/login.defs.bak.$(date +%F)

# 编辑文件
vim /etc/login.defs
### 修改以下参数:
# 密码最大有效期(90 天)
PASS_MAX_DAYS   90
# 密码最小修改间隔(0 表示随时可改)
PASS_MIN_DAYS   0
# 密码过期前提前警告天数(7 天)
PASS_WARN_AGE   7
# 密码最小长度(这里设置 8,但主要由 pwquality 控制)
PASS_MIN_LEN    8

### 方法 2:对已存在的用户修改密码策略
# 查看当前用户密码策略
chage -l root
# 为现有用户设置密码有效期 90 天
chage -M 90 root

# 批量修改所有普通用户(UID >= 1000)
for user in $(awk -F: '$3>=1000 && $3!=65534 {print $1}' /etc/passwd); do
  chage -M 90 -m 1 -W 7 "$user"
   echo "已设置用户 $user 的密码策略"
done


五、参数说明
PAM 模块参数:
| 参数 | 说明 | 示例 |
|------|------|------|
| `minlen=8` | 密码最小长度 8 位 | `minlen=8` |
| `dcredit=-1` | 至少包含 1 个数字 | `-1` 表示至少 1 个 |
| `ucredit=-1` | 至少包含 1 个大写字母 | `-1` 表示至少 1 个 |
| `lcredit=-1` | 至少包含 1 个小写字母 | `-1` 表示至少 1 个 |
| `ocredit=-1` | 至少包含 1 个特殊字符 | `-1` 表示至少 1 个 |
| `minclass=3` | 至少包含 3 种字符类型 | 小写、大写、数字、特殊字符中至少 3 种 |
| `retry=3` | 密码设置失败后重试次数 | 最多重试 3 次 |
| `remember=5` | 记住最近 5 次密码,防止重复使用 | 在 `pam_unix.so` 行配置 |
### login.defs 参数:
| 参数 | 说明 | 推荐值 |
|------|------|--------|
| `PASS_MAX_DAYS` | 密码最大有效期(天) | `90` |
| `PASS_MIN_DAYS` | 两次修改密码的最小间隔(天) | `1` |
| `PASS_WARN_AGE` | 密码过期前警告天数 | `7` |
| `PASS_MIN_LEN` | 密码最小长度(被 pwquality 覆盖) | `8` |
## 六、验证配置
### 1. 测试密码复杂度
# 创建测试用户
useradd testuser
# 尝试设置不符合规则的密码
passwd testuser


**测试案例:**
| 密码 | 是否通过 | 原因 |
|------|---------|------|
| `123456` | ❌ | 长度不足 8 位 |
| `12345678` | ❌ | 只有数字,未满足 3 种字符类型 |
| `Abcd1234` | ❌ | 没有特殊字符,只有 3 种字符类型(需要特殊字符) |
| `Abcd@123` | ✅ | 包含大写、小写、数字、特殊字符,满足 minclass=3 |
| `Test@123` | ✅ | 符合所有要求 |
| `testuser` | ❌ | 包含用户名 |
### 2. 检查密码有效期

# 查看用户密码策略
chage -l testuser

# 预期输出:
# Last password change                                   : Dec 15, 2024
# Password expires                                       : Mar 15, 2025 ← 90 天后
# Password inactive                                       : never
# Account expires                                         : never
# Minimum number of days between password change         : 1
# Maximum number of days between password change         : 90
# Number of days of warning before password expires     : 7

### 3. 验证 PAM 模块加载
# 检查 pwquality 模块
grep pam_pwquality.so /etc/pam.d/system-auth

自动化脚本

/tmp/password_policy_centos7.sh

#!/bin/bash
#########################################################################
# Script Name: password_policy_centos7.sh
# Description: CentOS 7.9 密码复杂度和有效期配置脚本(修正版)
# Author: zhangpeng
# Date: 2026-1-12
# Version: 2.1
# Changes:
#   - 密码复杂度为"至少 3 种字符类型"
#   - 移除强制 4 种字符类型的限制
#########################################################################

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

# 日志函数
log_info() {
   echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
   echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
   echo -e "${RED}[ERROR]${NC} $1"
}

log_step() {
   echo -e "${BLUE}[STEP]${NC} $1"
}

# 检查是否为 root 用户
check_root() {
   if [ "$(id -u)" -ne 0 ]; then
      log_error "此脚本必须以 root 用户运行!"
       exit 1
   fi
}

# 检查系统版本
check_system() {
   if [ ! -f /etc/redhat-release ]; then
      log_error "此脚本仅支持 CentOS/RHEL 系统!"
       exit 1
   fi
   
  local version=$(cat /etc/redhat-release | grep -oP '(?<=release )\d+')
   if [ "$version" != "7" ]; then
      log_warn "检测到系统版本为 $version,此脚本专为 CentOS 7.9 设计"
      read -p "是否继续执行?(y/n): " choice
       if [ "$choice" != "y" ]; then
           exit 0
       fi
   fi
}

# 获取普通用户列表
get_normal_users() {
   awk -F: '$3>=1000 && $3!=65534 {print $1":"$3":"$6}' /etc/passwd
}

# 显示普通用户列表
show_normal_users() {
  local users=$(get_normal_users)
   
   if [ -z "$users" ]; then
      log_warn "系统中没有普通用户(UID >= 1000)"
      return 1
   fi
   
   echo ""
   echo -e "${CYAN}=========================================="
   echo -e " 检测到的普通用户列表"
   echo -e "==========================================${NC}"
  printf "%-20s %-10s %-30s\n" "用户名" "UID" "家目录"
   echo "------------------------------------------------------------------"
   
   while IFS=: read -r username uid homedir; do
      printf "%-20s %-10s %-30s\n" "$username" "$uid" "$homedir"
   done <<< "$users"
   
   echo "------------------------------------------------------------------"
  local user_count=$(echo "$users" | wc -l)
   echo -e "总计: ${GREEN}$user_count${NC} 个普通用户"
   echo ""
   
  return 0
}

# 安装必要软件包
install_packages() {
  log_step "步骤 1/5: 检查并安装必要软件包..."
   
   if rpm -qa | grep -q libpwquality; then
      log_info "libpwquality 已安装"
   else
      log_info "正在安装 libpwquality..."
      yum install -y libpwquality
       if [ $? -eq 0 ]; then
          log_info "libpwquality 安装成功"
       else
          log_error "libpwquality 安装失败"
           exit 1
       fi
   fi
}

# 备份配置文件
backup_configs() {
  log_step "步骤 2/5: 备份原配置文件..."
   
  local backup_dir="/root/password_policy_backup_$(date +%Y%m%d_%H%M%S)"
   mkdir -p "$backup_dir"
   
  local files=(
       "/etc/pam.d/system-auth"
       "/etc/pam.d/password-auth"
       "/etc/security/pwquality.conf"
       "/etc/login.defs"
  )
   
   for file in "${files[@]}"; do
       if [ -f "$file" ]; then
           cp "$file" "$backup_dir/"
          log_info "已备份: $file -> $backup_dir/"
       fi
   done
   
  log_info "备份目录: $backup_dir"
}

# ✅ 修改后的 PAM 配置
configure_pam() {
  log_step "步骤 3/5: 配置 PAM 密码复杂度策略..."
   
   # 配置 system-auth
  log_info "配置 /etc/pam.d/system-auth..."
   
   # 删除旧的 pam_pwquality.so 行
   sed -i '/^password.*pam_pwquality.so/d' /etc/pam.d/system-auth
   
   # ✅ 只使用 minclass=3,不强制每种字符类型
   sed -i '/^password/i\password   requisite     pam_pwquality.so try_first_pass retry=3 authtok_type= minlen=8 minclass=3 enforce_for_root' /etc/pam.d/system-auth
   
   # 删除重复行
   awk '!seen[$0]++' /etc/pam.d/system-auth > /tmp/system-auth.tmp
   mv /tmp/system-auth.tmp /etc/pam.d/system-auth
   
   # 移除 remember 参数(如果存在)
   sed -i 's/\s*remember=[0-9]*//g' /etc/pam.d/system-auth
   
   # 同步到 password-auth
  log_info "同步配置到 /etc/pam.d/password-auth..."
   cp /etc/pam.d/system-auth /etc/pam.d/password-auth
   
  log_info "PAM 配置完成"
}

# ✅ 修改后的 pwquality 配置
configure_pwquality() {
  log_step "步骤 4/5: 配置 /etc/security/pwquality.conf..."
   
   cat > /etc/security/pwquality.conf << 'EOF'
# Configuration for systemwide password quality limits

# Number of characters in the new password that must not be present in the old password.
difok = 3

# Minimum acceptable size for the new password
minlen = 8

# ✅ 不强制要求每种字符类型,只要求至少 3 种即可
# The maximum credit for having digits in the new password.
# dcredit = 1

# The maximum credit for having uppercase characters in the new password.
# ucredit = 1

# The maximum credit for having lowercase characters in the new password.
# lcredit = 1

# The maximum credit for having other characters in the new password.
# ocredit = 1

# The minimum number of required classes of characters for the new password
# ✅ 至少 3 种字符类型(大写、小写、数字、特殊字符)
minclass = 3

# Whether to check for the words from the passwd entry GECOS string of the user
usercheck = 1

# Whether to check for the words from the cracklib dictionary
dictcheck = 1

# Enforces pwquality checks on the root user password.
enforce_for_root
EOF

  log_info "pwquality.conf 配置完成"
}

# 配置密码有效期
configure_password_aging() {
  log_step "步骤 5/5: 配置密码有效期策略..."
   
  log_info "配置 /etc/login.defs..."
   
   sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS   90/' /etc/login.defs
   sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS   0/' /etc/login.defs
   sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE   7/' /etc/login.defs
   
   if ! grep -q "^PASS_MIN_LEN" /etc/login.defs; then
       echo "PASS_MIN_LEN   8" >> /etc/login.defs
   else
       sed -i 's/^PASS_MIN_LEN.*/PASS_MIN_LEN   8/' /etc/login.defs
   fi
   
  log_info "login.defs 配置完成"
   
  log_info "为 root 用户设置密码有效期..."
  chage -M 90 -m 0 -W 7 root
  log_info "重置 root 密码修改时间为今天..."
  chage -d $(( $(date +%s) / 86400 )) root
  log_success "已对 root 用户应用密码策略并设置有效期90天"

   
  local users=$(get_normal_users)
   
   if [ -z "$users" ]; then
      log_warn "未找到普通用户(UID >= 1000),跳过普通用户配置"
      return
   fi
   
   echo ""
  show_normal_users
   
   echo -e "${YELLOW}是否为以上普通用户配置密码有效期?${NC}"
   echo " [1] 是 - 为所有普通用户配置密码有效期 90 天"
   echo " [2] 否 - 跳过普通用户配置(仅配置 root)"
   echo " [3] 自定义 - 手动选择要配置的用户"
   echo ""
  read -p "请选择 [1-3]: " user_choice
   
  case $user_choice in
       1)
          log_info "为所有普通用户设置密码有效期..."
          local user_count=0
           while IFS=: read -r username uid homedir; do
              chage -M 90 -m 0 -W 7 "$username"
              log_info " ✓ 已设置用户: $username"
              ((user_count++))
           done <<< "$users"
          log_info "共设置 $user_count 个普通用户的密码有效期"
          ;;
       2)
          log_warn "已跳过普通用户密码有效期配置"
          ;;
       3)
          configure_selected_users "$users"
          ;;
      *)
          log_warn "无效选择,跳过普通用户密码有效期配置"
          ;;
   esac
}

# 为选定的用户配置密码有效期
configure_selected_users() {
  local users="$1"
   
   echo ""
  log_info "请输入要配置密码有效期的用户名,多个用户用空格分隔"
  log_info "可用用户: $(echo "$users" | cut -d: -f1 | tr '\n' ' ')"
   echo ""
  read -p "用户列表: " selected_users
   
   if [ -z "$selected_users" ]; then
      log_warn "未选择任何用户,跳过配置"
      return
   fi
   
  local configured_count=0
  local failed_users=""
   
   for username in $selected_users; do
       if echo "$users" | grep -q "^${username}:"; then
          chage -M 90 -m 0 -W 7 "$username"
          log_info " ✓ 已设置用户: $username"
          ((configured_count++))
       else
          log_warn " ✗ 用户 $username 不存在或不是普通用户,跳过"
           failed_users="$failed_users $username"
       fi
   done
   
   echo ""
  log_info "成功配置 $configured_count 个用户的密码有效期"
   
   if [ -n "$failed_users" ]; then
      log_warn "以下用户配置失败:$failed_users"
   fi
}

# 验证配置

verify_configuration() {
   echo ""
  log_step "===== 配置验证 ====="
   echo ""
   
   echo -e "${BLUE}[1] PAM 配置:${NC}"
   grep pam_pwquality.so /etc/pam.d/system-auth
   echo ""
   
   echo -e "${BLUE}[2] pwquality 配置:${NC}"
   cat /etc/security/pwquality.conf | grep -v '^#' | grep -v '^$'
   echo ""
   
   echo -e "${BLUE}[3] 密码有效期配置:${NC}"
   grep PASS_ /etc/login.defs | grep -v '^#'
   echo ""
   
   echo -e "${BLUE}[4] root 用户密码策略:${NC}"
  chage -l root || chage -l root | grep -E "(Last password change|Password expires|Maximum number|Minimum number|Number of days of warning)"
   echo ""
   
   echo -e "${BLUE}[5] 已配置密码有效期的普通用户:${NC}"
  local users=$(get_normal_users)
   if [ -n "$users" ]; then
       echo ""
      printf "%-20s %-15s %-15s %-15s\n" "用户名" "最大有效期" "最小间隔" "警告天数"
       echo "---------------------------------------------------------------"
       while IFS=: read -r username uid homedir; do
          local max_days=$(chage -l "$username" | grep "Maximum" | awk -F: '{print $2}' | xargs)
          local min_days=$(chage -l "$username" | grep "Minimum" | awk -F: '{print $2}' | xargs)
          local warn_days=$(chage -l "$username" | grep "warning" | awk -F: '{print $2}' | xargs)
           
           if [ "$max_days" = "90" ]; then
              printf "%-20s %-15s %-15s %-15s\n" "$username" "$max_days" "$min_days" "$warn_days"
           fi
       done <<< "$users"
       echo ""
   else
      log_info "无普通用户"
       echo ""
   fi
}

# 测试密码复杂度
test_password_policy() {
   echo ""
  log_step "===== 密码复杂度测试 ====="
   echo ""
   
  read -p "是否进行密码复杂度测试?(y/n): " do_test
   if [ "$do_test" != "y" ]; then
      log_info "跳过测试"
      return
   fi
   
  local test_user="testpwd_$(date +%s)"
   
  log_info "创建测试用户: $test_user"
  useradd "$test_user"
   
   echo ""
  log_info "请为测试用户设置密码,建议测试以下密码:"
   echo " ✅ Abcd1234     (3种: 大写+小写+数字)"
   echo " ✅ [O_GtbyX     (3种: 大写+小写+特殊字符)"
   echo " ✅ test@123     (3种: 小写+数字+特殊字符)"
   echo " ✅ Test@123     (4种: 大写+小写+数字+特殊字符)"
   echo " ❌ 123456       (1种: 只有数字)"
   echo " ❌ abcdefgh     (1种: 只有小写)"
   echo " ❌ Test123       (2种: 大写+小写+数字,但只有2种)"
   echo ""
   
  passwd "$test_user"
   
   echo ""
  log_info "查看测试用户密码策略:"
  chage -l "$test_user"
   
   echo ""
  read -p "是否删除测试用户 $test_user?(y/n): " do_delete
   if [ "$do_delete" = "y" ]; then
      userdel -r "$test_user" 2>/dev/null
      log_info "已删除测试用户: $test_user"
   else
      log_warn "保留测试用户: $test_user"
      log_warn "手动删除命令: userdel -r $test_user"
   fi
}

# 显示配置摘要
show_summary() {
   echo ""
   echo "=========================================="
  log_info "配置完成摘要"
   echo "=========================================="
   echo ""
   echo "✅ 密码复杂度要求:"
   echo "   - 最小长度: 8 位"
   echo "   - 字符类型: 至少 3 种(大写、小写、数字、特殊字符)"
   echo "   - 示例密码:"
   echo "     • Abcd1234       (大写+小写+数字)"
   echo "     • [O_GtbyX       (大写+小写+特殊字符)"
   echo "     • test@123       (小写+数字+特殊字符)"
   echo "     • Test@123       (大写+小写+数字+特殊字符)"
   echo "   - 禁止使用: 用户名、字典单词"
   echo "   - 对 root 生效: 是"
   echo "   - 历史密码限制: 无"
   echo ""
   echo "✅ 密码有效期策略:"
   echo "   - 最大有效期: 90 天"
   echo "   - 最小修改间隔: 0 天 (随时可改)"
   echo "   - 过期前警告: 7 天"
   echo ""
   echo "✅ 已生效用户:"
   echo "   - root 用户: 已设置"
   
  local users=$(get_normal_users)
  local configured_count=0
   if [ -n "$users" ]; then
       while IFS=: read -r username uid homedir; do
          local max_days=$(chage -l "$username" | grep "Maximum" | awk -F: '{print $2}' | xargs)
           if [ "$max_days" = "90" ]; then
              ((configured_count++))
           fi
       done <<< "$users"
   fi
   
  local total_users=$(echo "$users" | wc -l)
  [ -z "$users" ] && total_users=0
   
   echo "   - 普通用户: $configured_count/$total_users 个已配置"
   echo ""
   echo "=========================================="
}

# 显示未配置的用户
show_unconfigured_users() {
  local users=$(get_normal_users)
   
   if [ -z "$users" ]; then
      return
   fi
   
  local unconfigured_users=""
   
   while IFS=: read -r username uid homedir; do
      local max_days=$(chage -l "$username" | grep "Maximum" | awk -F: '{print $2}' | xargs)
       if [ "$max_days" != "90" ]; then
           unconfigured_users="$unconfigured_users $username"
       fi
   done <<< "$users"
   
   if [ -n "$unconfigured_users" ]; then
       echo ""
      log_warn "以下普通用户未配置密码有效期:"
       echo "   $unconfigured_users"
       echo ""
      log_info "如需配置,可手动执行:"
       for user in $unconfigured_users; do
           echo "   chage -M 90 -m 0 -W 7 $user"
       done
   fi
}

# 主函数
main() {
   echo "=========================================="
   echo " CentOS 7.9 密码复杂度配置脚本 v2.1"
   echo "=========================================="
   echo ""
   
  check_root
  check_system
   
   echo ""
  read -p "即将开始配置,是否继续?(y/n): " confirm
   if [ "$confirm" != "y" ]; then
      log_info "用户取消操作"
       exit 0
   fi
   
   echo ""
   
  install_packages
  backup_configs
  configure_pam
  configure_pwquality
  configure_password_aging
  verify_configuration
  test_password_policy
  show_summary
  show_unconfigured_users
   
  log_info "所有配置已完成!"
  log_warn "建议重启系统后再次验证配置"
}

main "$@"

配置后验证清单

# ✅ 检查 PAM 配置
grep pam_pwquality.so /etc/pam.d/system-auth
# ✅ 检查 pwquality 配置
cat /etc/security/pwquality.conf | grep -v '^#' | grep -v '^$'
# ✅ 检查密码有效期
grep PASS_ /etc/login.defs | grep -v '^#'
# ✅ 检查root用户密码策略
chage -l root

# ✅ 测试密码复杂度(创建测试用户)
useradd testpwd
passwd testpwd  # 尝试输入 Test@123
# ✅ 检查用户密码策略
chage -l testpwd
# 为单个用户配置密码有效期
chage -M 90 -m 0 -W 7 username
# 批量配置多个用户
for user in user1 user2 user3; do
  chage -M 90 -m 0 -W 7 "$user"
   echo "已配置用户: $user"
done
# ✅ 清理测试用户
userdel -r testpwd
image-20260112162303384

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部