
1. 项目概述从“门锁”到“保险柜”的服务器安全观每次和运维同行聊起服务器安全大家的第一反应往往是“防火墙配好了吗”、“端口关了吗”。这没错防火墙就像是服务器的大门把守着网络层面的第一道防线。但今天我想聊点更深层的当攻击者已经站在了你的“家门口”甚至拿到了一个低权限的账户你靠什么阻止他登堂入室答案很可能就藏在最基础、也最容易被忽视的密码策略和其背后的PAMPluggable Authentication Modules可插拔认证模块机制里。我们花大价钱部署了WAF、IDS却常常对系统自带的、免费的、且威力巨大的认证安全模块视而不见。一个弱密码足以让所有外围防御形同虚设。这个项目就是一次对Linux服务器认证体系的内核级加固实战。它不仅仅是修改几个密码复杂度参数而是通过PAM模块构建一套从密码强度、登录尝试限制、到会话管理的立体化认证防线。我会带你从原理到实操一步步拆解如何让你的服务器安全从“装了个好门锁”升级到“配备了生物识别、动态密码和入侵警报的智能保险柜”。2. 核心需求解析为什么防火墙之后密码策略是命门在深入技术细节前我们必须先达成一个共识安全是一个链条其强度取决于最薄弱的一环。防火墙和网络策略解决了“谁能敲门”的问题而PAM和密码策略解决的是“谁有钥匙以及钥匙怎么用”的问题。2.1 认证环节的典型攻击场景想象一下这些场景它们每天都在互联网的阴影下发生暴力破解攻击者利用自动化工具对SSH、FTP、Web登录接口等进行海量用户名/密码组合尝试。如果密码简单如123456、password、公司名年份被攻破只是时间问题。密码喷洒与暴力破解相反攻击者使用几个常用密码如Summer2024!,Welcome1去碰撞大量的用户名。这种攻击针对那些有统一弱密码策略的组织尤其有效。凭证填充利用从其他网站泄露的账号密码库在目标服务器上尝试登录。很多人习惯在不同平台使用相同密码导致一处泄露全网遭殃。会话劫持与持久化攻击者通过某种方式获取了一个有效的会话或者植入了一个后门账户试图维持其访问权限。一个健壮的密码策略和PAM配置正是为了系统性地应对上述威胁。它的核心需求可以归纳为三点提高密码的猜测难度、增加连续猜测的成本和风险、监控和限制异常认证行为。2.2 传统密码策略的局限性很多管理员对密码策略的理解还停留在/etc/login.defs里修改一下PASS_MAX_DAYS密码最长有效期和PASS_MIN_LEN密码最小长度。或者使用chage命令管理一下用户密码过期时间。这些措施是必要的但远远不够。它们存在几个关键短板被动且静态只在密码创建或修改时检查无法应对实时的暴力破解攻击。缺乏智能响应无法根据登录失败频率、来源IP等动态信息做出反应如临时封禁。维度单一主要关注密码本身长度、复杂度对认证过程如尝试频率、时间、地点控制力弱。无法深度集成难以与其他安全工具如日志分析系统、入侵检测系统进行灵活联动。而这正是PAM模块大显身手的地方。PAM将认证过程模块化、可编程化允许我们以极高的灵活度定义“一次成功的登录究竟需要满足多少条件”。3. PAM模块深度解析Linux认证的万能插座理解PAM是进行一切高级认证配置的前提。你可以把它想象成服务器认证系统的一个“万能插座板”。3.1 PAM是什么架构与流程PAM的核心思想是将应用程序如login,sshd,su与具体的认证机制如密码、指纹、令牌解耦。应用程序不再需要关心用户是用密码登录还是用密钥登录它只需要向PAM库发起一个请求“请帮我认证这个用户。” PAM则根据一套预定义的规则配置文件调用一系列模块来完成认证工作。一个典型的PAM认证流程涉及四种模块类型按顺序执行auth认证核实用户身份。例如提示输入密码并与/etc/shadow中的哈希值比对。account账户检查账户本身是否有效。例如账户是否过期、当前时间是否允许登录、是否达到最大用户数限制。password密码负责更新用户的认证令牌如修改密码。session会话在用户认证成功前后进行会话管理和资源设置。例如记录登录日志、挂载用户目录、设置环境变量。PAM的配置文件通常位于/etc/pam.d/目录下每个需要认证的服务都有一个对应的文件如/etc/pam.d/sshd,/etc/pam.d/login。文件由一行行的“规则”组成每条规则定义了在什么条件下调用哪个模块。3.2 关键PAM模块介绍在安全加固中我们会频繁使用以下几个核心模块pam_unix.so / pam_pwquality.so (旧版为pam_cracklib.so)这是密码复杂度检查的基石。pam_pwquality是pam_cracklib的增强版提供了更精细的密码策略控制如必须包含的字符类别、拒绝常见弱密码等。pam_tally2.so这是防御暴力破解的利器。它能够统计用户登录失败的次数并在达到阈值后锁定账户一段时间。注意在一些新发行版如较新的Fedora、RHEL 8中pam_faillock模块正在取代pam_tally2两者功能类似但配置方式略有不同下文会分别说明。pam_limits.so限制用户会话所能使用的系统资源如最大进程数、打开文件数、内存等。这可以防止单个用户或被攻陷的账户发起资源耗尽攻击。pam_time.so基于时间的访问控制可以限制用户只能在特定时间段如工作日的工作时间登录。pam_access.so基于主机名、IP地址或终端类型的访问控制类似于/etc/hosts.allow和/etc/hosts.deny但集成在PAM流程中更加灵活。pam_lastlog.so显示用户上次登录的时间和地点有助于用户发现账户异常。pam_securetty.so限制root用户只能从安全的终端tty登录通常禁止root通过网络如ssh直接登录这是一个非常重要的安全实践。理解每个模块的作用就像拿到了工具箱里不同功能的工具。接下来我们看看如何用这些工具来搭建我们的安全体系。4. 立体化密码与认证策略实战配置理论说得再多不如一行配置。下面我们进入实战环节我会以最常见的CentOS 7/RHEL 7使用pam_tally2和Ubuntu 20.04/RHEL 8使用pam_faillock为例进行对比演示。请根据你的系统选择对应的路径。4.1 第一层防御强化密码本身pam_pwquality目标强制用户设置高强度密码从源头上减少被猜解的可能。首先确保系统安装了libpwquality工具和PAM模块# CentOS/RHEL sudo yum install libpwquality # Ubuntu/Debian sudo apt install libpam-pwquality主要的配置文件是/etc/security/pwquality.conf。你可以直接编辑这个文件或者通过pam_pwquality模块的参数在PAM配置中指定。我推荐直接修改配置文件因为它更集中、清晰。编辑/etc/security/pwquality.conf以下是一些关键参数及其建议值# 密码最小长度建议至少12位 minlen 12 # 至少包含一个大写字母 (A-Z) minclass 1 # 或者更精细地控制 # dcredit -1 # 至少1位数字 # ucredit -1 # 至少1位大写字母 # lcredit -1 # 至少1位小写字母 # ocredit -1 # 至少1位特殊字符 # 拒绝包含用户名的密码正向和反向 usercheck 1 # 拒绝包含pass等常见弱词汇的密码 badwords deny_words.txt # 需要自己创建这个字典文件 # 新密码与旧密码至少需要不同的字符数 difok 8 # 拒绝与/etc/passwd中GECOS字段用户全名等相似的密码 gecoscheck 1 # 密码中相同字符连续出现的最大次数 maxrepeat 3 # 检查密码是否是回文 palindrome 1实操心得minlen的设置需要平衡安全性与可用性。对于内部系统12位是较好的起点。difok参数非常重要它能防止用户只在旧密码后加个数字就了事。usercheck和gecoscheck能有效防止社交工程类密码。配置好后需要在PAM的密码管理栈中启用它。编辑/etc/pam.d/system-auth对于RHEL系或/etc/pam.d/common-password对于Debian系找到关于pam_pwquality.so的行。在RHEL 7上它通常已经存在password requisite pam_pwquality.so try_first_pass local_users_only retry3 authtok_type确保这行没有被注释且包含retry3允许3次重试等参数。注意修改密码策略不会强制现有用户立即更改密码。你需要结合chage命令来管理。例如强制所有用户下次登录时修改密码sudo chage -d 0 用户名。或者设置密码最长有效期sudo chage -M 90 用户名。4.2 第二层防御动态阻击暴力破解pam_tally2 与 pam_faillock目标在密码可能被猜中的“过程中”进行干预锁定攻击源。方案A针对使用pam_tally2的系统如CentOS 7配置PAM编辑/etc/pam.d/password-auth和/etc/pam.d/system-auth通常两者会互相包含修改一个即可。在auth部分的开头添加auth required pam_tally2.so deny5 unlock_time600 even_deny_root root_unlock_time300deny5连续失败5次后锁定账户。unlock_time600锁定600秒10分钟。even_deny_rootroot用户也受此规则限制。root_unlock_time300root账户锁定300秒5分钟可与普通用户区别对待。在account部分添加在同文件的account部分添加account required pam_tally2.so这一行负责检查账户是否已被锁定。管理锁定状态查看所有用户失败次数pam_tally2查看指定用户pam_tally2 --user username解锁一个被锁定的用户pam_tally2 --user username --reset方案B针对使用pam_faillock的系统如RHEL 8/CentOS 8, Ubuntu 20.04pam_faillock功能更强大它将失败记录存储在/var/run/faillock/目录下支持更复杂的策略。配置PAM编辑/etc/pam.d/password-auth和/etc/pam.d/system-auth。在auth部分的开头添加auth required pam_faillock.so preauth silent audit deny5 unlock_time600 auth [defaultdie] pam_faillock.so authfail audit deny5 unlock_time600在auth部分的末尾通常在pam_unix.so或pam_sss.so之后添加auth sufficient pam_faillock.so authsucc audit deny5 unlock_time600在account部分添加account required pam_faillock.so配置策略参数可选更推荐创建或编辑/etc/security/faillock.conf这是更现代的配置方式deny 5 unlock_time 600 fail_interval 900 # 统计失败次数的时间窗口为900秒15分钟 root_unlock_time 300 # root锁定时间稍短 audit # 审计日志 silent # 静默模式管理锁定状态查看状态faillock --user username解锁用户faillock --user username --reset踩坑记录pam_tally2的锁定是“内存中”的重启系统后锁定会解除。而pam_faillock的锁定信息存储在磁盘上重启后依然有效。这对于防护重启后仍持续的自动化攻击很有用。务必在测试环境先验证配置否则可能把自己锁在外面。永远保持至少一个活跃的root或sudo会话窗口在进行此类配置或者预先配置好基于密钥的SSH认证作为备用登录方式。4.3 第三层防御访问控制与资源限制目标从登录源头和会话资源上施加限制。基于时间的访问控制pam_time编辑/etc/security/time.conf语法如下服务;终端;用户;时间范围例如禁止developers组的用户在非工作时间通过sshd登录sshd;*;developers;!Al0000-2400这行规则表示对于sshd服务所有终端developers组用户在任何时间Al代表所有日期0000-2400代表全天都不允许!表示否定登录。显然这是个禁止所有时间的例子实际使用时需要更精细的时间段。例如只允许工作日9点到18点登录sshd;*;developers;Wd0900-1800。然后在/etc/pam.d/sshd文件中添加account required pam_time.so基于来源的访问控制pam_access编辑/etc/security/access.conf语法更直观permission : users : origins例如只允许来自内网网段192.168.1.0/24的用户通过SSH登录 : ALL : 192.168.1.0/24 : root : LOCAL # root允许从本地控制台登录 - : ALL : ALL # 拒绝其他所有在/etc/pam.d/sshd中添加account required pam_access.so会话资源限制pam_limits编辑/etc/security/limits.conf或/etc/security/limits.d/下的文件可以限制用户打开文件数、进程数等防止DoS。例如限制webuser最多只能有100个进程webuser hard nproc 100在PAM配置中pam_limits.so通常已在session部分默认加载。4.4 第四层防御关键安全基线配置这些是必须做的最低限度的安全配置。禁止root直接SSH登录编辑/etc/ssh/sshd_config设置PermitRootLogin no。然后使用普通用户登录后su或sudo提权。使用SSH密钥认证彻底禁用密码认证转向更安全的密钥认证。在sshd_config中设置PasswordAuthentication no和PubkeyAuthentication yes。配置sudo超时编辑/etc/sudoers使用visudo命令添加Defaults timestamp_timeout5表示sudo密码缓存5分钟之后需要重新输入。启用lastlog与securetty确保/etc/pam.d/login和/etc/pam.d/sshd中包含pam_lastlog.so和pam_securetty.so后者主要针对login服务让用户登录时能看到上次登录信息并限制root登录位置。5. 配置验证、测试与监控配置完成后绝不能一配了之。必须进行严格的测试和持续的监控。5.1 测试你的配置开一个新的终端会话这是铁律。永远不要在你唯一已登录的会话中测试认证锁定策略。测试密码复杂度尝试用弱密码如abc123修改密码看是否被拒绝。passwd testuser测试失败锁定使用一个普通用户通过SSH或su连续输入错误密码。观察第6次假设deny5是否被拒绝并提示“Account locked due to X failed logins”。等待解锁时间过后再次尝试登录是否成功。使用pam_tally2或faillock命令查看失败记录。测试访问控制从被禁止的IP段或时间段尝试SSH登录验证是否被拒绝。检查/var/log/secureRHEL或/var/log/auth.logUbuntu中的日志信息。5.2 关键日志监控认证相关的日志是安全审计的核心。主要关注/var/log/secure(RHEL/CentOS)或/var/log/auth.log(Ubuntu/Debian)这里记录了所有PAM和SSH的认证事件。/var/log/faillock/目录如果使用pam_faillock这里有详细的失败记录文件。你应该配置日志监控工具如logwatch,fail2ban或者更专业的SIEM系统来实时分析这些日志。一个简单的grep命令也能快速发现问题# 查看过去一小时内失败的SSH登录尝试 sudo grep \Failed password\ /var/log/secure | grep \$(date -d \-1 hour\ \%b %d %H:\)\ # 查看所有被锁定的账户事件 sudo grep \pam_tally2\|pam_faillock\ /var/log/secure | tail -205.3 使用fail2ban进行应用层联动防护虽然PAM的pam_tally2/fail2ban能在系统层面锁定账户但fail2ban这个工具可以做得更多。它监控日志文件当发现来自同一IP的多次失败登录尝试后会自动调用防火墙如iptables或firewalld临时封禁该IP地址。这是一种在网络层进行的、更彻底的阻断。安装与配置fail2ban# CentOS/RHEL sudo yum install epel-release sudo yum install fail2ban # Ubuntu/Debian sudo apt install fail2ban复制默认配置文件并创建本地配置sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local编辑/etc/fail2ban/jail.local启用SSH防护并调整参数[sshd] enabled true port ssh filter sshd logpath /var/log/secure # Ubuntu 改为 /var/log/auth.log maxretry 5 bantime 3600 findtime 600maxretry55次失败后封禁。bantime3600封禁3600秒1小时。findtime600在600秒10分钟内统计失败次数。重启服务并查看状态sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd个人体会fail2ban和PAM账户锁定是互补的。PAM锁定的是“用户名”防止针对特定用户的密码喷洒fail2ban封锁的是“IP地址”防止来自单一源的暴力破解。两者结合构成了认证防御的纵深。6. 常见问题与排查技巧实录在实际操作中你肯定会遇到各种问题。下面是我总结的一些典型场景和解决方法。6.1 问题排查清单问题现象可能原因排查步骤与解决方案修改PAM配置后所有用户都无法登录包括root。1. PAM配置文件语法错误。2. 添加了required或requisite控制标志的模块失败导致整个栈失败。黄金法则永远在另一个已认证的会话中测试1. 检查/var/log/secure或/var/log/auth.log中的具体错误信息。2. 使用pam_tally2 --user root --reset或faillock --user root --reset尝试解锁root。3. 通过服务器控制台物理机或云平台的VNC登录回退错误的PAM配置。用户密码符合策略但仍被拒绝。1.pam_pwquality的字典检查badwords或usercheck生效。2. 密码历史策略remember参数拒绝重复使用旧密码。3. 其他PAM模块如pam_limits资源耗尽意外失败。1. 检查/etc/security/pwquality.conf中的badwords文件和usercheck设置。2. 检查/etc/pam.d/system-auth中pam_unix.so是否包含remember5之类的参数。3. 查看认证日志定位是哪个模块返回了失败。pam_tally2不记录失败次数或锁定无效。1. PAM配置文件中模块顺序错误pam_tally2未在认证栈开头。2. 针对的服务如sshd的PAM配置文件/etc/pam.d/sshd未包含相关规则。3. 系统使用了pam_faillock而非pam_tally2。1. 确认pam_tally2.so行在/etc/pam.d/password-auth的auth和account部分正确添加。2. 确认/etc/pam.d/sshd通过include包含了system-auth或password-auth。3. 使用grep -r pam_tally /etc/pam.d/和grep -r pam_faillock /etc/pam.d/确认系统实际使用的模块。配置了pam_time或pam_access但未生效。1. 规则语法错误。2. 对应的PAM配置文件如/etc/pam.d/sshd中未添加pam_time.so或pam_access.so。3. 规则中的用户组需要用前缀。1. 仔细检查time.conf和access.conf的语法特别是分号、冒号分隔符。2. 确认account required pam_time.so或pam_access.so已添加到对应服务的PAM配置中。3. 使用groups username命令确认用户所属组名在规则中使用groupname。fail2ban服务运行但未封禁IP。1.filter定义不正确无法匹配日志中的失败信息。2.logpath指向错误。3. 防火墙规则iptables/firewalld未被正确调用。1. 使用fail2ban-regex /var/log/secure /etc/fail2ban/filter.d/sshd.conf测试过滤器。2. 确认logpath与系统日志路径一致。3. 运行sudo fail2ban-client status sshd查看“Currently failed”和“Total banned”计数。检查防火墙规则sudo iptables -L -n或sudo firewall-cmd --list-all。6.2 高级技巧与注意事项配置的继承与覆盖理解/etc/pam.d/下文件的包含关系至关重要。例如在RHEL中sshd通常会include system-auth。这意味着修改system-auth会影响所有包含它的服务。如果你想只为SSH设置特殊的策略应该直接修改/etc/pam.d/sshd而不是system-auth。控制标志Control Flags的精髓PAM规则行的第二个字段如required,sufficient,optional决定了模块失败或成功对整体认证结果的影响。required模块必须成功。失败会导致最终认证失败但会继续执行栈中后续模块。requisite模块必须成功。失败会立即导致认证失败后续模块不再执行。常用于关键检查如pam_securetty。sufficient模块成功则立即通过认证忽略后面required的模块。失败则忽略继续执行。optional成功或失败仅作为参考不影响大局。 错误地使用requisite可能导致合法用户因一个非关键模块失败而被提前拒绝体验很差。云服务器与控制台救援在云平台如AWS EC2, 阿里云ECS上如果你错误配置了PAM或SSH导致无法登录不要慌张。所有主流云平台都提供了“VNC连接”或“救援模式”功能。你可以通过云控制台连接到服务器的虚拟控制台就像坐在物理机前一样然后修复配置。务必在首次配置前测试并确保救援通道可用。自动化与版本管理服务器安全配置应该像代码一样被管理。将你的/etc/pam.d/关键文件、/etc/security/*.conf文件、/etc/ssh/sshd_config等纳入配置管理工具如Ansible, SaltStack或至少用Git进行版本控制。这样可以在出错时快速回滚也能保证环境的一致性。安全加固从来不是一劳永逸的事情尤其是认证安全它直接面对外部冲击。定期审查日志、更新密码策略、根据威胁情报调整失败锁定阈值是运维工作中不可或缺的一部分。从今天起别再只盯着防火墙了把你服务器的“内功”——PAM认证体系——好好修炼一番这才是应对真正威胁的基石。