跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Linux系统的安全基石:深入理解可插拔认证模块(PAM)

如果你管理过Linux系统,一定接触过登录时输错密码被拒绝、或者修改密码时被告知“密码不符合复杂度要求”这类场景。这些行为背后,都有一个统一的“指挥官”在协调——它就是可插拔认证模块(Pluggable Authentication Modules,简称PAM)。

PAM是Linux系统中与身份验证、账户管理、会话控制相关的一切操作的核心中间层。它真正实现了认证机制与应用本身的分离,让系统管理员可以像搭积木一样,灵活地为不同的服务(如sshd、login、su)配置所需的认证方式,而无需修改任何应用程序的源代码。

PAM解决了什么问题?

在PAM出现之前,每个需要认证用户的程序都要各自实现一套验证逻辑。如果想把“本地密码验证”切换为“LDAP服务器验证”,就需要分别去修改login、sshd等每一个程序的代码,不仅耗时费力,还极易出错。

PAM的诞生终结了这种混乱。它将所有与认证相关的通用任务标准化、集中管理,并为应用程序提供了一套统一的API(Application Programming Interface)。从此,像login或sshd这样的“PAM感知”应用程序,只需要调用PAM库的接口即可,具体的认证方式则完全由管理员通过外部配置文件来定义。

PAM的运作模式:四大管理组

PAM将认证任务清晰地划分为四个独立的管理组,每个组负责一个特定的环节。

管理组核心职责典型应用场景
auth(认证管理)验证用户的身份真实性提示用户输入密码,并与/etc/shadow中的记录比对;或通过指纹、智能卡等硬件设备进行认证。
account(账户管理)检查用户账户是否有效、是否有权使用特定服务验证账户是否过期;检查用户是否在允许登录的时间段内;或确认root用户是否只能从控制台登录。
password(密码管理)负责处理用户认证令牌(通常是密码)的更新当用户执行passwd修改密码时,password类型的模块会负责检查新密码的复杂度(如长度、字符类型),并最终更新/etc/shadow文件。
session(会话管理)在用户获得服务前后执行一些“后勤”工作记录用户的登录/注销日志;挂载用户的家目录;设置环境变量;或通过pam_xauth模块在用户切换时转发X11认证凭据,避免图形界面访问失败。

核心配置文件与语法

PAM的行为完全由配置文件定义。在现代Linux发行版中,配置通常位于/etc/pam.d/目录下,每一个支持PAM的服务(如sshd、login、passwd)都有一个同名的配置文件。如果/etc/pam.d/目录存在,则/etc/pam.conf文件会被忽略。

一个PAM配置文件条目通常由以下四部分组成:

module-type control-flag module-path arguments

  • module-type(模块类型):即上述的auth、account、password、session之一,指明该模块属于哪个管理组。
  • control-flag(控制标志):这是理解PAM逻辑的关键,它定义了模块执行成功或失败后的行为。主要有以下几种:
    • required:模块必须成功。若失败,则会在本类型所有模块都执行完毕后才返回错误,不会立即终止。这种策略可以防止用户通过返回信息猜测是哪个环节出错,增加了安全性。
    • requisite:与required类似,但若失败则会立即终止整个认证过程,并返回失败信息,不再执行后续同类型的模块。它常被用作一个“快速失败”的过滤器。
    • sufficient:如果此模块成功,且前面没有required模块失败,则立即返回成功,不再执行本类型后续的模块。若失败,则不影响最终结果,起到“跳过”后续模块的作用。
    • optional:模块成功或失败对最终结果没有直接影响,其返回值通常被忽略。常用于仅用于记录日志等目的模块。
  • module-path(模块路径):PAM模块文件的路径。如果是相对路径,通常指/lib/security/或/lib64/security/目录。
  • arguments(模块参数):传递给特定模块的参数,比如pam_unix.so模块的nullok参数允许空密码,pam_tally.so的deny=3参数设置连续错误3次后锁定。

实战配置示例:PAM如何保护你的系统

理解了基本语法之后,我们来通过几个真实场景的配置案例,看看PAM如何在各种服务中发挥作用。修改PAM配置文件后无需重启任何服务即可实时生效,但修改服务自身的配置文件(如/etc/ssh/sshd_config)后需要重启对应的服务。

示例一:为SSH登录增加双重认证(MFA)

这个例子演示如何为sshd服务配置PAM,让用户在SSH登录时,除了验证系统密码,还必须通过一个额外的身份验证步骤(比如输入动态验证码)。

1. 编辑SSH服务的PAM配置文件:

vim /etc/pam.d/sshd

2. 在认证(auth)部分插入MFA模块:

在文件中auth部分的开头,插入MFA模块。例如,使用Google Authenticator模块(pam_google_authenticator.so)。

# 在auth类型模块堆栈的开头添加
auth       required     pam_google_authenticator.so
# ... 原有的auth配置,比如下面这行 ...
auth       include      system-auth

这里的逻辑是:auth模块类型负责验证用户身份。required控制标志意味着该模块必须成功,才能继续后面的认证流程。如果动态验证码错误,整个登录过程就会在此失败。

