如何使用所有 3 个组件配置 SSH 身份验证:公钥、密码和 OTP

如何使用所有 3 个组件配置 SSH 身份验证:公钥、密码和 OTP

更新1:我可以使用/etc/pam.d/common-auth.

auth [success=ok] pam_unix.so
auth [success=1] pam_google_authenticator.so nullok echo_verification_code  [authtok_prompt=Enter your OTP:]
auth    requisite                       pam_deny.so
auth    required                        pam_permit.so

我会尝试将pam_faillock.so其作为原来的计划应用。


原问题:

我正在使用 Debian 10 和 12,并且希望我的用户只有在匹配公钥的情况下才能成功通过 SSH 连接到服务器,然后输入密码,然后使用 OTP(谷歌身份验证器)。简而言之,SSH 应该需要公钥+密码+OTP。

publickey + password我已经成功配置了or的组合publickey + OTP,但仍然很难将这三个组合起来。

请帮我配置一下。

到目前为止我的尝试:

/etc/pam.d/common-auth

auth    required       pam_faillock.so preauth audit silent deny=5 unlock_time=1800
auth    sufficient     pam_unix.so try_first_pass
auth    [default=die]  pam_faillock.so authfail audit deny=5 fail_interval=120 unlock_time=1800
auth    sufficient     pam_faillock.so authsucc audit deny=5 fail_interval=120 unlock_time=1800
auth    required [success=1] pam_google_authenticator.so echo_verification_code
auth    requisite      pam_deny.so
auth    required       pam_permit.so

/etc/pam.d/sshd

@include common-auth
account    required     pam_nologin.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so close
session    required     pam_loginuid.so
session    optional     pam_keyinit.so force revoke
@include common-session
session    optional     pam_motd.so  motd=/run/motd.dynamic
session    optional     pam_motd.so noupdate
session    optional     pam_mail.so standard noenv # [1]
session    required     pam_limits.so
session    required     pam_env.so # [1]
session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open
@include common-password

/etc/ssh/sshd_config

