TL;DR:我以 root 用户身份登录时运行了 google-authenticator。我应该以普通用户帐户运行它。
我刚刚在一台备用的 Apple Mac Mini 上安装了 Debian 12。我想通过 SSH 从我的 iMac 控制它。我想使用带有密码的 SSH 密钥,还希望使用 Google Authenticator 进行多因素身份验证。
在 iMac 上,我使用ssh-keygen -t rsa创建了 ssh 密钥并指定了密码。然后我使用ssh-copy-id [email protected]将公钥复制到远程 Debian 服务器上。
然后我想禁用仅密码登录,因此我在 /etc/ssh/sshd_config 末尾添加了以下两行:
Match User david
PasswordAuthentication no
然后我运行systemctl restart sshd并退出远程机器。然后我尝试重新登录,系统要求我输入密码,但没有输入密码。到目前为止一切顺利。
然后我按照以下两个指南设置了 Google Authenticator: 指南 1 指南 2
(我以 root 用户身份登录,因此不需要在开始所有操作时添加 sudo...)
具体来说:
apt install -y libpam-google-authenticator
google-authenticator
(answered yes to all four questions asked by Google Authenticator setup)
nano /etc/ssh/sshd_config
->Set UsePAM yes
->Added a line at the end of the file "ChallengeResponseAuthentication yes"
->Added another line at the end of the file "AuthenticationMethods publickey,keyboard-interactive"
->Saved and closed /etc/ssh/sshd_config
nano /etc/pam.d/sshd
->Commented out the line "@include common-auth"
->Added a line at the end of the file "auth required pam_google_authenticator.so"
->Saved and closed /etc/pam.d/sshd
systemctl restart ssh
然后,我尝试使用 iMac 上的其他终端窗口登录,但出现以下错误:
收到来自 192.168.4.7 端口 22:2 的断开连接:未启用身份验证方法
已断开与 192.168.4.7 端口 22 的连接
我可以恢复对这两个文件的更改,然后仅使用密码重新连接。但是,我无法让它要求我输入密码和 Google Authenticator 代码。
请问我做错了什么?
我发现了类似的问题,但唯一的答案没有提供足够的细节。
然后确保您的配置需要 PAM 身份验证(如果公钥身份验证方法成功,则跳过 PAM 密码身份验证部分)。您可以通过在 sshd_config 中设置适当的 AuthenticationMethods 来实现这一点。
不幸的是,他们没有解释如何在“sshd_config 中设置适当的 AuthenticationMethods”,所以这对我没有太大帮助……
先感谢您。
/etc/ssh/sshd_config 的完整内容:
Include /etc/ssh/sshd_config.d/*.conf
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
ChallengeResponseAuthentication yes
Match User david
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive
(加上一些其他我已省略的行,因为它们已被注释掉了)。
/etc/pam.d/sshd 的完整内容:
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
auth required pam_google_authenticator.so
(另外还有一些我省略的行,因为它们已被注释掉了)
在 Zoredache 在评论中建议检查日志后更新...
尝试连接到 Mac Mini 时,在 iMac 上运行ssh -vvv [email protected]的完整输出:
$ ssh -vvv [email protected]
OpenSSH_9.6p1, LibreSSL 3.3.6
[omitting a very long log file with no useful information as this website has a character limit and I would exceed it if I kept this here]
debug3: kex_input_ext_info: extension [email protected]
debug1: kex_ext_info_check_ver: [email protected]=<0>
debug3: receive packet: type 6
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug3: send packet: type 50
debug3: receive packet: type 1
Received disconnect from 192.168.4.7 port 22:2: no authentication methods enabled
Disconnected from 192.168.4.7 port 22
...没什么特别有用的。检查 Mac Mini 上的日志:
$ journalctl --since "1 hour ago"
Jul 09 06:50:05 docker1 sshd[10682]: error: Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive"
Jul 09 06:50:05 docker1 sshd[10682]: Authentication methods list "publickey,keyboard-interactive" contains disabled method, skipping
Jul 09 06:50:05 docker1 sshd[10682]: error: No AuthenticationMethods left after eliminating disabled methods
Jul 09 06:50:05 docker1 sshd[10682]: error: Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive" [preauth]
Jul 09 06:50:05 docker1 sshd[10682]: Authentication methods list "publickey,keyboard-interactive" contains disabled method, skipping [preauth]
Jul 09 06:50:05 docker1 sshd[10682]: error: No AuthenticationMethods left after eliminating disabled methods [preauth]
Jul 09 06:50:05 docker1 sshd[10682]: Disconnecting authenticating user david 192.168.4.6 port 50344: no authentication methods enabled [preauth]
Jul 09 06:53:00 docker1 sshd[10702]: error: Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive"
Jul 09 06:53:00 docker1 sshd[10702]: Authentication methods list "publickey,keyboard-interactive" contains disabled method, skipping
Jul 09 06:53:00 docker1 sshd[10702]: error: No AuthenticationMethods left after eliminating disabled methods
Jul 09 06:53:00 docker1 sshd[10702]: error: Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive" [preauth]
Jul 09 06:53:00 docker1 sshd[10702]: Authentication methods list "publickey,keyboard-interactive" contains disabled method, skipping [preauth]
Jul 09 06:53:00 docker1 sshd[10702]: error: No AuthenticationMethods left after eliminating disabled methods [preauth]
Jul 09 06:53:00 docker1 sshd[10702]: Disconnecting authenticating user david 192.168.4.6 port 50587: no authentication methods enabled [preauth]
啊哈!
进行了一些谷歌搜索,发现了这个,并特别注意到了关于“KbdInteractiveAuthentication”的引用。
然后我进入 /etc/ssh/sshd_config 并将 KbdInteractiveAuthentication
no 改为 yes。我还注释掉了该行,ChallengeResponseAuthentication yes
因为这似乎已被弃用。
systemctl restart sshd
然后我再次尝试登录。我越来越接近成功了;系统要求我输入密码和 Google Authenticator 代码。然而,Google Authenticator 代码一再被拒绝,我无法登录。
$ ssh -vvv [email protected]
OpenSSH_9.6p1, LibreSSL 3.3.6
debug1: Reading configuration data /Users/david/.ssh/config
debug1: /Users/david/.ssh/config line 1: Applying options for 192.168.4.7
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 21: include /etc/ssh/ssh_config.d/* matched no files
debug1: /etc/ssh/ssh_config line 54: Applying options for *
debug2: resolve_canonicalize: hostname 192.168.4.7 is address
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> '/Users/david/.ssh/known_hosts'
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> '/Users/david/.ssh/known_hosts2'
debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling
debug3: channel_clear_timeouts: clearing
debug3: ssh_connect_direct: entering
debug1: Connecting to 192.168.4.7 [192.168.4.7] port 22.
debug3: set_sock_tos: set socket 3 IP_TOS 0x48
debug1: Connection established.
debug1: identity file /Users/david/.ssh/docker1_id_rsa type 0
debug1: identity file /Users/david/.ssh/docker1_id_rsa-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_9.6
debug1: Remote protocol version 2.0, remote software version OpenSSH_9.2p1 Debian-2+deb12u3
debug1: compat_banner: match: OpenSSH_9.2p1 Debian-2+deb12u3 pat OpenSSH* compat 0x04000000
debug2: fd 3 setting O_NONBLOCK
debug1: Authenticating to 192.168.4.7:22 as 'david'
debug3: record_hostkey: found key type ED25519 in file /Users/david/.ssh/known_hosts:31
debug3: record_hostkey: found key type RSA in file /Users/david/.ssh/known_hosts:32
debug3: record_hostkey: found key type ECDSA in file /Users/david/.ssh/known_hosts:33
debug3: load_hostkeys_file: loaded 3 keys from 192.168.4.7
debug1: load_hostkeys: fopen /Users/david/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug3: order_hostkeyalgs: have matching best-preference key type [email protected], using HostkeyAlgorithms verbatim
debug3: send packet: type 20
debug1: SSH2_MSG_KEXINIT sent
debug3: receive packet: type 20
debug1: SSH2_MSG_KEXINIT received
debug2: local client KEXINIT proposal
debug2: KEX algorithms: [email protected],curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,ext-info-c,[email protected]
debug2: host key algorithms: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,[email protected],[email protected],rsa-sha2-512,rsa-sha2-256
debug2: ciphers ctos: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
debug2: ciphers stoc: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
debug2: MACs ctos: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
debug2: MACs stoc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
debug2: compression ctos: none,[email protected],zlib
debug2: compression stoc: none,[email protected],zlib
debug2: languages ctos:
debug2: languages stoc:
debug2: first_kex_follows 0
debug2: reserved 0
debug2: peer server KEXINIT proposal
debug2: KEX algorithms: [email protected],curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,[email protected]
debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519
debug2: ciphers ctos: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
debug2: ciphers stoc: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
debug2: MACs ctos: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
debug2: MACs stoc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
debug2: compression ctos: none,[email protected]
debug2: compression stoc: none,[email protected]
debug2: languages ctos:
debug2: languages stoc:
debug2: first_kex_follows 0
debug2: reserved 0
debug3: kex_choose_conf: will use strict KEX ordering
debug1: kex: algorithm: [email protected]
debug1: kex: host key algorithm: ssh-ed25519
debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none
debug3: send packet: type 30
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug3: receive packet: type 31
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:YqWOIqPh7NqasxGY07Yef+WDD52F/48qBkbiWlQxIE8
debug3: record_hostkey: found key type ED25519 in file /Users/david/.ssh/known_hosts:31
debug3: record_hostkey: found key type RSA in file /Users/david/.ssh/known_hosts:32
debug3: record_hostkey: found key type ECDSA in file /Users/david/.ssh/known_hosts:33
debug3: load_hostkeys_file: loaded 3 keys from 192.168.4.7
debug1: load_hostkeys: fopen /Users/david/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: Host '192.168.4.7' is known and matches the ED25519 host key.
debug1: Found key in /Users/david/.ssh/known_hosts:31
debug3: send packet: type 21
debug1: ssh_packet_send2_wrapped: resetting send seqnr 3
debug2: ssh_set_newkeys: mode 1
debug1: rekey out after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug3: receive packet: type 21
debug1: ssh_packet_read_poll2: resetting read seqnr 3
debug1: SSH2_MSG_NEWKEYS received
debug2: ssh_set_newkeys: mode 0
debug1: rekey in after 134217728 blocks
debug3: send packet: type 5
debug3: receive packet: type 7
debug1: SSH2_MSG_EXT_INFO received
debug3: kex_input_ext_info: extension server-sig-algs
debug1: kex_ext_info_client_parse: server-sig-algs=<ssh-ed25519,[email protected],ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,[email protected],[email protected],ssh-dss,ssh-rsa,rsa-sha2-256,rsa-sha2-512>
debug3: kex_input_ext_info: extension [email protected]
debug1: kex_ext_info_check_ver: [email protected]=<0>
debug3: receive packet: type 6
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug3: send packet: type 50
debug3: receive packet: type 51
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
debug3: ssh_get_authentication_socket_path: path '/private/tmp/com.apple.launchd.7ZPATgtfUu/Listeners'
debug1: get_agent_identities: bound agent to hostkey
debug1: get_agent_identities: ssh_fetch_identitylist: agent contains no identities
debug1: Will attempt key: /Users/david/.ssh/docker1_id_rsa RSA SHA256:Pk6ndbhbaLetYzTmHflWGqvG8gaO7CIyUp/XcpRT4S0 explicit
debug2: pubkey_prepare: done
debug1: Offering public key: /Users/david/.ssh/docker1_id_rsa RSA SHA256:Pk6ndbhbaLetYzTmHflWGqvG8gaO7CIyUp/XcpRT4S0 explicit
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 60
debug1: Server accepts key: /Users/david/.ssh/docker1_id_rsa RSA SHA256:Pk6ndbhbaLetYzTmHflWGqvG8gaO7CIyUp/XcpRT4S0 explicit
debug3: sign_and_send_pubkey: using [email protected] with RSA SHA256:Pk6ndbhbaLetYzTmHflWGqvG8gaO7CIyUp/XcpRT4S0
debug3: sign_and_send_pubkey: signing using rsa-sha2-512 SHA256:Pk6ndbhbaLetYzTmHflWGqvG8gaO7CIyUp/XcpRT4S0
Enter passphrase for key '/Users/david/.ssh/docker1_id_rsa':
debug2: bad passphrase given, try again...
Enter passphrase for key '/Users/david/.ssh/docker1_id_rsa':
debug3: send packet: type 50
debug3: receive packet: type 51
Authenticated using "publickey" 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
([email protected]) Verification code:
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
([email protected]) Verification code:
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
([email protected]) Verification code:
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.
[email protected]: Permission denied (keyboard-interactive).
在 Mac Mini 上:
journalctl --since "2 minutes ago"
Jul 09 07:20:18 docker1 sshd(pam_google_authenticator)[10989]: Failed to read "/home/david/.google_authenticator" for "david"
Jul 09 07:20:18 docker1 sshd(pam_google_authenticator)[10989]: No secret configured for user david, asking for code anyway.
Jul 09 07:20:25 docker1 sshd(pam_google_authenticator)[10989]: Invalid verification code for david
Jul 09 07:20:25 docker1 sshd[10987]: error: PAM: Authentication failure for david from 192.168.4.6
Jul 09 07:20:25 docker1 sshd(pam_google_authenticator)[10993]: Failed to read "/home/david/.google_authenticator" for "david"
Jul 09 07:20:25 docker1 sshd(pam_google_authenticator)[10993]: No secret configured for user david, asking for code anyway.
Jul 09 07:20:33 docker1 sshd(pam_google_authenticator)[10993]: Invalid verification code for david
Jul 09 07:20:33 docker1 sshd[10987]: error: PAM: Authentication failure for david from 192.168.4.6
Jul 09 07:20:33 docker1 sshd(pam_google_authenticator)[10996]: Failed to read "/home/david/.google_authenticator" for "david"
Jul 09 07:20:33 docker1 sshd(pam_google_authenticator)[10996]: No secret configured for user david, asking for code anyway.
Jul 09 07:20:42 docker1 sshd(pam_google_authenticator)[10996]: Invalid verification code for david
Jul 09 07:20:42 docker1 sshd[10987]: error: PAM: Authentication failure for david from 192.168.4.6
Jul 09 07:20:42 docker1 sshd[10987]: Connection closed by authenticating user david 192.168.4.6 port 52983 [preauth]
然后我跑ls -asl
进去/home/david/
,发现/home/david/.google_authenticator
它根本不存在。
再谷歌搜索一下,最终我发现了这一点,并意识到我是以 root 用户身份而不是 david 用户身份登录时运行 Google Authenticator 配置/设置的。检查 /root/,我在其中找到了 .google_authenticator 文件。我没有意识到 Google Authenticator 配置应该以需要该身份验证方法的用户身份运行。事后看来,如果我真的用眼睛看,这应该是显而易见的,因为 Google Authenticator 应用程序中代码的描述显示 root@hostname,而不是 david@hostname。
su david
google-authenticate
(Answer yes to everything and create a new code)
然后我再次尝试登录,这一次,系统要求我输入密码和 Google Authenticator 代码,然后我能够成功登录。
我以 root 用户身份登录时运行了 google-authenticator。我应该以普通用户帐户运行它。