3. 修改SSH服务端配置并重启:

确保SSH服务本身启用了PAM支持。编辑/etc/ssh/sshd_config文件,设置以下参数:

UsePAM yes
ChallengeResponseAuthentication yes
PasswordAuthentication no  # 建议启用,避免绕过MFA

然后重启sshd服务使配置生效。

systemctl restart sshd

示例二:强化系统密码复杂度策略

这个例子通过修改系统认证的公共配置文件,为所有使用PAM的服务(如login、sshd、passwd等)统一设置强密码规则。

1. 编辑密码策略公共配置文件:

在许多Linux发行版中(如CentOS、RHEL),这个策略通常定义在/etc/pam.d/system-auth。在Debian/Ubuntu系统中,对应的文件可能是/etc/pam.d/common-password。

vim /etc/pam.d/system-auth
# 或
vim /etc/pam.d/common-password

2. 修改密码(password)模块参数:

找到包含pam_cracklib.so或pam_pwquality.so的行,添加或修改参数。

password    requisite    pam_pwquality.so try_first_pass retry=3 minlen=8 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1
  • password模块类型:负责处理密码的更改。
  • requisite控制标志:表示如果密码强度检查不通过,会立即拒绝修改,并给出错误提示,不会执行后续模块。
  • 参数解释:
    • minlen=8:密码最小长度为8。
    • dcredit=-1:要求至少包含1个数字。
    • ucredit=-1:要求至少包含1个大写字母。
    • lcredit=-1:要求至少包含1个小写字母。
    • ocredit=-1:要求至少包含1个特殊字符。

示例三:vsftpd的三种PAM认证配置

vsftpd(Very Secure FTP Daemon)是Linux上最流行的FTP服务器软件,它深度集成了PAM认证机制,并且有一个显著特点:vsftpd通过在vsftpd.conf中指定pam_service_name参数来切换不同的认证方式,这意味着可以为同一个FTP服务快速切换PAM策略,而无需反复修改/etc/pam.d/vsftpd文件本身。

基础设置:vsftpd主配置文件

首先,无论采用哪种认证方式,都需要在/etc/vsftpd.conf中启用PAM支持并指定服务名:

# /etc/vsftpd.conf
anonymous_enable=NO          # 禁用匿名登录,强制用户认证
local_enable=YES             # 允许本地系统用户登录
write_enable=YES             # 允许上传/修改文件
chroot_local_user=YES        # 将用户限制在其主目录
pam_service_name=vsftpd      # 指定PAM服务名为"vsftpd"
userlist_enable=YES          # 启用用户列表控制

配置一:使用标准系统用户密码认证(最基础)

最简单的场景是让vsftpd直接使用Linux系统用户进行认证。编辑/etc/pam.d/vsftpd:

# /etc/pam.d/vsftpd
auth     required     pam_unix.so
account  required     pam_unix.so
  • auth required pam_unix.so:认证阶段使用系统/etc/shadow文件验证用户名和密码。
  • account required pam_unix.so:账户管理阶段检查账户是否过期、是否有效。

这种配置会让vsftpd直接调用系统PAM认证,行为与SSH登录类似。

配置二:结合用户名单与系统认证(推荐常规场景)

这种方式既保留了系统密码认证,又增加了用户白名单控制:

# /etc/pam.d/vsftpd
auth     required     pam_listfile.so item=user sense=allow file=/etc/vsftpd.user_list onerr=succeed
auth     required     pam_shells.so
account  required     pam_nologin.so
account  required     pam_access.so

各模块的作用:

模块类型作用说明
pam_listfile.soauth读取/etc/vsftpd.user_list文件,sense=allow表示仅允许列表中的用户登录
pam_shells.soauth检查用户的shell是否在/etc/shells中,防止拥有无效shell的系统账号登录FTP
pam_nologin.soaccount如果/etc/nologin文件存在,拒绝非root用户登录
pam_access.soaccount基于/etc/security/access.conf进行更细粒度的访问控制,如限制IP来源

然后创建/etc/vsftpd.user_list文件,每行一个允许登录的用户名:

# /etc/vsftpd.user_list
zhangsan
lisi
wangwu

配置三:虚拟用户认证(最安全的FTP专属方案)

虚拟用户是vsftpd最经典的用法——FTP用户不与任何Linux系统用户绑定,仅存在于FTP服务的认证数据库中,即使密码泄露也不会威胁系统安全。这需要使用pam_userdb.so模块配合独立的用户数据库。

  1. 创建虚拟用户凭证文件并生成数据库:
# 创建明文密码文件(用户名和密码交替排列)
sudo vi /etc/vsftpd/virtual_users.txt
testuser1
password123
testuser2
securepass456

# 转换为Berkeley DB格式
sudo db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db
sudo chmod 600 /etc/vsftpd/virtual_users.db
  1. 创建独立的PAM服务配置文件/etc/pam.d/vsftpd-virtual:
