
1. 项目概述为什么需要账户锁定策略在Linux服务器特别是Ubuntu这类广泛用于生产环境的系统中账户安全是运维的第一道防线。想象一下你管理的服务器暴露在公网总有不怀好意的脚本小子尝试用“admin”、“root”、“123456”这类弱密码进行暴力破解。如果放任不管他们可以无限次尝试直到撞库成功你的数据和服务就危在旦夕了。账户锁定策略就是在多次连续输错密码后自动将账户临时或永久锁定的安全机制。这就像你家门锁连续输错几次密码锁芯就会暂时冻结防止有人拿万能钥匙一直试。在Ubuntu中这个功能并非系统默认强力开启需要我们手动配置。它主要依赖于一个名为PAMPluggable Authentication Modules可插拔认证模块的底层框架。PAM是Linux身份验证的“中央处理器”所有登录行为SSH、本地控制台、图形界面登录都要经过它。通过配置PAM我们可以精细地控制认证策略。本次要实现的就是利用PAM的pam_tally2模块在新系统中也可能是pam_faillock来构建一个可靠的账户登录失败防御体系。对于任何需要将Ubuntu服务器对外提供服务的管理员来说这都是一项必须掌握的基础安全加固技能。2. 核心组件与原理深度解析2.1 PAM框架安全策略的基石要玩转账户锁定必须先理解PAM。你可以把PAM想象成一个高度模块化的安检系统。当用户尝试登录时比如输入密码这个请求会先递交给PAM。PAM本身不判断密码对错它只负责协调流程按照预设的“安检程序”即PAM配置文件依次调用各个专业的“安检模块”如pam_unix.so验证密码pam_tally2.so计数失败次数。PAM的配置文件通常位于/etc/pam.d/目录下里面针对不同的服务有独立的配置例如common-auth通用认证、login本地终端登录、sshdSSH远程登录等。我们要修改的正是这些文件。模块的调用有四种控制标志required模块必须成功。即使失败也会等所有模块执行完才返回失败。requisite模块必须成功。一旦失败立即返回失败后续模块不再执行。sufficient模块成功则立即通过认证忽略后续的required模块。optional模块成功与否不影响整体认证结果。对于账户锁定我们通常使用required标志确保失败计数和锁定检查是强制性的环节。2.2 pam_tally2 模块的工作机制pam_tally2模块是实现计数和锁定的核心。它主要有两个功能计数在认证失败时对相应用户的失败次数进行累加。检查在认证开始时检查该用户的失败次数是否已超过阈值如果超过则直接拒绝本次登录尝试。它的工作依赖于一个“账本”文件默认是/var/log/faillog或/var/log/tallylog里面以二进制格式记录了每个用户的失败次数和最近失败时间。当失败次数达到我们设定的上限例如5次模块就会触发锁定。锁定有两种模式自动解锁锁定一段时间如600秒时间一到计数器清零或允许再次尝试。手动解锁锁定后必须由管理员使用pam_tally2命令手动重置计数器。这里有一个关键细节pam_tally2模块在配置时需要被调用两次。第一次在auth阶段检查账户密码之前用于“检查”是否已锁定第二次在account阶段或auth阶段失败后用于“计数”失败次数。顺序弄反了就会失效。注意在 Ubuntu 22.04 及更新版本中官方更推荐使用pam_faillock模块它功能更现代语法略有不同。但pam_tally2在旧版本和许多其他发行版中依然广泛使用原理相通。下文会以pam_tally2为例详解并在最后补充pam_faillock的配置差异。2.3 策略设计考量平衡安全与便利在配置前我们需要想清楚策略避免把自己锁在外面。失败次数阈值设为多少3次太敏感容易误锁10次又太宽松。对于服务器5-6次是常见选择。锁定时间是永久锁定直到管理员干预还是自动解锁生产环境通常建议自动解锁如10-30分钟既阻止了暴力破解又避免了因管理员遗忘而导致的服务账户永久不可用。但针对特别敏感的系统或特定用户如root可以考虑永久锁定并邮件告警。作用范围是锁定所有用户还是排除某些服务账户通常系统内置的非登录账户如www-data,mysql不需要此策略但所有可登录的普通用户和root都应覆盖。重置时机成功登录后失败计数器是否清零是的这是pam_tally2的默认行为这很合理。3. 详细配置步骤与实操下面我们以配置SSH服务和本地登录login为例演示完整的配置过程。假设我们的策略是连续失败5次后锁定账户600秒10分钟。3.1 环境准备与备份在修改任何PAM配置文件之前备份是铁律。打开终端执行sudo cp /etc/pam.d/common-auth /etc/pam.d/common-auth.backup sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.backup sudo cp /etc/pam.d/login /etc/pam.d/login.backup这样万一配置出错导致所有用户无法登录我们还可以通过恢复模式或单用户模式回滚备份文件。3.2 配置 SSH 登录锁定策略SSH是远程攻击的主要入口我们先加固它。编辑SSH服务的PAM配置sudo nano /etc/pam.d/sshd在文件的开头部分通常在include common-auth这行之前添加以下两行# 检查失败次数超过5次则拒绝访问 auth required pam_tally2.so deny5 unlock_time600 onerrsucceed file/var/log/tallylog # 统计登录失败次数仅在认证失败时计数 account required pam_tally2.so参数解析deny5失败次数阈值。unlock_time600锁定时间秒600秒10分钟。设置为0表示永久锁定直到手动重置。onerrsucceed即使模块内部出错如无法写入日志文件也让认证流程继续。这是一个安全兜底避免因模块自身问题导致所有人都无法登录。生产环境建议加上。file/var/log/tallylog指定记录失败次数的账本文件路径。配置顺序至关重要auth阶段的pam_tally2带参数必须在其他认证模块如pam_unix.so之前执行用于先行检查是否已锁定。account阶段的pam_tally2放在后面负责计数。保存并退出编辑器在nano中按CtrlX然后按Y最后回车。3.3 配置本地控制台登录锁定策略对于服务器本地的文本或图形化登录需要修改/etc/pam.d/login文件图形化登录如GDM可能涉及其他文件但原理类似。编辑文件sudo nano /etc/pam.d/login采用与sshd相同的配置在文件开头合适位置添加同样的两行。注意有些系统在login文件中已经存在一些pam_tally2行请先检查避免重复。3.4 配置通用认证策略可选但推荐为了确保策略覆盖所有通过PAM认证的服务如sudo、su等最好也修改/etc/pam.d/common-auth。但这里需要更小心因为影响面广。编辑文件sudo nano /etc/pam.d/common-auth找到以auth [success1 defaultignore]开头的那一行这是调用pam_unix.so的模块行。在这行之前插入我们的检查行auth required pam_tally2.so deny5 unlock_time600 onerrsucceed file/var/log/tallylog接着我们需要在account部分添加计数行。找到account相关的段落通常以account [defaultbad successok user_unknownignore] pam_unix.so结尾在这行之后添加account required pam_tally2.so3.5 手动管理锁定账户配置完成后我们需要掌握管理命令。查看所有用户失败次数sudo pam_tally2查看指定用户失败次数sudo pam_tally2 --user username手动解锁重置某个用户sudo pam_tally2 --user username --reset这个命令会将指定用户的失败计数清零立即解除锁定。重置所有用户的失败计数谨慎使用sudo pam_tally2 --reset3.6 针对 Ubuntu 22.04 的 pam_faillock 配置在新版Ubuntu中如果发现pam_tally2模块不存在或无效可以使用pam_faillock。编辑/etc/pam.d/common-auth在文件顶部添加auth required pam_faillock.so preauth silent deny5 unlock_time600 auth required pam_faillock.so authfail deny5 unlock_time600preauth在认证前检查authfail在认证失败后计数。编辑/etc/pam.d/common-account在文件末尾添加account required pam_faillock.so管理命令也变了查看状态sudo faillock --user username重置用户sudo faillock --user username --reset4. 配置验证与测试配置完不测试等于没做。务必在另一个活跃的SSH会话窗口进行测试防止把自己锁在外面导致失联。新建一个测试用户sudo adduser testlock设置一个简单的密码。在另一个终端或SSH窗口用错误密码尝试登录ssh testlock你的服务器IP连续输入错误密码5次。观察现象第5次失败后你应该会看到类似Account locked due to X failed logins的提示。第6次尝试时可能在输入密码前就直接被拒绝。验证锁定在服务器原会话中运行sudo pam_tally2 --user testlock会看到失败次数为5且账户被锁定。测试自动解锁等待10分钟或你设置的unlock_time再次尝试用正确密码登录应该可以成功。成功后再次查看计数应该被重置为0。测试手动解锁再次锁定测试账户后使用sudo pam_tally2 --user testlock --reset命令重置然后立即尝试登录应该成功。5. 常见问题、故障排查与进阶技巧5.1 常见问题速查表问题现象可能原因解决方案配置后所有用户包括root都无法登录1. PAM配置语法错误。2.onerrsucceed参数未加且日志文件不可写。3. 模块顺序错误导致检查逻辑死循环。1. 通过备份文件恢复仔细检查语法。2. 确保/var/log/tallylog文件存在且PAM进程有写权限通常属主root权限600。3. 确保auth阶段的检查行在pam_unix.so等认证模块之前。失败次数不累计或成功登录后不清零1.account阶段的pam_tally2行缺失或位置错误。2. 不同服务sshd, login使用了不同的日志文件导致计数不统一。1. 确认account required pam_tally2.so这行已正确添加到配置中。2. 在所有PAM配置文件中为pam_tally2指定相同的file路径。pam_tally2命令未找到或执行报错1. 系统未安装该模块。2. 在新版系统中被pam_faillock取代。1. 安装libpam-modules包sudo apt install libpam-modules。2. 切换到使用pam_faillock模块和faillock命令。锁定策略对某个特定用户不生效该用户可能被配置了nologinshell或者其登录方式绕过了PAM如密钥认证。SSH密钥认证确实不触发密码失败计数。确保测试时使用的是密码认证。检查用户shell是否为/sbin/nologin或/bin/false。5.2 故障排查心法如果遇到问题按以下顺序排查检查PAM调试日志在/etc/pam.d/sshd的模块行中添加debug参数如auth required pam_tally2.so deny5 unlock_time600 debug。然后通过sudo tail -f /var/log/auth.log观察SSH登录时的详细PAM流程信息。这是最强大的排错手段。检查系统日志/var/log/auth.log和/var/log/syslog是宝藏任何认证相关的错误都会记录在这里。使用grep pam_tally2 /var/log/auth.log或grep faillock来过滤关键信息。验证配置文件语法使用pam-auth-update命令可以交互式地管理一些通用PAM配置但对我们手动添加的行无效。更直接的是用pamtester工具模拟认证sudo apt install pamtester然后pamtester sshd username authenticate来测试。5.3 进阶技巧与最佳实践为root账户设置更严格的策略可以在配置中针对root用户单独设置更低的失败阈值如3次和更长的锁定时间甚至永久锁定然后通过其他方式如物理控制台、预先配置的授权密钥进行紧急解锁。结合Fail2ban实现IP封锁pam_tally2锁定的是用户账户。攻击者可以换一个用户名继续尝试。Fail2ban可以监控认证日志发现来自同一IP的多次失败后直接使用iptables封锁该IP地址一段时间实现用户IP的双重防护。设置报警通知编写一个简单的Shell脚本定期检查/var/log/tallylog或使用pam_tally2命令如果发现root用户或关键管理用户被锁定立即发送邮件或短信告警给管理员。将配置纳入版本管理将/etc/pam.d/目录下的关键配置文件纳入Git等版本控制系统。这样任何更改都有记录回滚也极其方便。注意Docker容器环境在容器内PAM通常不被使用或配置不同。容器安全应更多依赖于镜像安全、网络隔离和宿主机的安全策略而非容器内的账户锁定。账户锁定策略是一个“沉默的卫士”它不会每天刷存在感但能在关键时刻挡住绝大部分自动化密码爆破攻击。花半小时配置并测试好它是每个Linux系统管理员对自己和业务负责的基本体现。记住安全不是一个功能而是一个持续的过程从这样一个个扎实的基础配置开始。