拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Ubuntu 22.04企业级密码策略实战:基于PAM构建系统安全防线

1. 项目概述为什么企业级密码策略是系统安全的基石在任何一个稍有规模的企业IT环境中服务器密码管理都是安全防线的第一道关口。我见过太多因为密码策略松懈而引发的安全事件从员工使用“123456”或“password”作为root密码到离职员工账户未被及时禁用再到密码长期不更换导致被暴力破解。这些看似低级的问题往往就是安全堤坝上最致命的蚁穴。Ubuntu 22.04 LTS作为当前长期支持的主流服务器发行版其内置的PAMPluggable Authentication Modules可插拔认证模块框架为我们提供了构建这道防线的强大工具箱。PAM不是一个单一的命令或配置文件而是一套完整的、模块化的认证体系。它允许系统管理员在不修改应用程序源代码的情况下灵活地定制认证流程。简单来说当用户尝试登录无论是通过SSH、控制台还是图形界面、使用sudo命令甚至修改密码时PAM都在后台默默地工作决定这次操作是否被允许。本指南的目的就是带你深入PAM的腹地从零开始在Ubuntu 22.04上搭建一套符合企业安全基线要求的密码策略。这不仅仅是修改几个参数而是理解其背后的安全逻辑并构建一个可管理、可审计、可扩展的认证体系。无论你是管理着几十台服务器的小团队运维还是负责数百节点基础设施的资深管理员一套严谨的密码策略都是你不可或缺的核心技能。2. 核心需求解析与企业安全基线设计在动手配置之前我们必须明确要解决什么问题。一套好的密码策略绝不是密码越复杂、更换越频繁就越好。过于严苛的策略会导致用户频繁忘记密码反而增加运维负担甚至促使用户将密码写在便签纸上造成更大的安全隐患。我们的目标是在安全性与可用性之间找到最佳平衡点。2.1 企业级密码策略的六大核心要素结合CIS互联网安全中心基准、NIST美国国家标准与技术研究院指南以及国内等级保护要求我们可以梳理出以下六个必须控制的维度密码复杂度要求防止用户设置过于简单的密码。这包括最小长度、字符类别要求大小写字母、数字、特殊符号以及禁止使用常见弱密码或与用户名相关的密码。密码历史与重复使用限制防止用户在新旧密码之间来回切换。系统需要记住最近N次使用过的密码并禁止用户再次使用它们。密码最长与最短使用期限最短使用期限防止用户在被迫修改密码后立即又改回原来的老密码。例如设置密码修改后24小时内不能再次修改。最长使用期限强制用户定期更换密码降低密码因长期使用而被泄露或破解的风险。通常建议为90天。密码过期前警告在密码即将过期前如7天主动提醒用户给予充足的更换时间避免突然失效导致业务中断。账户锁定策略应对暴力破解攻击。当连续多次认证失败如5次后临时锁定该账户一段时间如15分钟以阻止自动化攻击脚本。密码加密算法确保存储在系统中的密码哈希值足够强健能够抵御彩虹表等破解手段。Ubuntu默认使用yescrypt这已经是目前非常安全的算法。2.2 方案选型为什么是pam_pwquality和pam_tally2PAM有众多模块我们需要选择合适的“积木”来搭建策略。对于密码复杂度历史上有pam_cracklib和pam_pwquality两个主要模块。在Ubuntu 22.04上pam_pwquality是更现代、功能更强大的替代品它由libpwquality库提供支持提供了更精细的控制和更好的错误信息。对于账户锁定我们选择pam_tally2模块。它比旧的pam_tally功能更完善可以分别统计和锁定tty本地控制台和remote如SSH的失败登录并且管理起来更方便。注意在Ubuntu 22.04的某些版本或配置中pam_tally2可能默认未安装。如果遇到问题可以回退使用pam_faillock它是另一个现代且功能强大的账户锁定模块但配置语法略有不同。本指南以pam_tally2为例因为它更直观。我们的整体思路是通过pam_pwquality控制密码的“质量”创建和修改时的规则通过pam_tally2控制认证的“行为”登录失败处理再结合PAM的其他核心模块和系统文件形成一个完整的策略闭环。3. 环境准备与PAM架构深度解析在开始配置前我们需要对操作环境和工作原理有清晰的认识。这不是一次可以随意回滚的桌面实验任何配置错误都可能导致所有用户包括你自己无法登录系统。3.1 操作前的绝对安全准则必须在维护窗口进行不要在业务高峰期操作。提前通知所有用户。必须保持至少两个活跃的SSH会话在第一个会话中执行修改用第二个会话始终保持着登录状态作为“逃生通道”。在第二个会话中测试su或sudo确认策略生效且不会锁死自己后再关闭它。必须备份原始配置文件这是你的救命稻草。sudo cp /etc/pam.d/common-password /etc/pam.d/common-password.backup sudo cp /etc/pam.d/common-auth /etc/pam.d/common-auth.backup sudo cp /etc/login.defs /etc/login.defs.backup使用虚拟机或非生产环境先行测试强烈建议在VirtualBox或VMware中克隆一个测试环境完整演练一遍。3.2 理解PAM的配置文件结构与工作流程PAM的配置文件位于/etc/pam.d/目录下每个需要认证的服务都有一个对应的文件如sshd,sudo,login。但为了集中管理Ubuntu使用了“include”的方式。我们主要修改的是以下几个文件/etc/pam.d/common-password负责密码修改相关的策略passwd命令。/etc/pam.d/common-auth负责身份验证相关的策略登录、sudo等。/etc/pam.d/common-account负责账户管理相关的策略账户是否过期、是否在允许登录时间段内等。每个PAM配置文件由一行行的“规则”组成。每一行定义了一个模块、控制标志、模块参数。控制标志是理解PAM行为的关键required模块必须成功。如果失败最终会失败但会等所有模块执行完才返回失败。requisite模块必须成功。如果失败立即返回失败后续模块不再执行。安全性更高常用于关键检查。sufficient模块成功即足以通过认证除非前面有required失败。如果失败则忽略继续后续检查。optional模块成功与否通常不影响结果。一个典型的common-password文件片段如下password requisite pam_pwquality.so retry3 password [success1 defaultignore] pam_unix.so obscure use_authtok try_first_pass yescrypt password requisite pam_deny.so password required pam_permit.so我们来拆解第一行password管理类别表示这条规则用于“密码管理”服务。requisite控制标志表示这个模块必须成功否则立即失败。pam_pwquality.so调用的PAM模块。retry3传递给模块的参数表示用户有3次机会输入符合要求的密码。工作流程当用户执行passwd命令时PAM会按顺序执行common-password文件中的规则。首先用pam_pwquality.so检查新密码的复杂度如果失败立即终止。如果通过则执行下一行pam_unix.so模块使用yescrypt算法将密码哈希并写入/etc/shadow文件。4. 实战配置构建企业级密码复杂度策略现在我们开始核心配置。首先处理密码复杂度这是防御弱密码的第一道防线。4.1 安装与配置pam_pwquality模块安装必要的软件包sudo apt update sudo apt install libpam-pwquality -y安装后系统会自动在/etc/pam.d/common-password中插入对pam_pwquality.so的调用。主配置文件/etc/security/pwquality.conf这是pam_pwquality的核心配置文件。我们可以直接编辑它而不是将大量参数写在PAM文件里这样更清晰。sudo vim /etc/security/pwquality.conf下面是一个符合企业级要求的配置示例每一行我都加了注释# 最小密码长度设置为12位是当前安全实践的一个良好起点 minlen 12 # 要求密码中至少包含一个大写字母 (A-Z) ucredit -1 # 要求密码中至少包含一个小写字母 (a-z) lcredit -1 # 要求密码中至少包含一个数字 (0-9) dcredit -1 # 要求密码中至少包含一个特殊字符 (!#$%^*等) ocredit -1 # 密码中相同字符连续出现的最大次数防止如“aaa”这样的简单序列 maxrepeat 2 # 检查新密码是否包含用户名的正向或反向序列。0为不检查1为检查。 usercheck 1 # 检查新密码是否包含/etc/passwd中用户全名GECOS字段中的单词 enforce_for_root # 对root用户也强制执行此策略这很重要 # 密码中相同类别的字符如全是数字允许的最大连续长度 maxclassrepeat 3 # 拒绝包含在字典文件中的单词。字典文件路径可以自定义。 dictcheck 1 # 拒绝包含与旧密码有太多相同字符的新密码 difok 8参数详解credit类参数ucredit,lcredit,dcredit,ocredit负数表示至少需要的数量-1表示至少1个正数表示最多给予的“信用分”已过时不建议使用正数。difok默认是5表示新密码中至少要有5个字符与旧密码不同。我设置为8要求更高的差异性。验证配置配置完成后无需重启任何服务策略立即生效。打开一个新的终端尝试为一个普通用户修改密码测试策略# 切换到你要测试的用户不要用当前登录的会话 su - testuser # 修改密码 passwd尝试输入简单密码如password123你会看到类似错误BAD PASSWORD: The password fails the dictionary check - it is too simplistic/systematic尝试输入TestUser2024!如果用户名为testuser可能会看到BAD PASSWORD: The password contains the user name in some form这表明我们的复杂度策略和用户检查已经生效。4.2 配置密码历史与有效期策略密码复杂度管“创建”密码历史管“轮回”。我们需要防止用户在新旧密码之间“仰卧起坐”。配置密码历史记忆这需要修改/etc/pam.d/common-password文件在pam_unix.so模块行添加remember参数。sudo vim /etc/pam.d/common-password找到包含pam_unix.so的那一行它可能看起来像这样password [success1 defaultignore] pam_unix.so obscure use_authtok try_first_pass yescrypt在行末添加remember5表示系统会记住最近5次使用的密码哈希。修改后如下password [success1 defaultignore] pam_unix.so obscure use_authtok try_first_pass yescrypt remember5实操心得remember参数的工作原理是在/etc/security/opasswd文件中存储旧密码的哈希值。确保这个文件的权限是600-rw-------属主为root。你可以通过sudo ls -l /etc/security/opasswd检查。配置密码有效期密码有效期通过/etc/login.defs文件和一个系统命令chage来管理。全局默认设置编辑/etc/login.defs。sudo vim /etc/login.defs修改以下关键参数# 密码的最大有效期天90天是常见策略 PASS_MAX_DAYS 90 # 密码的最小有效期天防止频繁修改设为2天 PASS_MIN_DAYS 2 # 密码过期前多少天开始警告用户 PASS_WARN_AGE 7 # 以下参数保持默认或根据需要调整 # PASS_MIN_LEN 12 # 这个已被pam_pwquality的minlen覆盖可不设或保持注释为用户设置特定策略login.defs中的设置只对新创建的用户生效。对于系统中已存在的用户包括root需要使用chage命令手动修改。# 查看用户testuser当前的密码策略 sudo chage -l testuser # 为testuser设置策略与全局一致 sudo chage -M 90 -m 2 -W 7 testuser # 为root用户设置策略安全要求应更高 sudo chage -M 90 -m 2 -W 7 rootchage命令参数解释-M 90: 最大使用天数90天。-m 2: 最小使用天数2天。-W 7: 过期前7天警告。5. 实战配置实现智能账户锁定与失败处理密码策略的另一面是防御主动攻击。账户锁定策略就是在有人尝试暴力破解时自动拉响警报并封锁入口。5.1 配置pam_tally2进行失败登录锁定我们将修改/etc/pam.d/common-auth文件在认证栈的开头添加pam_tally2模块进行计数在栈的末尾添加另一个pam_tally2模块进行重置认证成功时。编辑/etc/pam.d/common-authsudo vim /etc/pam.d/common-auth在文件开头部分通常在auth required pam_deny.so之前添加以下两行# 对认证失败进行计数连续失败5次则锁定600秒10分钟同时禁止root用户通过远程SSH被锁定deny_root auth required pam_tally2.so onerrfail deny5 unlock_time600 even_deny_root root_unlock_time600在文件末尾部分在所有auth规则之后添加重置计数的一行# 认证成功后重置该用户的失败计数 auth required pam_tally2.so reset参数深度解析onerrfail: 当模块内部出现错误如无法写入日志时视为认证失败。deny5: 连续认证失败次数阈值。超过则锁定。unlock_time600: 锁定时间单位秒600秒10分钟。自动解锁。even_deny_root: 对root用户也实施锁定。这是一个重要的安全加固但请务必确保你有其他可用的root权限访问方式如物理控制台、已登录的另一个root会话。root_unlock_time600: root用户的锁定时间。reset: 这个实例的模块只做一件事——当用户成功认证后将其失败计数器归零。管理锁定账户配置完成后失败计数会记录在/var/log/tallylog文件中。查看所有用户失败次数sudo pam_tally2查看特定用户失败次数sudo pam_tally2 --user testuser手动解锁一个被锁定的用户例如在误操作或紧急情况下sudo pam_tally2 --user testuser --reset5.2 测试账户锁定策略这是非常关键的一步务必在测试用户或虚拟机上操作。打开两个SSH终端终端A保持一个有效的登录会话作为逃生舱。在终端B尝试用错误的密码登录测试账户5次。ssh testuseryour_server_ip # 连续输入错误密码5次第6次尝试时即使输入了正确的密码也会被拒绝并提示类似“Account locked due to X failed logins”的信息。等待10分钟或你设置的unlock_time或者使用sudo pam_tally2 --user testuser --reset手动解锁后再尝试用正确密码登录应该可以成功。成功后再次查看计数应该已被重置为0。踩坑记录pam_tally2的计数是针对“认证组件”的。如果你在common-auth中配置那么ssh、login、sudo等所有引用该文件的服务的失败次数会累加。但有时su命令可能使用独立的PAM配置/etc/pam.d/su需要单独添加pam_tally2规则才能统一计数这点需要根据你的实际管理需求调整。6. 高级策略与集成考量基础策略搭建完成后我们可以考虑一些更精细化的控制让整个认证体系更贴合企业实际运维场景。6.1 为SSH单独配置更严格的策略有时我们希望SSH登录有更严格的限制比如更短的锁定时间或不同的失败阈值。我们可以不修改全局的common-auth而是单独编辑/etc/pam.d/sshd。备份并编辑SSHD的PAM配置sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.backup sudo vim /etc/pam.d/sshd在include common-auth这一行之前插入自定义的pam_tally2规则。这样SSH服务会先使用我们自定义的严格规则然后再走通用的common-auth规则其中也有pam_tally2但由于控制标志和顺序自定义的会优先或共同生效具体逻辑需测试。一个更清晰的做法是在sshd中覆盖设置并注释掉include common-auth中关于锁定的行需谨慎。更简单的做法是直接为SSH设置独立计数文件# 在文件开头添加 auth required pam_tally2.so file/var/log/tallylog.ssh deny3 unlock_time300 even_deny_rootfile参数指定了独立的计数日志文件这样SSH的失败次数就不会和本地登录混在一起。6.2 与LDAP/AD等中央认证系统集成在企业中用户账户通常存储在LDAP如OpenLDAP或Active Directory中。PAM同样可以与之集成。使用pam_ldap或sssd对于LDAP传统方式是pam_ldap但更现代、功能更全的是sssd(System Security Services Daemon)。sssd作为一个守护进程可以缓存凭证并在网络断开时提供离线登录体验更好。配置关键当使用中央认证时密码策略复杂度、历史、有效期最好在目录服务器如AD域控制器上统一设置因为PAM的pam_pwquality和pam_unix主要管理本地/etc/shadow中的密码。如果让PAM来检查LDAP用户的密码配置会非常复杂且容易出错。账户锁定策略pam_tally2锁定的是本地系统的认证尝试。即使账户在AD上被锁定只要本地pam_tally2计数器没超PAM可能依然会尝试去AD认证这会返回错误。更佳实践是结合使用pam_tally2提供第一层本地防御防止暴力破解冲击你的服务器同时依赖AD本身的账户锁定策略。6.3 密码策略的例外与豁免处理没有任何策略能一刀切。总会有一些特殊情况服务账户用于跑应用、定时任务的非交互式账户。这些账户不应该有密码过期策略否则会导致服务中断。处理方法是使用chage -M -1 service_account将最大天数设为-1永不过期并为其设置一个非常复杂的强密码或使用密钥认证。紧急访问账户俗称“break-glass account”。这个账户的密码可以设置得很复杂且永不过期平时禁用登录usermod -L或passwd -l仅在紧急情况下由授权人员启用。其密码应密封保存在保险柜或安全的密码管理器中。7. 策略验证、审计与日常维护配置不是终点持续的验证和审计才能保证策略有效运行。7.1 系统性的策略验证清单部署完成后请执行以下检查密码复杂度测试# 切换到非特权测试用户 sudo -u testuser passwd # 尝试设置短密码、简单密码、包含用户名的密码确认被拒绝。 # 尝试设置符合要求的复杂密码确认成功。密码历史测试sudo -u testuser passwd # 成功修改密码为NewPass1! sudo -u testuser passwd # 立即尝试改回旧密码应被拒绝。 # 连续修改密码5次用不同的新密码第6次尝试使用第一次的密码应被拒绝。账户锁定测试如前所述使用错误密码触发锁定验证锁定时间和手动解锁功能。密码过期测试需等待或模拟# 将测试用户密码设为立即过期 sudo chage -d 0 testuser # 下次该用户登录时系统会强制要求更改密码。 # 测试过期前警告需将警告时间设短如1分钟然后等待 sudo chage -W 1 testuser # 用户登录时应看到类似“Warning: your password will expire in 1 day”的消息。7.2 关键日志监控与审计安全策略的效力体现在日志中。你需要定期检查相关日志认证日志/var/log/auth.log是PAM和SSH等认证相关日志的核心。使用grep或journalctl进行筛选。# 查看所有失败的登录尝试 sudo grep -i failed password /var/log/auth.log # 查看账户锁定事件 sudo grep -i locked\|pam_tally2 /var/log/auth.log # 使用journalctlsystemd系统 sudo journalctl -u ssh --since today | grep -i failpam_tally2计数文件定期检查/var/log/tallylog查看哪些账户经常被锁定这可能是攻击迹象也可能是用户需要培训。密码修改日志密码修改成功或失败也会记录在auth.log中。sudo grep -i password changed\|passwd /var/log/auth.log7.3 自动化合规检查脚本示例可以编写一个简单的Shell脚本定期运行并报告策略合规状态例如检查关键用户的密码过期时间。#!/bin/bash # check_password_policy.sh echo 密码策略合规检查报告 echo 检查时间: $(date) echo # 1. 检查关键系统账户密码是否永不过期这通常是合规要求 CRITICAL_USERSroot for user in $CRITICAL_USERS; do max_days$(sudo chage -l $user | grep Maximum | awk -F: {print $2} | tr -d ) if [ $max_days ! 99999 ] [ $max_days ! -1 ]; then echo [警告] 关键账户 $user 的密码未设置为永不过期 (当前: $max_days 天)。 else echo [正常] 关键账户 $user 的密码策略符合要求。 fi done echo # 2. 检查是否有账户密码即将过期例如7天内 WARNING_DAYS7 echo --- 密码将在 $WARNING_DAYS 天内过期的账户 --- sudo chage -l $(getent passwd | cut -d: -f1) 2/dev/null | awk -v warn$WARNING_DAYS BEGIN {user; max0; last0} /^[^[:space:]]/ {if(user max0 last0 lastwarn) print user : last 天后过期; user$0; max0; last0} /Maximum/ {max$2} /Last password change/ {split($0, a, /:/); date %s -d \ a[2] \ | getline change; date %s | getline now; if(max0) lastint((change max*86400 - now)/86400);} | grep -v 天后过期$ | sort -nk2 echo echo 检查完成 将脚本保存并添加执行权限放入cron定期执行输出结果可以发送邮件给管理员。8. 常见问题排查与修复实录在实际操作中你几乎一定会遇到问题。下面是我总结的几个典型场景和解决方法。8.1 问题配置后所有用户包括root无法登录或sudo现象修改PAM配置后退出当前会话发现无法通过SSH或控制台登录提示认证失败。甚至当前已登录的会话执行sudo也失败。原因这是最危险的错误通常是因为在/etc/pam.d/common-auth或/etc/pam.d/common-password中配置语法错误、模块路径错误或者添加的规则与控制标志required,requisite的组合导致了认证流程被意外阻断。紧急修复步骤如果你还有已登录的会话不要退出当前的救命会话使用备份文件恢复配置sudo cp /etc/pam.d/common-auth.backup /etc/pam.d/common-auth sudo cp /etc/pam.d/common-password.backup /etc/pam.d/common-password立刻测试认证功能是否恢复sudo -v # 测试sudo su - testuser # 测试切换用户如果恢复备份后问题依旧可能是其他文件如/etc/pam.d/sshd被误改。逐一检查恢复。如果已完全锁死物理服务器通过IPMI、iDRAC、iLO等带外管理工具连接虚拟控制台以单用户模式或救援模式启动系统挂载根分区并修复PAM配置。云服务器如AWS EC2, Azure VM大多数云平台提供了“串行控制台”或“运行命令”功能。例如在AWS EC2上你可以使用EC2 Serial Console或SSH通过Session Manager如果之前已配置来访问系统。如果都不行可能需要停止实例将其根卷挂载到另一个临时实例上进行修复。根本预防永远遵循“测试-备份-修改-验证”的流程。先在测试机操作并在生产环境修改前备份。8.2 问题密码复杂度策略对某些用户不生效现象为普通用户设置了密码复杂度但root用户修改自己密码时或者通过sudo passwd username为其他用户修改密码时策略似乎被绕过了。原因与解决root用户绕过默认情况下root用户为自己修改密码不受pam_pwquality限制。需要在/etc/security/pwquality.conf中明确设置enforce_for_root参数如前文配置所示。管理员为其他用户修改密码当root或sudo用户执行passwd username时PAM栈可能不同。确保/etc/pam.d/common-password中的pam_pwquality.so行没有使用[success... defaultignore]这类过于宽松的控制标志并且其控制标志是requisite或required。一个可靠的配置是使用requisite这样任何不符合复杂度要求的密码修改都会立即被拒绝。8.3 问题账户锁定后即使等待锁定时间结束也无法登录现象用户触发锁定等待了超过unlock_time设置的时间后仍然无法登录。排查步骤检查计数文件sudo pam_tally2 --user username。看看失败次数是否真的清零了。有时系统时间不同步或日志写入问题可能导致计数器未正确重置。手动重置使用sudo pam_tally2 --user username --reset手动清零。检查系统时间使用date命令检查服务器时间是否准确。如果服务器时间被大幅向前或向后调整可能会影响锁定时间的计算。检查PAM配置顺序确保pam_tally2 reset行被放置在common-auth文件所有auth模块的最后。如果顺序不对可能在成功认证后没有执行重置操作。8.4 问题密码过期后用户无法通过非交互方式更改密码现象用户密码过期通过SSH登录时被强制要求更改密码但一些自动化脚本或基于密码的CI/CD流水线会因此中断。解决方案对于自动化脚本尽可能使用SSH密钥认证彻底避免密码问题。对于必须使用密码的场景可以使用chpasswd或usermod命令由管理员非交互式地修改密码。# 使用chpasswd密码需要是明文 echo username:newStrongPassword | sudo chpasswd # 使用usermod密码需要是加密后的哈希值可以用openssl或mkpasswd生成 sudo usermod -p $(openssl passwd -6 newStrongPassword) username安全警告这种方法会在命令行历史或脚本中留下密码痕迹存在安全风险。应确保脚本权限严格并及时清理历史记录或考虑使用Ansible Vault等加密工具来管理密码。8.5 问题如何将密码策略应用到sudo密码验证现象配置了密码复杂度但使用sudo时输入密码似乎没有应用复杂度策略。说明这是正常的。sudo命令验证的是用户的当前密码而不是设置新密码。密码复杂度策略 (pam_pwquality) 只在修改密码passwd命令时触发。sudo的密码验证走的是common-auth中的认证流程只检查密码是否正确以及是否触发了账户锁定 (pam_tally2)。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门