使用 Google 身份验证器进行 SSH 公钥身份验证仍然要求输入密码

使用 Google 身份验证器进行 SSH 公钥身份验证仍然要求输入密码

我正在尝试使用 libpam-google-authenticator 通过 ssh 启用 2FA。并非所有用户都需要启用身份验证器。每个人都使用 ssh 公钥,没有人有密码。我正在运行 Debian buster,我也尝试过 bullseye 的 libpam-google-authenticator。

我的问题是,无论我在 PAM 配置中输入什么,未启用身份验证器的用户永远不会直接登录,但总是要求输入密码

我已经安装了 libpam-google-authenticator 并使用以下命令配置了 /etc/ssh/sshd_config:

PasswordAuthentication no
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
PasswordAuthentication no
PermitEmptyPasswords no

我无法制定正确的 PAM 配置,以便没有 .google_authenticator 文件的用户仍可登录。根据我使用的方式,要么提示用户输入密码(他们没有密码),要么根本不允许登录。

在 /etc/pam.d/sshd 中我尝试过(像这样尝试在 Ubuntu 14.04.1 上使用公钥(无密码)+ Google 身份验证器进行 SSH):

#@include common-auth
auth       required     pam_google_authenticator.so debug nullok

在这种情况下,未设置身份验证器的用户将被拒绝,并出现以下调试;

Aug 05 15:11:18 <host> sshd(pam_google_authenticator)[746624]: debug: start of google_authenticator for "<user>"
Aug 05 15:11:18 <host> sshd(pam_google_authenticator)[746624]: debug: end of google_authenticator for "<user>" Result: The return value should be ignored by PAM dispatch
Aug 05 15:11:18 <host> sshd[746620]: error: PAM: Permission denied for <user> from <IP>

是否pam_permit需要设置后备案例?

我也尝试过前后的各种组合auth requiredauth sufficient@include common-auth它们都导致没有身份验证器的用户被要求输入密码,有时也要求有身份验证器的用户输入密码。

有人有办法实现这个效果吗?

答案1

这是我的工作配置。有些用户启用了身份验证器,有些则没有,并且只允许使用公钥进行 SSH 登录,而不允许使用密码。

在 /etc/ssh/sshd_config 中,

UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
PermitEmptyPasswords no

在 /etc/pam.d/sshd 中,

# Standard Un*x authentication.
#@include common-auth

# Require authenticator, if not configured then allow
auth    required    pam_google_authenticator.so debug nullok
auth    required    pam_permit.so

@include comon-auth必须禁用,因为它包含 pam_unix,我不想使用它。然后您需要pam_permit让没有身份验证器的用户身份验证成功(pam_google_authenticator返回 ignore 而不是 pass)。

这仍然不允许 root 使用 ssh 密钥登录;sshd 日志

sshd[1244501]: fatal: Internal error: PAM auth succeeded when it should have failed

讨论SSH 上的 Google Authenticator PAM 阻止没有 2FA 的 root 登录

按照上述方法操作后,我认为使用 SSH 配置对某些组强制实施 2FA 实际上更好,正如 @zoredache 所建议的那样。这让您可以轻松地将某些 IP 列入白名单,使其不需要 2FA。在这种情况下,sshd_config 例如说

UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
#AuthenticationMethods any # default
PermitEmptyPasswords no

Match Group adm Address *,!172.16.1.0/24
    AuthenticationMethods publickey,keyboard-interactive

并且 /etc/pam.d/ssh 说

 Standard Un*x authentication.
#@include common-auth

# Require authenticator; SSH should not allow any user in who doesn't have it
auth       sufficient   pam_google_authenticator.so debug nullok
auth       requisite    pam_deny.so

答案2

我认为您不需要或不想注释掉@include common-auth。或者至少我没有这样做,而且它似乎可以正常工作。但我仍在测试这一点。

有人有办法实现这个效果吗?

没有时间为您将其翻译成 shell 脚本,但这是 ansible playbook 的摘录,似乎对我有用。我想即使您不使用 ansible,您也应该能够理解它正在做什么。

- hosts: linux_systems
  tasks:

  - name: Add group 'totp'
    group:
      name: totp
      state: present
      system: yes

  - name: Create directory for totp secrets
    file:
      state: directory
      path: /var/lib/google-authenticator
      owner: "0"
      group: "0"
      mode: "0700"

  - name: install libpam-google-authenticator
    apt:
      update_cache: yes
      cache_valid_time: '{{ apt_cache_valid_time | default(7200) }}'
      state: present
      name:
      - libpam-google-authenticator

  - name: Create secret for 'example-user'
    args:
      creates: /var/lib/google-authenticator/example-user
    shell: |
      TOTP_USER=example-user; \
      google-authenticator \
        --force --quiet \
        --emergency-codes=10 \
        --time-based \
        --qr-mode=none \
        --allow-reuse \
        --window-size=3 \
        --rate-limit=4 --rate-time=30 \
        --secret=/var/lib/google-authenticator/${TOTP_USER}

  - name: update pam
    lineinfile:
      insertafter: '^@include common-password'
      path: /etc/pam.d/login
      line: 'auth required pam_google_authenticator.so nullok user=root secret=/var/lib/google-authenticator/${USER}'

  - name: update pam
    lineinfile:
      insertafter: '^@include common-password'
      path: /etc/pam.d/sshd
      line: 'auth required pam_google_authenticator.so nullok user=root secret=/var/lib/google-authenticator/${USER}'

  - name: update sshd ChallengeResponseAuthentication
    notify: Restart sshd
    lineinfile:
      path: /etc/ssh/sshd_config
      regexp: '^ChallengeResponseAuthentication .*'
      line: 'ChallengeResponseAuthentication yes'

  handlers:

  - name: Restart sshd
    service:
      name: sshd
      state: restarted

相关内容