Include /etc/ssh/sshd_config.d/*.conf
MaxAuthTries 5
MaxSessions 1
PubkeyAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords no
KbdInteractiveAuthentication yes
UsePAM yes
X11Forwarding yes
PrintMotd no
ClientAliveInterval 60
ClientAliveCountMax 15
AcceptEnv LANG LC_*
Subsystem       sftp    /usr/lib/openssh/sftp-server
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,password,keyboard-interactive

尝试连接时:ssh -i <key_path> user@server -vvv

debug1: Authentications that can continue: publickey
debug3: start over, passed a different list publickey
debug3: preferred publickey,keyboard-interactive,password
debug3: authmethod_lookup publickey
debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Trying private key: <key_path>
debug3: sign_and_send_pubkey: 
debug3: sign_and_send_pubkey: signing using rsa-sha2-512
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 51
Authenticated with partial success.
debug1: Authentications that can continue: password
debug3: start over, passed a different list password
debug3: preferred publickey,keyboard-interactive,password
debug3: authmethod_lookup password
debug3: remaining preferred: ,keyboard-interactive,password
debug3: authmethod_is_enabled password
debug1: Next authentication method: password
user@server's password:
debug3: send packet: type 50
debug2: we sent a password packet, wait for reply
debug3: receive packet: type 51
Authenticated with partial success.
debug1: Authentications that can continue: keyboard-interactive
debug3: start over, passed a different list keyboard-interactive
debug3: preferred publickey,keyboard-interactive,password
debug3: authmethod_lookup keyboard-interactive
debug3: remaining preferred: password
debug3: authmethod_is_enabled keyboard-interactive
debug1: Next authentication method: keyboard-interactive
debug2: userauth_kbdint
debug3: send packet: type 50
debug2: we sent a keyboard-interactive packet, wait for reply
debug3: receive packet: type 60
debug2: input_userauth_info_req: entering
debug2: input_userauth_info_req: num_prompts 1
(user@server) Password:
debug3: send packet: type 61
debug3: receive packet: type 51
debug1: Authentications that can continue: keyboard-interactive
debug2: userauth_kbdint
debug3: send packet: type 50
debug2: we sent a keyboard-interactive packet, wait for reply
debug3: receive packet: type 60
debug2: input_userauth_info_req: entering
debug2: input_userauth_info_req: num_prompts 1
(user@server) Password:
debug3: send packet: type 61
debug3: receive packet: type 51
debug1: Authentications that can continue: keyboard-interactive
debug2: userauth_kbdint
debug3: send packet: type 50
debug2: we sent a keyboard-interactive packet, wait for reply
debug3: receive packet: type 60
debug2: input_userauth_info_req: entering
debug2: input_userauth_info_req: num_prompts 1
(user@server) Password:
debug3: send packet: type 61
debug3: receive packet: type 51
debug1: Authentications that can continue: keyboard-interactive
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
user@server: Permission denied (keyboard-interactive).

在此输入图像描述

它在步骤 3(键盘交互)中失败,并且有些事情与正常的 OTP 验证不同:

  • 它没有要求,Verification code:而只是要求(user@server) Password:
  • 尽管echo_verification_codecommon-auth.

P/s:我还配置了pam_faillock.so在登录尝试失败时锁定用户。

答案1

经过一番尝试,并感谢这个帖子,我可以添加pam_faillock.so到我的解决方案中以检查日志记录尝试并在需要时锁定用户。

当心在编辑下面那些与身份验证相关的文件时。总是进行备份首先是文件。和记住保持一个 root 会话处于活动状态,并在另一个会话中测试您的登录。

让我们看看我的配置文件:

第一的:编辑/etc/pam.d/common-auth适用于各种登录方式:

auth    requisite       pam_faillock.so preauth audit deny=5 fail_interval=120 unlock_time=1800
auth    [success=1]     pam_unix.so try_first_pass
auth    [default=die]   pam_faillock.so authfail audit deny=5 fail_interval=120 unlock_time=1800
auth    [success=2]     pam_google_authenticator.so nullok echo_verification_code  [authtok_prompt=Enter your OTP:]
auth    sufficient      pam_faillock.so authsucc audit deny=5 fail_interval=120 unlock_time=1800
auth    requisite       pam_deny.so
auth    required        pam_permit.so

一些逐行解释:

  1. pam_faillock.sopreauth和 一起使用requisite将检查用户的状态。如果用户被锁定,则阻止密码提示。接下来是一些faillock您可以签入的配置这里
  2. 用于pam_unix.so检查用户的密码。[success=1]如果密码正确,将跳过下一行。try_first_pass使用第一步的输入。
  3. pam_faillock.sowithauthfail将记录失败的尝试,并阻止身份验证过程进一步进行[default=die]。如果您希望用户不知道哪里出了问题(密码或 OTP),则交换第 3 行和第 4 行。
  4. 用于pam_google_authenticator.so检查 OTP。您可以找到更多信息这里[success=2]如果 OTP 正确,将跳过接下来的两行。
  5. pam_faillock.soauthsucc标记的这次尝试是好的,会清除不良的尝试记录,让用户可以走得更远。
  6. pam_deny.sowithrequisite将拒绝登录尝试。因此,如果信息正确,上面的某些行会跳过此行。
  7. pam_permit.so只需在完成上述所有检查后允许访问即可。

第二:编辑/etc/pam.d/common-account并在开头添加此行以使用faillock

account required        pam_faillock.so

第三:编辑/etc/pam.d/sshdSSH 连接。我没有对默认配置进行任何更改,只是将其列在这里供大家比较。

@include common-auth
account    required     pam_nologin.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so close
session    required     pam_loginuid.so
session    optional     pam_keyinit.so force revoke
@include common-session
session    optional     pam_motd.so  motd=/run/motd.dynamic
session    optional     pam_motd.so noupdate
session    optional     pam_mail.so standard noenv # [1]
session    required     pam_limits.so
session    required     pam_env.so # [1]
session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open
@include common-password

第四:编辑/etc/ssh/sshd_config配置SSH会话

Include /etc/ssh/sshd_config.d/*.conf
MaxAuthTries 5
MaxSessions 1
PubkeyAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords no
KbdInteractiveAuthentication yes
UsePAM yes
X11Forwarding yes
PrintMotd no
ClientAliveInterval 60
ClientAliveCountMax 15
AcceptEnv LANG LC_*
Subsystem       sftp    /usr/lib/openssh/sftp-server
AuthenticationMethods publickey,keyboard-interactive

一些关键项目:

  1. KbdInteractiveAuthentication=yes使用keyboard-interactive方法。ChallengeResponseAuthentication是一个已弃用的别名。
  2. UsePAM必须设置为yes使用上面的所有 PAM 配置
  3. 在 中AuthenticationMethods,我仅声明keyboard-interactive密码和 OTP 提示。

编辑文件后sshd_config,重新加载sshd服务以更新新配置。

systemctl reload sshd

像这样,我可以检查所有public key + password (of the user) + OTP.

相关内容