OpenSSH 与 Kerberos/公钥相结合的双因素身份验证

OpenSSH 与 Kerberos/公钥相结合的双因素身份验证

我正在尝试为 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 代码。

Duo Unix 配置

答案2

  • 拥有现有有效 Kerberos 票证的用户仅需提供第二个因素。

这无法通过 PAM 实现。

针对 sshd 执行的成功基于密钥的身份验证会绕过authPAM 堆栈。这包括 GSSAPI,这是基于票证的 Kerberos 身份验证的必要条件。它别无选择,只能这样做,因为 PAM 在设计时根本没有考虑这种类型的身份验证。

设置UsePAM yes执行以下操作:

  • ChallengeResponseAuthentication并将PasswordAuthentication挂接authPAM 堆栈以验证密码。除这两种方法之外的任何形式的身份验证都将不是触摸auth堆栈。
  • 身份验证成功后,account将调用 PAM 堆栈来确定是否允许经过身份验证的用户访问。(总是)
  • 将调用 PAM堆栈session来处理会话设置任务。

auth摘要:对于使用 GSSAPI 或 ssh 密钥进行身份验证的用户,绝对没有办法触发位于堆栈内的双因素身份验证提示。您可以将accountsession堆栈与这些身份验证方法结合使用,但 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

相关内容