# /etc/pam.d/vsftpd-virtual
auth     required     pam_userdb.so db=/etc/vsftpd/virtual_users
account  required     pam_userdb.so db=/etc/vsftpd/virtual_users
  1. 修改vsftpd主配置文件指向新的PAM服务:
# /etc/vsftpd.conf
guest_enable=YES                    # 启用虚拟用户模式
guest_username=ftpuser              # 所有虚拟用户映射到系统用户ftpuser
virtual_use_local_privs=YES         # 虚拟用户拥有本地用户权限
user_sub_token=$USER                
local_root=/home/ftpuser/$USER      # 每个虚拟用户独立子目录
pam_service_name=vsftpd-virtual     # 指向刚刚创建的PAM配置文件
  1. 创建承载虚拟用户的系统账号:
sudo adduser --system --home /home/ftpuser --shell /sbin/nologin ftpuser
sudo mkdir -p /home/ftpuser/testuser1
sudo chown ftpuser:ftpuser /home/ftpuser/testuser1
认证方式适用场景PAM核心模块vsftpd.conf中pam_service_name
系统用户认证小型团队、与系统用户共用账号pam_unix.sovsftpd
用户名单+系统认证需要限制特定用户登录的常规场景pam_listfile.so + pam_unix.sovsftpd
虚拟用户认证企业级FTP、多租户、安全隔离要求高pam_userdb.sovsftpd-virtual(自定义)

PAM模块生态

PAM的强大在于其丰富的模块库,按功能可大致分为以下几类:

  • 认证类:pam_unix.so(传统系统密码)、pam_ldap.so(LDAP目录服务)、pam_winbind.so(Windows域认证)、pam_google_authenticator.so(Google动态验证码)、pam_radius.so(RADIUS服务器认证)。
  • 账户管理类:pam_listfile.so(用户名单控制)、pam_access.so(基于主机/IP的访问控制)、pam_nologin.so(维护模式拒绝登录)、pam_time.so(基于时间的访问控制)。
  • 密码强度类:pam_pwquality.so / pam_cracklib.so(密码复杂度检查)、pam_passwdqc.so(更严格的密码质量策略)。
  • 会话管理类:pam_limits.so(资源限制,对应/etc/security/limits.conf)、pam_env.so(设置/清除环境变量)、pam_mount.so(自动挂载加密目录)、pam_lastlog.so(记录最后登录时间)。
  • 安全防护类:pam_tally.so / pam_tally2.so(登录失败计数与锁定)、pam_faillock.so(更精细的失败锁定策略)、pam_securetty.so(限制root仅从安全终端登录)。
  • 日志与调试类:pam_warn.so(记录警告日志)、pam_debug.so(调试输出)。

每个模块的详细参数均可通过man 模块名(如man pam_access)查看,配置思路与前面示例完全一致——在对应服务的/etc/pam.d/配置文件中添加一行即可。

配置要点总结

  1. 定位配置文件:绝大多数现代Linux发行版都使用/etc/pam.d/目录下的独立配置文件。该目录下与应用程序同名的文件,就是其PAM配置。
  2. 理解四个模块类型:auth(认证)、account(账户有效性)、password(密码更新)、session(会话管理)这四个职责要分清。
  3. 控制标志是关键逻辑:required、requisite、sufficient、optional决定了模块成功或失败后认证流程如何继续。简单来说,required是“必须成功,但会给其他模块机会”,而requisite是“必须成功,一旦失败就立即停止”。
  4. 生效机制:PAM配置修改后实时生效,无需重启任何服务。但修改服务自身的配置文件(如/etc/ssh/sshd_config或/etc/vsftpd.conf)后,需要重启对应的服务。
  5. 安全操作建议:配置出错可能导致所有用户无法登录,建议在测试环境中先验证配置,同时保持一个已登录的root会话作为“逃生通道”,以便在配置失败时能够回滚。

总结

PAM作为Linux安全体系的核心组件,其“可插拔”的设计理念赋予了系统管理员前所未有的灵活性和控制力。它成功地将应用程序开发与安全策略部署解耦,使我们能够在不改动任何程序代码的前提下,动态调整整个系统的认证方式、增强安全策略。理解并善用PAM,是迈向精通Linux系统管理和安全运维的关键一步。

作者

老丹

关注我
其他文章
上一个

vsftpd 完全指南:从核心原理到Docker容器化部署

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Linux系统的安全基石:深入理解可插拔认证模块(PAM) 2026年7月27日
  • vsftpd 完全指南:从核心原理到Docker容器化部署 2026年7月27日
  • 互联网的”导航”安全卫士:深入解读DNSSEC 2026年7月27日
  • Ubuntu DNS 配置完全指南 2026年7月27日
  • 在 Ubuntu 中使用 Certbot 的操作指南 2026年7月27日

文章分类

  • C/C++开发 (13)
  • Docker容器 (3)
  • Linux工具包 (10)
  • Linux服务配置 (33)
  • Linux系统 (10)
  • OpenWrt路由 (2)
  • Shell脚本 (3)
  • 安防技术 (4)
  • 数据安全 (30)
  • 网络协议 (17)
  • 计算机理论 (22)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号