主机接受了 SSH 密钥,但客户端断开连接。

你好,

我在 Fedora 23 安装后遇到了 SSH 的问题。

当我想要使用私钥连接到我的远程主机时,我的主机找到了这把密钥:

debug1: matching key found: file /home/theo/.ssh/authorized_keys, line 1 RSA {REDACTED}
debug1: restore_uid: 0/0
Postponed publickey for theo from {REDACTED} port 60351 ssh2 [preauth]
Connection closed by {REDACTED} [preauth]
debug1: do_cleanup [preauth]
debug1: monitor_read_log: child log fd closed

但是你看,我的客户端自己断开了连接

debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/tbouge/.ssh/id_rsa
debug3: send_pubkey_test
debug2: we sent a publickey packet, wait for reply
debug1: Server accepts key: pkalg ssh-rsa blen 1047
debug2: input_userauth_pk_ok: fp SHA256:{REDACTED}
debug3: sign_and_send_pubkey: RSA SHA256:{REDACTED}
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
Permission denied (publickey).
我可以使用Putty在Windows上使用相同的私钥连接到我的主机,也可以使用不同的私钥连接到我的手机。 你有什么想法吗? /etc/ssh/ssh_conf
Host *
        GSSAPIAuthentication yes
# If this option is set to yes then remote X11 clients will have full access
# to the original X11 display. As virtually no X11 client supports the untrusted
# mode correctly we set this to yes.
        ForwardX11Trusted yes
# Send locale-related environment variables
        SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
        SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
        SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
        SendEnv XMODIFIERS
谢谢 编辑:我可以用密码连接

你有没有查看过这个serverfault上的问答?也许是你的shadow.conf文件出现了错误。 - Henrik Pingel
你在审计中看到任何 SELinux 拒绝或 SECCOMP 消息吗?使用 ausearch -m SECCOMPausearch -m AVC 命令来查找。最近有一些变更可能会影响某些设置。 - Jakuje
1你好,感谢您提供的所有答案,但我没有找到发生了什么事情。 我降级到F22,现在它可以正常工作了。祝您度过愉快的一天。 - Preovaleo
sshd有任何日志吗? - neutrinus
确切的ssh命令行是什么?你在使用代理吗?如果你在使用代理,你可以尝试在命令前加上SSH_AUTH_SOCK=来去除代理。 - kasperd
1这里最重要的是缺少来自服务器的日志。客户端日志永远无法完整地讲述整个故事。如果你添加相关的服务器日志,获得答案的机会将显著提高。 - Jenny D
请显示服务器日志。如有必要,请在服务器上提高日志级别。 - user9517
对于其他遇到此问题的人,解决方案是http://superuser.com/q/1016989/93541。 - D.W.
8个回答

首先,关于如何设置或配置基于公钥的身份验证,有很多非常详细且写得很好的文档可以在网上找到。请看一下其中之一,看看你是否正确地按照它们进行操作。这里是其中一个链接。所以我就不再重复了。 基本概念(从这里链接复制而来): 引用块: "基于密钥的身份验证使用两把键,一把是“公钥”,任何人都可以看到,另一把是“私钥”,只有所有者才能看到。为了安全地使用基于密钥的身份验证进行通信,需要创建一对密钥,将私钥安全地存储在想要登录的计算机上,并将公钥存储在想要登录的计算机上。" 现在根据你发布的调试日志: 看起来涉及到两个不同的用户。`/home/theo/.ssh/authorized_keys`和`/home/tbouge/.ssh/id_rsa`。你是想以一个用户登录到另一个用户的主目录吗? 错误信息`Postponed publickey for theo..`意味着在尝试使用公钥方法之前,已经尝试了不需要的身份验证方法。SSH会按照配置文件中启用的每种身份验证方法逐一尝试。在你的情况下,你启用了`GSSAPIAuthentication yes`,但你并没有使用它。你可以通过将其禁用来解决问题,方法是执行`GSSAPIAuthentication no`。 `debug2: we did not send a packet, disable method`的错误很可能是无法处理私钥文件(可能是文件权限或文件名问题)。SSH对本地和远程计算机上的目录和文件权限非常敏感。因此,请确保这些权限设置正确。参考这个链接:https://unix.stackexchange.com/questions/131886/ssh-public-key-wont-send-to-server。 至于第三个错误`Permission denied (public key)`,有几个要检查的事项: - 用户名是否正确 - 密钥对是否正确 - 目标主机是否正确 这里有更多详细信息:https://stackoverflow.com/questions/18551556/permission-denied-publickey-when-ssh-access-to-amazon-ec2-instance。 以下部分有点令人困惑:
debug2: we sent a publickey packet, wait for reply
debug1: Server accepts key: pkalg ssh-rsa blen 1047
debug2: input_userauth_pk_ok: fp SHA256:{REDACTED}
debug3: sign_and_send_pubkey: RSA SHA256:{REDACTED}
debug2: we did not send a packet, disable method
为了更好地理解,让我们按照digitalocean上描述的步骤逐步进行认证过程。 客户端首先通过向服务器发送其想要进行身份验证的密钥对的ID来开始。服务器检查客户端尝试登录的帐户的authorized_keys文件,以查找密钥ID。如果在文件中找到具有相同ID的公钥,则服务器生成一个随机数,并使用公钥对该数字进行加密。服务器将加密的消息发送给客户端。如果客户端实际上拥有关联的私钥,则可以使用该密钥解密消息,从而揭示原始数字。客户端将解密后的数字与用于加密通信的共享会话密钥相结合,并计算此值的MD5哈希。然后,客户端将此MD5哈希作为对加密数字消息的答复发送回服务器。服务器使用相同的共享会话密钥和发送给客户端的原始数字来自行计算MD5值。它将自己的计算结果与客户端发送回的结果进行比较。如果这两个值匹配,则证明客户端拥有私钥且客户端已经通过身份验证。 在你的情况下,正如你所看到的,远程计算机只接受了你的“公钥”,用该密钥加密数据包并将其发送回客户端计算机。现在客户端计算机需要证明它拥有正确的“私钥”。只有拥有正确的私钥,它才能解密收到的消息并发送答复。在这种情况下,客户端未能做到这一点,认证过程以失败告终。 希望这能帮助你理解问题并解决它们。

