系统管理员有一个早上的例行程序。咖啡因、裤子、更多的咖啡因和蹒跚地走进办公室后,我们瘫倒在工作站前。我们使用用户名和密码登录。大多数人输入我们的SSH密码,并将我们的密钥加载到SSH代理中。此时,我们可以开始工作了。这需要对我们的工作站进行两次身份验证:一次使用用户名和密码,一次使用密码和SSH密钥。
pam_ssh模块将ssh密钥管理与登录过程集成在一起。用户可以访问他们的工作站,仅使用SSH密钥登录。用户使用其帐户中的SSH私钥进行身份验证,而不是使用 /etc/passwd 进行身份验证。成功通过身份验证后,pam_ssh会启动一个ssh代理,并将解密的私钥存储在代理中。
与本书中讨论的其他PAM模块不同,pam_ssh对工作站最有用,而且只适用于选定的工作站。您当然不希望根据存储在服务器上的SSH密钥文件对服务器进行身份验证。典型用户永远不应该向远程服务器提供密码。你可能不想在销售人员的机器上有这个功能。但许多系统管理员发现pam_ssh在他们的个人笔记本电脑上非常方便。
Pam_ssh为身份验证和会话类型提供服务。pam_ssh用于身份验证策略,提示用户输入密码。它尝试使用该密码对用户的私有SSH密钥进行解密,就像 ssh(1)
或 ssh-add(1)
一样。如果密码有效,模块将返回PAM_UCCESS。否则,模块将出现故障。在会话策略中,pam_ssh为用户启动一个ssh代理,并将密钥添加到代理中。
FreeBSD默认包含pam_ssh。Centos有一个pam_ssh包,而Debian提供了一个libpam-ssh包。这些模块不仅包装不同;它们是不同的代码。FreeBSD导入了原始的pam_ssh并进行了改进。该代码是从FreeBSD中提取出来的,并分叉成CentOS和Debian的略有不同的版本。每种都支持不同的功能。我们将分别介绍每个操作系统的pam_ssh。
此外,每个操作系统使用pam_ssh的方式不同。我们将利用这个模块来探索如何用完全不同的PAM语句配置一个非常相似的模块,并产生非常不同的行为。
我们介绍的pam_ssh的所有版本都支持try_first_pass、use_first-pass和debug选项。
第十章:使用SSH密钥访问控制台一个模块,不同的政策FreeBSD 和 pam_sshDebian 和 pam_ssh比较SSH 和 pam_sshFreeBSD pam_sshOpenPAM SSH 代理密钥选择CentOS pam_sshCentOS pam_ssh 登录提示选择密钥文件Debian pam_sshDebian pam_ssh 密钥选择绕过密码
我们的三个目标平台都以不同的方式部署pam_ssh。CentOS不提供任何关于放置pam_ssh语句的建议。FreeBSD在默认安装中包含pam_ssh。pam_ssh的语句出现在FreeBSD的标准配置文件中,但它们被注释掉了。Debian的libpam-ssh包不仅安装了pam_ssh,还添加了pam语句来启用该模块。
我们将首先考虑更简单的FreeBSD案例,然后是Debian。
FreeBSD提供了在系统范围和单个服务中启用pam_ssh的示例。我不想使用pam_ssh在我的工作站上或通过串行线对FTP服务器进行身份验证,所以我不会在系统范围内启用它。但是,我确实想在图形控制台登录期间使用它。 /etc/pam.d/xdm 文件已将pam_ssh的条目注释掉。取消对它们的注释为我们提供了这些身份验证和会话策略。
xxxxxxxxxx
auth sufficient pam_ssh.so no_warn try_first_pass
auth required pam_unix.so no_warn try_first_pass
session required pam_ssh.so want_agent
session required pam_lastlog.so no_fail
身份验证策略只有两条语句。第一个pam_ssh就足够了。登录将提示用户输入其SSH密钥的密码。如果密码短语正确,则充分(sufficient)语句意味着立即授予访问权限。no_warn标志禁用警告。try_first_pass标志告诉pam_ssh尝试任何早期的密码。由于这是策略中的第一条声明,因此不会有更早的密码。
pam_unix的第二个auth语句用于针对 /etc/passwd 的传统unix身份验证。仅当pam_ssh失败时,才会触发此身份验证规则。使用try_first_pass参数,此模块尝试将之前输入的SSH密钥短语用作Unix系统密码。如果您不小心输入了密码而不是密码短语,系统会让您进入。
综上所述,这意味着首先会提示用户输入用户名和SSH密码。如果他没有输入正确的密码,系统会提示他输入用户名和密码。
在会话策略中,pam_ssh模块设置用户的ssh代理。want_agent选项是FreeBSD特有的,在FreeBSD一节中进行了讨论。会话策略还使用pam_lastlog执行日志记录。
其他X管理器,如Gnome的gdm,在其 /usr/local/etc/pam.d 文件中需要类似的PAM规则条目。
对于部署pam_ssh的完全不同的看法,请考虑Debian。
当你在Debian上安装libpam-ssh时,该软件包会自动将pam_ssh规则添加到 /etc/pam.d/common-auth 和 /etc/pam.d/common-session 中。这将为使用通用规则的每个服务启用SSH密钥身份验证。如果该主机运行Telnet或FTP服务器,它们将根据用户的SSH密钥进行身份验证,并以明文形式在网络上传输用户的密码。
这是Debian的 /etc/pam.d/common-auth ,注释已删除。虽然Debian管理员应该阅读这些评论,但我们可以在没有这些评论的情况下研究PAM策略。
xxxxxxxxxx
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
auth optional pam_ssh.so use_first_pass
第一条语句调用pam_unix对密码文件执行传统身份验证。它使用扩展的Linux控件,而不是标准的PAM控件。如果用户输入了正确的用户名和密码,PAM将跳过策略中的一条语句。在任何其他响应中,pam_unix模块都会被忽略,我们将执行第二条语句。
第二条语句调用pam_deny,它立即拒绝任何身份验证尝试。这是一条必要的规则,所以拒绝会立即发生。乍一看,这看起来很荒谬——为什么在政策开始时就自动拒绝一切?然而,到达该语句的唯一方法是无法通过pam_unix的密码身份验证。如果倒霉的用户在第一条语句中成功通过身份验证,身份验证策略将跳过此步骤。
第三条语句使用pam_permit。如果用户在规则一中成功地使用用户名和密码进行了身份验证,他们就会被丢弃在这里。这是一个必需的规则,但调用pam_permit总是成功的。前三条语句作为一个整体,意味着“用户必须使用用户名和密码进行身份验证,否则他们的登录将被拒绝。”
第四条语句调用pam_ssh模块。这是可选的——用户不必输入正确的SSH密码即可登录。用户名和密码就足够了。不过,所示的标准Debian pam_ssh语句使用了use_first_pass选项。这个命令告诉PAM回收用户之前输入的密码,并将其提供给PAM_ssh。如果密码不适用于pam_ssh,请不要再次提示。
结果是,Debian的标准配置假定您的SSH密码短语(passphrase)与密码(password)相同。长期在Debian上尝试pam_ssh的SSH用户会发现这令人惊讶。密码短语应该比密码长得多:这就是为什么它们是短语(phrases)而不是单词(words)。
如果您在Debian上使用pam_ssh,并且不想使用单个单词作为ssh密码短语,您可以从pam_ssh auth语句中删除use_first_pass选项,或者将密码更改为密码短语。Debian允许您使用非常长的密码。
现在让我们快速看看会话规则:
xxxxxxxxxx
session [default=1] pam_permit.so
session requisite pam_deny.so
session required pam_permit.so
session required pam_unix.so
session optional pam_ssh.so
session optional pam_tmpdir.so
前三条语句与auth策略中的第一条语句相似。有一个必要的pam_deny,但你永远无法触及它。真正的规则始于第四条语句,它调用pam_unix来设置用户的环境。对于pam_ssh,规则五启用用户的ssh代理。最后一条语句调用pam_tmpdir为用户配置一个安全的临时目录。
为什么FreeBSD和Debian对类似的功能有如此大的不同政策?部分原因是Debian的策略旨在对 pam-auth-update(8)
pam配置工具友好。FreeBSD假设您将编辑自己的PAM规则,因此您了解每种类型的语句的作用。
不过,另一个关键区别是,操作系统打包者对模块的使用方式做出了不同的假设。FreeBSD的开发人员认为通过用户的SSH密钥进行身份验证就足够了,完全跳过了对系统密码文件的身份验证。另一方面,Debian要求用户根据密码文件进行身份验证,但它假设用户的密码短语与他们的密码相同。
这里真正的问题是“假设”——assumes这个词。
如果你听说了一个很酷的PAM模块并试图部署它,你必须仔细检查你的假设、模块作者的假设以及为你的操作系统打包模块的人所做的假设。如果你使用的是第三方文档,也要检查作者的假设。真正理解模块工作原理的唯一方法是逐一仔细阅读PAM策略。我曾多次部署FreeBSD的pam_ssh,但第一次在Debian上尝试pam_ssh时,它把我逼到了疯狂的边缘,直到我仔细地解开了pam配置。
PAM的假设会毁了你的一天、一周、一切,直到你仔细剖析你的配置。
说到假设:你也不能假设名为X的模块在平台之间是相同的,即使它们具有相似的功能。pam_ssh模块在FreeBSD、CentOS和Debian之间有所不同,我们稍后会看到。
一个正确的SSH密钥有一个几个单词或更长的密码短语。在正常使用过程中,您很少键入密码短语。然而,当你第一次尝试pam_ssh时,你可能会反复键入密码短语。我建议创建一个仅用于测试的SSH密钥,其中包含一个简单、易于键入的密码短语,以便在确定pam_SSH配置时使用。不要在任何服务器上安装测试密钥。一旦pam_ssh按预期工作,请擦除测试密钥。
您可能会问的下一个问题是,我的登录是否成功解密了我的密钥并将其添加到我的代理中?在像Debian这样的系统上,假设你的密码是你的密码短语,这是一个重要的细节。使用 ssh-add –l
检查代理中的密钥:
xxxxxxxxxx
$ ssh-add -l
2048 8c:f9:2d:…:91 testlab 2016-02-01 RSA
从这里开始,正常管理您的SSH会话和密钥。
当使用SSH密码短语进行身份验证时,没有密码短语的密钥就像没有密码的帐户。pam_ssh通常忽略没有密码短语的密钥:它不会将它们用于身份验证,也不会将它们添加到ssh代理中。
如果要允许使用没有密码的密钥进行身份验证,请在pam_ssh auth语句中使用 nullok 选项。所有三个pam_ssh版本都支持nullok。允许使用无密码短语密钥进行身份验证是一个糟糕的主意。这甚至比允许没有密码的帐户更糟糕,因为无密码短语密钥可能会授予其他主机访问权限。
所有这些pam_ssh实现都允许使用私钥文件 $HOME/.ssh/indentity 登录。此密钥文件用于SSH协议的版本1。这个版本不仅过时了,而且已经被破坏了。任何能够捕获您的流量的人都可以解密它。我们还没有完全处于“如果您正在运行SSHv1,请关闭它并启用Telnet;它可能不安全,但它不会假装安全”的阶段,但那一天很快就会到来。如果你有一个旧的SSHv1密钥,请验证你的SSH服务器是否都不支持SSHv1,仔细检查你的现代SSH密钥是否安装在任何地方,并将你的 identity 密钥降级到备份。
pam_ssh实现不支持 sshd(8)
使用的AuthorizedKeysCommand。AuthorizedKeysCommand选项仅提供公钥,不提供用于身份验证的私钥。您的私钥属于工作站,而不是网络。
FreeBSD附带了pam_ssh安装,/etc/pam.d 中的许多FreeBSD PAM配置都删除了auth和session pam_ssh条目。其中一些让我觉得很奇怪(使用pam_ssh对FTP进行身份验证,从而以明文形式传输您的密码?),但它们都不是强制性的。在 /etc/pam.d/login 或 /etc/pam.d/system 中激活这些登录尝试规则会更改用户的登录提示:
xxxxxxxxxx
login: mwl
SSH passphrase:
输入您的SSH密码。pam_ssh模块将尝试解密 .ssh 目录中的每个标准密钥文件: id_ecdsa 、 id_dsa 、id_rsa 和 identity 。如果您正确键入密码短语,则足够的控件会显示“允许登录,立即结束策略!”,您就可以访问。
pam_ssh支持第1章中讨论的常见调试、use_first_pass和try_first-pass选项。
当pam_ssh解密用户的密钥时,会话pam_ssh语句会启动一个ssh代理,并将解密后的密钥添加到代理中。但是,如果pam_ssh无法解密任何密钥,它就不会启动代理。相反,PAM直接进入会话策略中的下一个语句。最终结果是,如果用户使用SSH密码短语登录,他将获得一个SSH代理。如果他使用密码登录,则不会获得SSH代理。
不过,系统管理员可能希望使用密码登录的用户单方面获得SSH代理。将 want_agent 选项添加到pam_ssh会话语句中会触发在登录时启动ssh代理,即使没有向其中加载任何密钥。want_agents选项出现在注释掉的FreeBSD语句中。
FreeBSD的pam_ssh会自动尝试解密用户 $HOME/.ssh 目录中的密钥文件标识 id_rsa 、 id_dsa 和 id_ecdsa 。登录过程不会解密具有不同名称的密钥。
您无法从pam_ssh的检查中删除这些密钥中的任何一个。为此,您需要使用不同版本的pam_ssh,例如CentOS中的版本。
CentOS的EPEL存储库包含一个pam_ssh包。与FreeBSD和Debian不同,CentOS不包含任何PAM策略声明。您必须决定如何使用pam_ssh,并为您的身份验证和会话策略创建规则。
在这里,我将pam_ssh添加到 /etc/pam.d/login 中,这是CentOS 7.2的纯文本控制台登录的pam配置。我们将从身份验证策略开始:
xxxxxxxxxx
auth [user_unknown=ignore success=ok ignore=ignore default=bad] \
pam_securetty.so
auth [success=1 default=ignore] pam_ssh.so
auth substack system-auth
auth include postlogin
身份验证策略中的第一条语句是安全终端的常用pam_securetty规则检查。
第二条语句将pam_ssh插入到策略中。然而,我没有使用标准控件,而是使用了Linux-PAM扩展控件。如果pam_ssh返回除PAM_SUCCESS之外的任何内容,我们将忽略pam_ssh,策略将正常进行。如果用户成功输入了她的密码短语,并且pam_ssh可以解密用户的私钥,pam将跳过下一个规则。
下一个规则是正常系统身份验证的子步骤。为pam_ssh提供一个有效的密码短语,可以让策略跳过整个正常的Unix风格的身份验证过程。
最后一条规则包括正常的登录后处理。无论用户是使用密码短语还是密码登录,CentOS都会执行其日志记录和记帐。
会话规则更简单。将pam_ssh语句放在包含系统身份验证文件之前,以便在设置环境的其余部分之前启动ssh代理。它真的可以在pam_selinux.so开放规则之后的会话策略中的任何地方。
xxxxxxxxxx
…
session optional pam_ssh.so
session include system-auth
…
在PAM级别,您已经准备好了。
不过,在现代CentOS上,您几乎可以肯定使用的是SELinux。如果您的SSH代理有问题,请检查 /var/log/secure 。启动代理时的权限错误几乎肯定与SELinux有关。第6章以pam_ssh为例讨论了修复SELinux相关的PAM问题。
与OpenPAM不同,CentOS的pam_ssh不会向用户显示“密码短语(passphrase)”提示。用户看到的是始终出现的密码提示。CentOS使pam_ssh变得隐秘。用户需要知道输入他们的SSH密码短语是一个选项。
根据本节前面给出的语句,未输入密码短语的用户将其身份验证尝试转移到系统身份验证子包,其中pam_unix的try_first_pass选项意味着它将尝试使用用户输入的任何内容作为密码。
使用 keyfiles 选项指定pam_ssh尝试解密的SSH私钥文件。CentOS默认检查 id_dsa 、 id_rsa 和 identity 文件。identity 文件仅用于长期损坏的SSH版本1协议,我建议您在pam_ssh中禁用它。
xxxxxxxxxx
auth [success=1 default=ignore] pam_ssh.so keyfiles=id_dsa,id_rsa
您可以根据需要在此处添加非标准密钥文件。
如果你想要复杂的密钥选择,请查看Debian的pam_ssh。
Debian在libpam-ssh软件包中提供了pam_ssh。我们在本章前面详细讨论了Debian的pam_ssh策略,所以让我们直接进入该模块的工作原理。请记住,Debian的默认pam_ssh配置要求您的ssh密码与密码相同。
Debian的pam_ssh的有趣之处在于,它为用户提供了对哪些密钥可用于身份验证以及哪些密钥被添加到ssh代理的极大控制。
Debian的pam_ssh忽略了所有常用的密钥文件,而是依赖于目录 $HOME/.ssh/login-keys.d 和 $HOME/.ssh/session-keys.d 。这些目录默认不存在;用户必须创建它们。
login-keys.d 目录包含可用于身份验证的SSH私钥文件。这里的文件可以是实际的私钥,也可以是密钥文件的符号链接。在这里,我进入我的登录密钥目录,并链接到我的标准SSH密钥。
xxxxxxxxxx
$ cd .ssh/login-keys.d
$ ln -s ../id_rsa
当我登录系统时,pam_ssh会检查此目录。它试图使用用户提供的密码来解密它找到的任何私钥。它将任何可以解密的密钥添加到用户的SSH代理中。
session keys.d 目录还包含密钥文件或指向密钥的符号链接。不过,与login-keys.d中的文件不同,pam_ssh不会使用这些密钥文件进行身份验证。然而,一旦用户进行了身份验证,pam_ssh就会尝试使用密码解密会话目录中的密钥。它将解密密钥添加到代理中。
也许你不想要一个长密码,而是只依靠密码短语来访问控制台。这将使您能够将FTP等明文协议的身份验证方法与通过SSH或控制台登录的方法分开。您可以通过重新安排Debian的身份验证策略来实现这一点。
xxxxxxxxxx
auth sufficient pam_ssh.so
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
在这里,我已经将pam_ssh规则移动到了身份验证策略的顶部,甚至在pam_unix之前。我可以使用Linux-PAM扩展控件,就像pam_unix语句一样,但足以表达我想要的行为。
实际上,由于我手动编辑此文件,因此使其不适合自动化管理,我更有可能重做整个策略并删除永远无法命中的语句。
xxxxxxxxxx
auth sufficient pam_ssh.so
auth required pam_unix.so nullok_secure
如果用户无法使用SSH密钥进行身份验证,则必须使用密码进行身份验证。我发现这更容易理解。在我的个人工作站上,我甚至可能将pam_ssh设置为必需,并完全放弃pam_unix规则。
不过,其他人并不像我那样注重安全。他们的机器需要一些东西来确保他们有一个像样的密码,我们将在下一章中看到。