类Unix系统上的身份验证可能是系统管理员最接近魔法的东西。
每个系统管理员都听说过可插拔身份验证模块(Pluggable Authentication Modules —— PAM)。我们都知道 /etc/pam.d/ 中的文件决定了大多数软件的身份验证方式。如果你想使用公钥身份验证,或使用物理令牌进行身份验证,或者只依赖密码,你必须在这些文件中混日子。通常,系统管理员会盲目地遵循说明,希望不会发生任何可怕的事情。
PAM策略与系统管理中的其他策略并不完全相同。一组PAM语句的处理方式不像一组数据包过滤规则或共享库路径,除非是这样。此外,PAM使用了“必需”(requisite)等奇怪的单词,而“足够”(sufficient)一词显然意味着“足够”(enough)之外的任何东西。
当你破坏PAM时,你破坏了整个服务。大多数服务一开始就很难运行,因此不建议破坏它们。希望这不是让你登录到机器的服务。
然而,PAM不一定是黑魔法。启用谷歌身份验证器并不一定需要在一年的第十三个满月上用一把由母系继承的银新锻造的刀牺牲一只黑色公鸡。你所需要的只是你的系统管理员技能和这本书。
本书是为中等经验的系统管理员编写的。您需要了解管理共享库、安装和删除软件以及排除首选平台的故障。
并非所有平台都有适用于所讨论的所有模块的软件包。使用这些模块需要从源代码构建它们。虽然我将给出编译模块的基本说明,但这些说明假设您以前编译过软件,并且了解平台编译器的行为。在CentOS上,您需要“开发工具”包组和pam-devel包。在Debian上,您将需要构建要点和libpam0g开发包。FreeBSD ports系统包含本书讨论的所有模块。
本书重点介绍跨平台解决方案,特别是用于教育目的的解决方案。也许你的类Unix系统有一个专门用于特定任务的PAM模块。我偶尔会提到这样的模块,但最关注的是多个操作系统使用的模块。
您还需要测试系统。尝试PAM的好处是系统要求很低。虚拟机非常适合测试PAM。如果您正在尝试使用pam_exec生成一个Perl进程来管理身份验证,那么您需要在部署到生产环境之前执行负载测试。
你会从这一切中得到什么?这本书不会教你在你喜欢的平台上深入了解PAM的细节。它将教你如何思考PAM,策略和模块是如何工作的,以及如何探索和掌握你首选的操作系统的PAM实现。您还可以将这里获得的专业知识传授给任何其他使用PAM的操作系统。
各种安全和计算机构重新定义了“身份验证”,以最好地满足自己的需求。如果你深入研究安全理论,你会偶然发现身份验证、授权和计费(Authentication, Authorization, and Accounting ——AAA)这个术语。管理信息系统文档可能侧重于资源控制,而系统管理员只关心用户名和密码的匹配。
就PAM而言,身份验证(authentication )意味着验证用户的凭据,并为提供这些凭据的人建立服务。使用AAA术语的安全专家会告诉你,PAM将所有这些角色结合在一起。它确实如此。然而,PAM还允许您为AAA的各个组件配置不同的模块和服务。
PAM不仅验证身份验证凭据。它可以安排主目录、日志访问、启用服务等。PAM将系统服务与身份验证集成在一起。
如果您习惯于术语标识、身份验证和授权(Identification, Authentication, and Authorization —— IAA),您应该知道PAM不处理标识(identification)。依赖PAM的系统通常使用名称服务交换机(NSS)来管理标识。NSS也起源于Solaris,比PAM早几年。从那以后,NSS和PAM之间缺乏集成,给类Unix系统带来了持续的偏头痛。
双因素身份验证(two-factor authentication)这个短语经常被提及。您可以使用PAM来实现双因素身份认证,或者实际上是多因素身份验证。显而易见的问题是:什么是身份验证因素?
身份验证基于三个用户特征之一:他们拥有(have)的东西、他们知道(know)的东西或他们是(are)什么。“他们拥有的东西”是指物理令牌,如硬件安全令牌或与特定电话号码绑定的手机。这些实物很容易丢失或损坏。“他们知道的东西”是一个秘密,比如密码——我们都知道密码会写在便签上并附在显示器上。“它们是什么”——包括指纹、虹膜扫描或基因扫描等生物特征因素——可能看起来是最好的。但生物特征数据可能会被盗。为应对盗窃而改变虹膜扫描模式超出了本书的范围。
多因素身份验证需要这些因素中的两个或多个。也许你需要一个安全令牌、一部特定的手机、一个密码和一个指纹。入侵者可以毫不费力地捕获其中任何一个,但要抓住每一个必要的部分则要困难得多。
本书的后半部分包括几个添加身份验证因素的PAM模块,如Google Authenticator(第9章)或用于特定目的,如PAM_passwdqc密码质量检查器(password quality checker)(第11章)。
如果可插拔身份验证模块如此麻烦,为什么要使用它们?
因为大多数替代品都更糟糕。
在计算的早期,每个程序都需要单独的配置来支持任何所需的身份验证方法。如果你想让一个新的工作站符合企业网络要求的标准,你需要调整该工作站上的每个程序。其中一些程序需要更改配置文件,而另一些程序则要求完全重新编译。没有软件或操作系统支持所有身份验证方法。如果你想做一些与众不同的事情……祝你好运!
1995年,Sun Microsystems提出了一个标准的跨平台、跨程序的身份验证接口。采用此接口的软件可以利用提供该接口的任何身份验证程序。如果你想为这些程序提供一种新的身份验证机制,你可以编写它来连接到此接口,然后将其插入到所有软件中。因此,可插拔身份验证模块或PAM。
PAM模块(PAM modules)是实现特定身份验证方法的代码块。您想提供用户名和密码的身份验证吗?这是一个模块。通过硬件令牌?这是一个模块。通过基因扫描、酒精测试和舞蹈革命平台?如果存在这样的东西,这些也都是模块。(为了与平台无关,本书在许多示例中使用了这三个模块。)模块是共享库,根据配置动态链接到主程序中。是的,短语“PAM模块”是多余的,但这就是系统管理员所说的,我已经有太多的战斗要打了。
使用PAM的软件接收身份验证请求。程序将每个请求交给配置的身份验证模块,这些模块告诉服务器是否应该允许该身份验证请求。
今天,PAM是类Unix系统中使用最广泛的身份验证标准。它在Linux世界以及基于Solaris和BSD系统中非常受欢迎。甚至苹果的OS X也使用PAM,以及AIX和HP-UX等商业UNIX系统。
严格来说,PAM不是官方认可的标准。没有一个大型认证机构在一组PAM定义和协议上盖章,并将其宣布为一个真正的PAM规范。通用桌面环境(Common Desktop Environment —— CDE)包括PAM,CDE在20世纪90年代成为标准,因此PAM确实在各种标准文档中被引用。大多数现代PAM实现都是基于1997年尝试将PAM包含在可移植操作系统接口(Portable Operating System Interface —— POSIX)中的规范草案。如果你真的想深入了解PAM,请查看文档 X/Open Single Sign-on Service (XSSO) – Pluggable Authentication Modules,可从许多互联网网站获得,包括http://pubs.opengroup.org.从那时起,人们就试图对PAM进行标准化,但所有的尝试都失败了。
缺乏正式标准意味着PAM也缺乏正式定义的语言。根据您阅读的文档,一组规则可能是链(chain )、堆栈(stack )或策略(policy)。身份验证过程的一个组成部分可能是类型(type )、设施(facility )或诸如此类的东西(whatsit)。在这本书中,我给出了每个组件最常用的术语,然后选择一个单词来表示该组件。我用一个特定的词来指代PAM的一部分,并不意味着所有其他选择都是无效的;这只意味着,如果你想理解这个晦涩难懂的术语,你需要一致性。
PAM是使用最广泛的身份验证系统,但其局限性使其不适合某些应用。
PAM最大的缺点是PAM模块不能直接与客户端交互。服务器程序是PAM模块和客户端之间的中介,模块与客户端之间的任何交互都仅限于标准PAM接口提供的交互。一些身份验证协议,如Kerberos,包括一系列全面的客户端-服务器交互,远远超出了PAM的支持范围。在Kerberos中,PAM是一个瓶颈。虽然您可以使用PAM模块来支持Kerberos,但您不能通过PAM实现Kerberos。这也是SSH在PAM之外处理其大部分身份验证的原因(尽管如果您决定这样做,它可以利用PAM)。
这种限制就是人们创建其他身份验证协议的原因,例如简单身份验证和安全层(Simple Authentication and Security Laye r—— SASL)和通用安全服务API(Generic Security Services API —— GSSAPI),以及围绕这些协议发展的所有工具和服务。
并非所有操作系统都使用PAM。值得注意的是,OpenBSD使用BSD身份验证(BSD Authentication),它将身份验证请求分为单独的进程,而不是动态链接的库。BSD身份验证比PAM更广泛地分离特权,从而降低了安全风险,但不如PAM灵活,也没有PAM广泛使用。
不过,如果您想在PAM之前尝试身份验证管理,请考虑在所有服务器软件中实现和部署Kerberos所需的各种工作。虽然这些应用程序都连接到一个通用的Kerberos域,但您可以以完全不同的方式配置每个应用程序。现在想象一下,乘以今天使用的所有身份验证协议,以及这些协议与所有不同软件的所有交互。PAM现在看起来好多了,不是吗?
虽然任何人都可以实现PAM,但最常见的是三个特定版本:Solaris、Linux-PAM和OpenPAM。不同的版本几乎兼容。
Sun首先提出了PAM,Sun Solaris也首次实现了PAM。Solaris的PAM代码进入了开源OpenSolaris,在那里它不可逆转地成为了公共源代码生态系统的一部分。Oracle收购了Sun,不再公开发布Solaris代码的任何更新,但OpenIndiana等社区项目维护和更新了公共版本的Solaris PAM。虽然其他PAM实现者基于Sun的原始工作构建了他们的模块,但Sun删除了这些模块,转而使用全新的模块。这意味着Linux和BSD系统中出现的模块和配置虽然基于Sun的工作,但与目前Solaris PAM系统附带的模块和设置没有相似之处。
Linux-PAM是用于大多数Linux系统的可插拔身份验证模块实现。它非常接近原始的Sun模型,许多PAM模块保持了原始实现的相同名称和功能。它与Solaris PAM基本兼容,但并非完全兼容。你会发现Linux-PAM主要存在于Linux系统中,但它也出现在一些商业Unix变体中。可悲的是,不同的Linux发行版通常使用略有不同的Linux-PAM版本。
OpenPAM的作者试图包括Linux-PAM、Solaris PAM和拟议的XSSO标准中最重要的部分。OpenPAM起源于FreeBSD社区。OpenPAM本身包含的模块很少,但大多数人所说的OpenPAM实际上是“OpenPAM和从FreeBSD中挑选出来的模块”。使用PAM的基于BSD的系统都使用OpenPAM。OpenPAM的标准模块类似于Linux-PAM和原始Solaris的模块。 虽然OS X使用OpenPAM,但苹果不使用常见的PAM模块。相反,他们编写了自己的PAM模块,以便更好地与One True Apple方式集成。
商业UNIX系统通常有自己的PAM实现,其行为方式符合供应商的偏好。例如,IBM的AIX使用标准的PAM策略,但几乎在所有地方都调用PAM_AIX模块。(AIX PAM也在其专有的可加载身份验证模块系统上实现,因为它是IBM的。)
CentOS和Debian都使用Linux-PAM。遗憾的是,他们使用的Linux-PAM版本略有不同。每个发行版的设计者都会选择对他们有意义的功能和模块。结果是,CentOS Linux-PAM包含Debian Linux-PAM中没有的功能和选项,反之亦然。当我们遇到这些差异时,我会提到其中的一些。如有疑问,请查阅您的Linux文档,看看您会得到什么玩具。
此外,Linux-PAM和OpenPAM使用PAM的方式不同,因为它们支持不同设计的操作系统。例如,Linux-PAM可以更改用于存储新密码的加密算法。BSD和较旧的Sun系统使用登录类处理密码加密算法,因此OpenPAM不包括该功能。我会在我们前进的过程中指出这些差异。
Linux-PAM比OpenPAM有更多的旋钮和按钮。部分原因是Linux-PAM需要OpenPAM在其他地方提供的功能,但Linux-PAM开发人员似乎也喜欢额外的旋钮和按钮。为了避免你随意摆弄按钮,这本书对Linux-PAM的关注比OpenPAM多一点。
虽然操作系统供应商可以协调他们的PAM配置,并提出每个系统管理员都可以立即识别和使用的东西,但没有人可能这样做。相反,每个开源平台都欢迎其他操作系统打包者复制他们明显优越的设计。因此,每个平台对PAM的配置都不同。
当您第一次深入了解操作系统的PAM设置时,请分配时间来了解打包者是如何组装所有内容的。人们很容易认为,为不熟悉的操作系统设计PAM策略的人是疯狂的。容易,但适得其反。研究这些不熟悉的配置,找出它们以这种方式组合在一起的原因。您不仅可以理解PAM实现,还可以深入了解操作系统打包者的想法,而这种洞察力将帮助您掌握系统的其余部分。
第10章说明了我们的三个参考平台中的每一个都可以以完全不同的方式使用一个PAM模块,其原因对操作系统打包者来说非常有意义。
所有这些不同的实现都有共同的结构和配置语法。也许你最初不会理解为什么Debian在其默认系统范围配置的顶部附近放置了“拒绝所有身份验证”规则,但你会理解策略的语法,并能够弄清楚。大多数PAM实现共享通用的模块名称,但我会注意到一些例外。
每个实现和操作系统安装都有一个共同点:它们都有bug。在我写这篇文章的时候,长标准pam_mkhomedir模块在CentOS上窒息而死。(Red Hat对此有原因,第6章展示了如何解决这个问题。)FreeBSD上的pam_unix上的 use_first_pass
和 try_first_pass
选项失败。请务必阅读操作系统文档,如果有什么奇怪的地方,请查看邮件列表存档和讨论板,了解其他有同样问题的人。如果你真的了解你首选的PAM实现中的许多错误,你就不会嘲笑其他版本中的错误。
一些Linux发行版提供了管理PAM的工具。这些工具允许您更改身份验证方法,而无需编辑讨厌的配置文件。它们适用于许多简单的部署。但是,如果你想弄清楚为什么你的系统会以某种方式运行,或者你想做一些复杂的事情,这些工具将你限制在工具作者想象的场景中。理解奇怪的行为绝对需要理解规则是如何工作的,无论是作为独立的语句还是作为策略的组成部分。
这些附加工具覆盖了现有的PAM配置。您必须学会强制这些工具创建所需的配置,或者放弃它们并手动管理身份验证。无论哪种情况,了解配置都会使您成为更好的系统管理员。
本书主要介绍PAM,因为它部署在普通的Linux和BSD版本中。关于PAM如何处理策略的材料也适用于Oracle Solaris、OpenSolaris衍生系统、OS X和专有UNIX系统,但这些系统使用非常不同的核心PAM模块。您可以把我将讨论的许多PAM模块添加到这些系统中,但您必须仔细研究配置文件。
我专门针对三种不同配置风格的操作系统:CentOS、Debian和FreeBSD。
CentOS是Linux的Red Hat Linux分支的代表。这本书使用CentOS而不是官方的Red Hat Linux,因为CentOS是免费的,而我是个吝啬鬼。CentOS使用Linux-PAM。许多Linux发行版都是在Red Hat Linux之上构建的,这些衍生版本应该能够使用CentOS PAM配置。
本文涵盖的一些PAM模块位于EPEL包存储库中。要使用这些模块,您需要启用该存储库、构建自己的包或进行其他安排。
CentOS和相关的Linux发行版提供了一个命令行工具来配置PAM: authconfig(8)
。
Debian Linux分支的设计理念与Red Hat Linux分支不同。它支持大部分相同的软件,但管理界面几乎完全不同。Debian使用Linux-PAM。许多Linux发行版,如Ubuntu和Kali Linux,都是在Debian之上构建的,应该能够使用Debian配置。
本书中讨论的一些PAM模块位于实验包存储库中。您需要启用该仓库或构建自己的包。
与CentOS一样,Debian也包含一个为您编写PAM配置文件的附加工具。与CentOS不同,Debian使用 pam-auth-update(8)
,这是Debian人员专门为Debian编写的工具。
FreeBSD是我们的OpenPAM参考平台。支持PAM的BSD平台,如Dragonfly和NetBSD,使用OpenPAM,苹果的OS X也是如此。在FreeBSD上工作的配置应该在除OS X之外的任何BSD平台上工作。(OS X使用与任何其他OpenPAM实现完全不同的PAM模块,使其几乎适用于所有情况。)
一些Linux发行版使用OpenPAM,或者允许轻松地用另一个替换他们选择的PAM实现。您将像其他PAM实现一样配置这些操作系统,但您可能会发现一些PAM模块的名称略有不同。如果你正在使用带有OpenPAM的Linux发行版,并且在寻找模块时感到困惑,请查看CentOS或Debian示例,以找到Linux人员为该模块指定的名称。
PAM可能不是一个单一的标准,但其配置的基础知识在各种实现中都是通用的。管理Solaris衍生产品或OS X的系统管理员可以使用这里的指导来创建自己的PAM配置。
关于附加PAM模块的大部分指导,如Google Authenticator或SSH代理身份验证,直接适用于每个平台。配置密码质量检查器的细节在操作系统之间没有太大差异,即使您在策略中放置该模块的位置不同。
OpenSSH的SSH服务器 sshd(8)
并不真正需要PAM。SSH身份验证的行业标准方法——密钥——不适合PAM。SSH服务器确实需要检查密码,这确实涉及PAM,但这是一个简单的检查。如果你使用单因素身份验证,简单的密码检查就可以正常工作。
不过,如果您想要更复杂的基于PAM的身份验证,请首先告诉 sshd(8)
与PAM链接。将 sshd_config 中的 UsePAM
选项设置为 yes
。这启用了基于PAM的帐户访问检查、自动完成主目录等。但是,它不会触发基于PAM的身份验证。
SSH守护进程有两个选项来处理键盘上的用户身份验证。一个是 PasswordAuthentication
,专门用于密码。另一种是 ChallengeResponseAuthentication
,它是一种更通用的身份验证机制。要使用PAM,您几乎肯定需要 ChallengeResponseAuthentication
。
xxxxxxxxxx
UsePAM yes
ChallengeResponseAuthentication yes
PasswordAuthentication no
控制台和串行端口登录尝试使用 login(8)
程序,该程序有自己的PAM策略。SSH服务器可以通过 UseLogin
选项将部分用户登录过程传递给 login(8)
。此选项通常为否。login(8)
和 sshd(8)
策略之间的交互要么非常有趣,要么完全令人恼火,这取决于你是否是需要让它们工作的人。要使用PAM,最好让SSH服务器处理登录过程,而不是调用login(8)
。
xxxxxxxxxx
UseLogin no
最后,告诉 sshd(8)
咨询PAM进行身份验证。为此,您需要 sshd_config 中的 AuthenticationMethods
选项。keyboard-interactive
设置告诉sshd将身份验证传递给另一个代理,如PAM。如果您激活PAM并告诉 sshd(8)
使用键盘交互式身份验证,您将获得PAM进行身份验证和帐户管理。将其设置为公钥意味着sshd需要公钥身份验证。将两者用逗号组合意味着sshd需要两者,而用空格分隔意味着sshd提供了多种身份验证选项。
大多数希望在 sshd(8)
中启用PAM的人都希望守护进程拒绝所有没有公钥的身份验证请求,然后给PAM一个允许或否决连接的机会。这会给你一个像这样的 AuthenticationMethods
条目。
xxxxxxxxxx
AuthenticationMethods publickey,keyboard-interactive
或者,您可能希望让具有公钥身份验证的用户直接进入,然后回退到PAM进行一次性密码或其他一些强身份验证。在方法之间留一个空格。
xxxxxxxxxx
AuthenticationMethods publickey keyboard-interactive
即使有这些选项,也不是所有PAM模块都能与sshd一起工作。将 pam_ssh_agent_auth
(第8章)插入sshd,虽然听起来很有趣,但只会让你恼火。
每当系统管理员考虑身份验证时,集中身份验证的话题就会出现。这些讨论大多以轻量级目录访问协议(Lightweight Directory Access Protocol —— LDAP)和Kerberos的各种排列结束。这本书能帮你吗?
是的,也不是。
部署LDAP的困难与PAM关系不大。配置LDAP身份验证很困难,因为LDAP非常自由。您可以使用任意数量的LDAP模式或创建自己的模式。在LDAP部署早期做出的决定会产生影响,您将永远忍受。更糟糕的是,我们每个参考平台上的LDAP模块之间的差异意味着每个平台都需要一个唯一的配置。
Kerberos不像LDAP那样自由,但它有非常具体的要求和更高的开销。
本书将帮助您了解PAM配置如何影响这些集中式身份验证方法。它将帮助您在部署时从PAM中提取调试信息。它不会帮助您决定如何设计LDAP模式。
这本书有两大块。前六章将指导您了解PAM的工作原理。
通过这六章,您可以执行基本的配置任务和调试。本书的其余部分将带您进入特定的模块。简单的互联网搜索可以发现数百个PAM模块,但本书只涵盖了其中的几个。其中一些非常广泛可用且非常有用,例如 pam_exec
(第7章)。有些很受欢迎,比如 pam_ssh_agent_auth
(第8章)和谷歌身份验证器(第9章)。让我来说明一些关于PAM的要点。 pam_ssh
模块(第10章)不仅说明了一个有用的功能,还作为一个案例研究,说明了操作系统如何部署相同的pam模块的令人恼火的差异。
这仍然留下数百个PAM模块。许多PAM模块对需要它们的人来说至关重要,但只有一小部分读者需要任何给定的模块。这本书让你对PAM有了足够的了解,可以确信你有能力为使用该模块编写正确的规则,从而释放你宝贵的脑力来理解模块本身以及该模块如何融入政策。
拿上你的手电筒。我们要去PAM。