我正在尝试为 OpenSSH 实现双因素身份验证。环境是 Centos 7(内核:3.10.0-229.1.2.el7.x86_64),带有 OpenSSH_6.6.1p1、OpenSSL 1.0.1e-fips 2013 年 2 月 11 日。我们部署了 Active Directory(LDAP)+ Kerberos。规范如下:
- 仅需向具有现有有效 Kerberos 票证的用户询问第二个因素
- 如果用户没有现有的有效 Kerberos 票证,则必须同时要求其输入密码和第二个因素
- 本地用户(无 LDAP 帐户)应该能够使用其本地密码进行身份验证
- 第二个因素不能在第一个因素之前提供
- 除了 Kerberos 之外,如果可用,公钥身份验证也应被接受为第一因素
- 该功能应该能够限制在一组用户中 - 其他用户只需输入密码即可进入
为了执行第二因素的身份验证过程,可以使用第三方 PAM 模块,该模块对 Kerberos 一无所知。因此,我做了以下操作:
将这些行放入 /etc/ssh/sshd_config:
# To enable PAM - this will make sshd use PAM with configuration /etc/pam.d/sshd
UsePam yes
ChallengeResponseAuthentication yes
# To enable Kerberos and public key authentication - it will let sshd use existing Kerberos tickets
GSSAPIAuthentication yes
# Enable public key authentication
PubkeyAuthentication yes
# Password validation should be done via the KDC
PasswordAuthentication yes
KerberosAuthentication yes
KerberosOrLocalPasswd yes
# Kerberos / Public Key + PAM
AuthenticationMethods gssapi-with-mic,keyboard-interactive:pam publickey,keyboard-interactive:pam password,keyboard-interactive:pam
# (only supported for OpenSSH 6.2 or higher)
sshd 的 PAM 配置的 auth 部分(/etc/pam.d/sshd)
auth [success=ignore default=1] pam_localuser.so
auth substack password-auth
auth [success=1 default=ignore] pam_localuser.so
auth required pam_2fa.so [...some arguments...]
auth include postlogin
模块 pam_2fa.so 负责提示和验证第二个因素。
现在对于 Kerberos,这几乎可以实现我想要实现的所有功能。但是,对于本地帐户,它会导致两次连续的密码提示。这是我的主要问题。这是因为在这种情况下,路径“password,keyboard-interactive:pam”被使用,正如预期的那样。(我需要这个身份验证路径,以便拥有 Kerberos 帐户但没有有效票证的人可以通过输入密码然后输入 OTP 来获取票证。)如果我从 PAM 配置中完全删除密码身份验证子堆栈,那么 Kerberos 帐户将继续工作,而本地帐户仍然无法工作。对我来说,似乎 KerberosOrLocalPasswd yes 语句被忽略了,因为 UsePAM yes 也存在。但是,sshd 确实继续使用 KDC 进行密码验证,因为否则它也不会适用于 LDAP 帐户。
因此,为了进一步阐明我希望实现的内容,这里给出了描述所需身份验证逻辑的伪代码:
if gssapi_auth_ok(principal) or pubkey_auth_ok(pubkey):
return second_factor_auth(user, read_otp())
else:
if is_local_account(user):
if local_passwd_auth(user, read_password()):
return second_factor_auth(user, read_otp())
else:
return AUTH_ERR
else:
if krb5_auth(principal, read_password()):
return second_factor_auth(user, read_otp())
return AUTH_ERR
所以我认为我的方案并不太复杂或过于雄心勃勃,但尽管我花了几天时间研究和试验,我仍然找不到明确的实现方法。你能帮我找到解决方案吗?
提前非常感谢您!
答案1
我不知道有什么方法可以在不编写新 pam 模块的情况下使用 PAM 实现您想要的功能。PAM 相对复杂,并且根据我的经验,sshd 与 PAM 和 kerberos 交互的方式总是存在无法正常工作的极端情况。
你想要的可能是可能的,我只是不知道怎么做。如果你只需要保护 ssh,我建议使用
ForceCommand /path/to/2fa_executable
在您的 sshd_config 中。这将允许您实现所需的逻辑,缺点是 2fa_executable 需要设置为 setuid 才能读取任何 2fa 机密。
Duo Security 网站上有一个示例和代码。您可以使用 duo setuid 包装器和您正在使用的任何 2fa 代码。
答案2
- 拥有现有有效 Kerberos 票证的用户仅需提供第二个因素。
这无法通过 PAM 实现。
针对 sshd 执行的成功基于密钥的身份验证会绕过auth
PAM 堆栈。这包括 GSSAPI,这是基于票证的 Kerberos 身份验证的必要条件。它别无选择,只能这样做,因为 PAM 在设计时根本没有考虑这种类型的身份验证。
设置UsePAM yes
执行以下操作:
ChallengeResponseAuthentication
并将PasswordAuthentication
挂接auth
PAM 堆栈以验证密码。除这两种方法之外的任何形式的身份验证都将不是触摸auth
堆栈。- 身份验证成功后,
account
将调用 PAM 堆栈来确定是否允许经过身份验证的用户访问。(总是) - 将调用 PAM堆栈
session
来处理会话设置任务。
auth
摘要:对于使用 GSSAPI 或 ssh 密钥进行身份验证的用户,绝对没有办法触发位于堆栈内的双因素身份验证提示。您可以将account
和session
堆栈与这些身份验证方法结合使用,但 PAM 只能做到这一点。
答案3
以下是如何操作的说明https://cern-cert.github.io/pam_2fa/
- 基础:使用 pam 进行双因素身份验证
一个更了解 ssh 身份验证方法的 pam 模块:
auth [成功=2 忽略=忽略默认=die] pam_ssh_user_auth.so
最新或已打补丁的 OpenSSH 可将其暴露给 pam
身份验证方法 gssapi-with-mic、键盘交互:pam publickey、键盘交互:pam 键盘交互:pam