![如何使用所有 3 个组件配置 SSH 身份验证:公钥、密码和 OTP](https://linux22.com/image/231017/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E6%89%80%E6%9C%89%203%20%E4%B8%AA%E7%BB%84%E4%BB%B6%E9%85%8D%E7%BD%AE%20SSH%20%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%EF%BC%9A%E5%85%AC%E9%92%A5%E3%80%81%E5%AF%86%E7%A0%81%E5%92%8C%20OTP.png)
更新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_code
在common-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
一些逐行解释:
pam_faillock.so
与preauth
和 一起使用requisite
将检查用户的状态。如果用户被锁定,则阻止密码提示。接下来是一些faillock
您可以签入的配置这里。- 用于
pam_unix.so
检查用户的密码。[success=1]
如果密码正确,将跳过下一行。try_first_pass
使用第一步的输入。 pam_faillock.so
withauthfail
将记录失败的尝试,并阻止身份验证过程进一步进行[default=die]
。如果您希望用户不知道哪里出了问题(密码或 OTP),则交换第 3 行和第 4 行。- 用于
pam_google_authenticator.so
检查 OTP。您可以找到更多信息这里。[success=2]
如果 OTP 正确,将跳过接下来的两行。 pam_faillock.so
带authsucc
标记的这次尝试是好的,会清除不良的尝试记录,让用户可以走得更远。pam_deny.so
withrequisite
将拒绝登录尝试。因此,如果信息正确,上面的某些行会跳过此行。pam_permit.so
只需在完成上述所有检查后允许访问即可。
第二:编辑/etc/pam.d/common-account
并在开头添加此行以使用faillock
:
account required pam_faillock.so
第三:编辑/etc/pam.d/sshd
SSH 连接。我没有对默认配置进行任何更改,只是将其列在这里供大家比较。
@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
一些关键项目:
KbdInteractiveAuthentication
=yes
使用keyboard-interactive
方法。ChallengeResponseAuthentication
是一个已弃用的别名。UsePAM
必须设置为yes
使用上面的所有 PAM 配置- 在 中
AuthenticationMethods
,我仅声明keyboard-interactive
密码和 OTP 提示。
编辑文件后sshd_config
,重新加载sshd
服务以更新新配置。
systemctl reload sshd
像这样,我可以检查所有public key + password (of the user) + OTP
.