你的ssh文件权限设置正确吗? .ssh文件夹 --> 700 公钥 --> 644 私钥 --> 600 还要检查用户和组。

谢谢您的回答,但我已经检查过了。 - Preovaleo

你的问题似乎是相当普遍和明确的,我可以这样说。
 Permission denied (publickey).

这对你有什么意义吗? 对我来说,这意味着很多。

请你在服务器端检查一下是否启用了强制模式的 SELinux?如果没有,请告诉我 SELinux 正在运行的模式。

另外,如果你能再尝试一次并捕获该尝试的审计日志,并在此处发布,那肯定会告诉我们原因:

  tail -f /var/log/audit/audit.log  (and try to attempt)
这是一个明显的权限问题,但不是文件权限问题:-)

+1 在RHEL7.1的设置中也见过这种情况。请使用audit2allow进行扩展 :) - kubanczyk

你说你在Windows机器上有相同的密钥;你确定你在Linux机器上拥有的私钥文件是正确的吗?也许私钥是以putty格式保存的,ssh不容易理解。无论如何,如果我放入一个不正确或无效的私钥文件,我会得到与你一样的错误。 为了纠正这个问题,更合适的做法是在Linux机器上生成一个新的密钥,而不是重用另一台机器上的密钥。你只需将新的公钥添加到主机上的authorized_keys文件中,然后你就可以同时使用来自Windows的密钥和来自Fedora的新Linux密钥。

谢谢你的回答,但是是的,私钥没问题(有趣的事实:花了一个小时才找到如何在PuTTY中使用它!)。 - Preovaleo
根据您(非常合理的)解决问题的方案,私钥是好的,但客户端无法使用它,尽管它认为应该能够。我怀疑可能有某些东西本应该要求您输入密码短语,但未能这样做。这可以解释为什么在升级之前它能正常工作;升级可能错误地设置了要求输入密码短语的过程,或者如果已经存在,则搞乱了它,并且sudo authconfig --updateall修复了它。 - Law29

似乎问题(在我的情况下...)是由密钥类型引起的。 我刚刚通过将以下内容添加到本地的~/.ssh/config文件(Fedora 23客户机)来解决它:
PubkeyAcceptedKeyTypes=+ssh-dss
虽然我已经在服务器和客户端配置文件中都添加了那行代码,但只有客户端生效了。请注意,配置文件的权限需要设置为600才能被读取。

这并非事实。问题涉及的是RSA密钥。 - Jakuje
@Jakuje 是的,看起来是这样,我没有注意到。也许对其他人有帮助,因为我昨天升级后遇到了完全相同的问题。 - jeroen
@jeroen,默认情况下,它使用rsa密钥。请参考Fedora的相关文档此处,除非进行了定制化。当然,用户可以选择配置和使用不同类型的密钥。 - Diamond
我的经验是@Jakuje是正确的。我发现在升级了我的客户端之后,无论是我的旧DSA密钥还是新生成的RSA密钥都无法用于登录到我的(仍然是F22)服务器,而该服务器通常禁用密码验证。为了解决这个问题,我不得不重新激活密码验证作为一种变通方法。根据这个论坛帖子的建议,生成一个新的ECSDA密钥(ssh-keygen -t ecdsa)解决了这个问题:http://forums.fedoraforum.org/showthread.php?t=307406 - FeRD
@FeRD 我确实尝试生成了一个新的RSA密钥,但我还没有尝试过ECSDA密钥。谢谢你的建议,我会试一试的。 - jeroen
2@jeroen 在进一步的测试中,我不建议这样做;不幸的是,gnome-keyring-daemon无法识别$HOME/.ssh/id_ecdsa文件,因此这些密钥将无法在登录时自动解锁并添加到会话的ssh-agent中。无论如何,我已经将我的服务器升级到F23,并且使用RSA密钥在它和剩余的F22客户端之间(无论是正向还是反向)没有任何问题。虽然ECSDA密钥确实为我需要它的笔记本电脑提供了一个解决方法(尝试使用RSA密钥失败),但根本问题似乎是其他原因引起的。 - FeRD
1谢谢你的有帮助的回答。请注意,如果服务器升级到OpenSSH 7.0或更高版本(例如,升级到Fedora 23或更高版本),你需要在服务器上进行相同的更改。参见http://superuser.com/q/1016989/93541。 - D.W.

我不知道是否还有其他人遇到这个问题,但是我终于解决了我的一个机器(一台笔记本电脑)上的问题。我相信我知道最终是什么解决了它,并且我将在这里留下信息,希望能帮助任何可能仍然遇到此问题的人,并且也希望有人能够检查我的解决方案并确认它是否真正解决了问题。 事实证明,问题并不是(对我来说)与SSH有关,而是与PAM如何配置我的密钥有关。在/etc/pam.d中的配置已经过时(尽管在Fedora 22中正常工作),因此登录时没有正确执行从$HOME/.ssh/获取我的密钥的操作。运行以下命令:
# sudo authconfig --updateall
重新正确配置了/etc/pam.d。在下次重启后,我登录后第一次尝试通过ssh连接到我的服务器时,弹出了一个对话框要求我输入我的ssh密钥的密码($HOME/.ssh/id_rsa)。我这样做了,并勾选了“登录时自动解锁”选项,然后就大功告成了!我可以从笔记本电脑上重新进行ssh连接了。 背景 我解决问题的线索是当我从外部来源导入了一个RSA密钥时。(我随身携带的一个USB密钥,用于我的家庭网络的“远程访问”。多年前,在遭受入侵后,我关闭了对外部服务器的密码验证。)在使用ssh-add命令添加了那个RSA密钥之后,与位于$HOME/.ssh/id_rsa的密钥不同,它被远程服务器接受了,没有任何问题。 然后,我又做了一个本应该多余的ssh-add操作,以获取$HOME/.ssh/id_rsa。我注意到在我这样做之后,ssh-add -l命令返回了两个相同密钥的条目。
% ssh-add -l
2048 SHA256:XXXXXXXXXXXXXXXXXXXXXX id_rsa (RSA)
2048 SHA256:XXXXXXXXXXXXXXXXXXXXXX me@host (RSA)
2048 SHA256:YYYYYYYYYYYYYYYYYYYYYY imported@usbkey (RSA)
注意其中两个条目中的一个没有显示密钥标识符,只显示与其公共签名匹配的私钥文件名。就好像私钥并没有被密钥管理器真正解锁一样。 我相信这正是发生的事情,而且PAM正在将“坏密钥”传递给尚未使用密码短语解锁的SSH代理。因此,当ssh尝试使用该密钥进行身份验证时,实际上并没有(解锁的)密钥对的私钥部分,因此身份验证失败。 最后一点是推测,但无论如何,如果有人在升级到F23后遇到ssh密钥在远程主机上不被接受的问题(以前是可以的),则重建/etc/pam.d/目录使用authconfig作为解决方案是值得尝试的。

检查用户主目录权限。这很重要。 必须是755。700或770都不行。

在您的ssh_config中,尝试取消注释和/或添加/删除/追加到、或行。 我觉得sshd正在寻找一种特定的密码,但该密码未包含在请求中,可以通过在ssh_config中进行配置来添加它。 ...并且我假设您不会碰巧将PubkeyAuthentication设置为no在远程服务器上,因为那肯定会导致此操作失败。