SSH权限被拒绝(公钥)

我正在尝试从我的本地机器(也在运行Ubuntu 12.04 LTS)连接到一个Linode(运行Ubuntu 12.04 LTS)。

在我的本地机器上创建了私钥和公钥,并将我的公钥复制到Linode的authorized_keys文件中。然而,每当我尝试通过ssh连接到我的Linode时,都会收到错误消息Permission denied (publickey)

这不是因为我的Linode上的ssh设置出了问题,因为我可以使用密钥认证从我的Windows机器ssh连接到它。

在我的本地Ubuntu机器的.ssh目录中,我有id_rsaid_rsa.pub文件。我需要在我的本地机器上创建一个authorized_keys文件吗?

编辑:当我运行ssh -vvv -i id_rsa [youruser]@[yourLinode]时,我得到以下结果:

debug3: authmethod_lookup publickey
debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: id_rsa
debug3: send_pubkey_test
debug2: we sent a publickey packet, wait for reply
debug1: Authentications that can continue: publickey
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
Permission denied (publickey).

71)关于客户端出现错误的时间,SSH服务器上的日志记录显示了什么?(/var/log/auth.log) 2)您是如何将公钥传输到服务器的?请始终使用ssh-copy-id命令以确保权限正确。您的主目录、.ssh目录和authorized_keys文件都有严格的权限要求(详见sshd(8)手册中关于~/.ssh/authorized_keys的说明)。 3)您是否在Ubuntu上生成了新的密钥对?如果您重用了来自Windows的密钥,则需要先将其转换为OpenSSH格式。 - gertvdijk
2命令应该ssh -vvv -i .ssh/id_rsa ....(注意id_rsa的路径!)- 请替换 - 旧日志只显示“我们”没有可发送的公钥。 - guntbert
@guntbert 我错过了 .ssh,因为我已经在 .ssh 目录中了。我还尝试了 .ssh/id_rsa,但结果一样。 - Pattle
我明白了,所以我看错了 - 请回答@gertvdijk的问题。 - guntbert
非常有用的教程:www.digitalocean.com: 如何设置SSH密钥 - Gabriel Staples
1我遇到了同样的问题。我可以使用root账户登录,但无法使用new_user账户登录。如果你能以root或sudo用户的身份访问服务器,你可以通过"tail -f /var/log/auth.log"命令查看ssh认证日志。在我的情况下,问题是new_user账户配置了一个无效的shell。"user new_user not allowed because shell /bin/ is not executable"。 - Bryan
最近,这也可能是由于RSA密钥中的SHA-1签名被弃用而发生的。如果是这种情况,运行ssh -vvv将报告“没有共同的签名算法”。要修复此问题,可以更新您的ssh服务器以支持rsa-sha2,或者使用ssh-keygen -t ed25519重新生成密钥,或者在ssh客户端中传递-o PubkeyAcceptedKeyTypes=+ssh-rsa - Sir Athos
今天我用一个新的用户账户遇到了这个问题 - 密钥都没问题,而且都正确安装了。在检查/var/log/auth.log时,我发现连接被拒绝是因为服务器的AllowUsers列表中没有该用户账户。 - ChumKui
我是说服务器的SSH配置文件(/etc/ssh/sshd_config)。以这种方式锁定SSH是一个好的做法,只有那些绝对需要通过SSH登录的用户账户才能够这样做。 - ChumKui
22个回答

PubKeyAuthentication

设置您的客户端

  1. 生成您的密钥。

    ssh-keygen
    
  2. 配置ssh使用该密钥。

    vim ~/.ssh/config
    

    您的配置文件应该类似于以下内容:

    Host 服务器名称
    Hostname 服务器的IP或域名
    User 用户名
    PubKeyAuthentication yes
    IdentityFile ./密钥路径
    

    您可以添加IdentitiesOnly yes以确保ssh在身份验证期间仅使用指定的IdentityFile而不使用其他密钥文件。设置IdentitiesOnly可以防止身份验证失败,否则ssh将尝试使用多个密钥进行登录。这样做也被认为更安全,因为您不会泄露已安装的其他密钥的信息,并且在不同访问级别之间保持密钥的分离。

  3. 将您的密钥复制到服务器上。

    ssh-copy-id -i 密钥.pub 服务器名称
    

    例如:ssh-copy-id -i ~/.ssh/id_res.pub -p 22 user@1.1.1.1

故障排除

  1. 使用"-vvv"选项。
  2. 确保服务器拥有您的公钥(.pub)。
  3. 确保您的IdentiyFile指向您的私钥。
  4. 确保您的.ssh目录具有700权限,并且其中的文件具有600权限。
    • ssh-keygen将为您创建具有正确权限的文件和目录。
  5. 在尝试登录时,使用tail -f /var/log/auth.log(在服务器上)监视错误。
  6. 如果您有多个密钥文件,请尝试使用IdentitiesOnly yes来限制身份验证仅使用单个指定的密钥。

4我在https://github.com/centic9/generate-and-send-ssh-key创建了一个小脚本,FYI。它可以一次性运行所有必要的步骤,并且还能确保文件/目录权限,这总是让我头疼的问题... - centic
6只是为了详细说明第二步:在~/.ssh/config文件中的IdentityFile行必须指向私钥。 - Danny Schoemann
1确实 - earthmeLon
6我想知道为什么您要在第四步中将文件设置为可执行权限? - Todd Walton
1对于每个用户,赋予正确的权限也非常重要(使用chown和chmod),否则即使您的服务器拥有您的公钥,您也会遇到身份验证被拒绝的问题。 - joseluisq
1为什么每个类似这样的问题都包含一个回答,告诉你要通过ssh-keygen生成密钥?楼主已经说过他有公钥和私钥了。 - Aaron Franke
2后代和完整性是原因。 - earthmeLon
6虽然目录需要700权限,但文件不需要,它们应该是600。 - openCivilisation
tail -f /var/log/auth.log 给了我所需的信息。 - Shankar Thyagarajan
authorized_keys 需要 644,我认为。 - KuN
600在authorized_keys中是默认值,在大多数情况下,这已经足够了。 - earthmeLon

有时候问题出在权限和所有权上。例如,如果你想以root用户登录,/root、.ssh和authorized_keys必须属于root用户。否则,sshd将无法读取它们,因此也无法判断用户是否被授权登录。
在你的主目录中:
chown -R your_user:your_user .ssh

关于权限方面,对于 .ssh 设置为 700,authorized_keys 设置为 600。
chmod 700 .ssh
chmod 600 .ssh/authorized_keys

4这个答案对我很有帮助。我从这篇帖子中采纳了建议,并将我的authorized_keys文件移出了加密的家目录。在这样做的过程中,我无意中改变了所有权为root:root - Jordan Grant
3希望我能点赞两次,一次给文件夹,一次给文件。权限必须准确无误,非常重要。 - Mr Griever
我不小心将我的主文件夹/home/user的权限更改为777,导致ssh连接失败。执行chmod 777 /home/user可以修复这个问题。 - hellohawaii

我遇到的问题是客户端使用了错误的密钥。我将id_rsa和id_rsa.pub重命名为其他名称。 你可以将它们重新改回默认名称,或者在发出ssh命令时像这样使用它们。
ssh -i ~/.ssh/private_key username@host

1不,使用公钥。 - St3an
12@St3an 你把公钥放在服务器上,但是当你像Todd在上面那样连接时,你要使用你的私钥。 - Nathan F.
@NathanFiscaletti 你绝对不能暴露你的私钥,因为它是私有的。本地 SSH 代理使用私钥来验证你提供的公钥是否与你的私钥相对应。机器之间的 SSH 代理可以确保用户的身份真实性,以免冒充他人 :-) - St3an
15没错。这就是为什么当你连接时,你要提供你的私钥给ssh客户端。服务器会存储你的公钥。上面的命令正是私钥应该使用的方式。 - Nathan F.
这个方法真是太棒了,终于解决了我第一次连接服务器的问题。 - chenghuayang

在客户端上不需要 authorized_keys

您必须告诉 ssh-client 实际使用您生成的密钥。有几种方法可以做到这一点。仅用于测试,键入 ssh -vvv -i .ssh/id_rsa [youruser]@[yourLinode]。每次连接到服务器时都必须提供密码短语。

如果成功了,您可以使用 ssh-add .ssh/id_rsa 将密钥添加到 ssh-agent 中(您只需提供一次密码短语即可,只要您不注销/重新启动即可正常工作)。


谢谢你的帮助,我已经编辑了我的答案,展示了当我输入你建议的内容时会发生什么。 - Pattle
2要在客户端上传输密钥,请使用ssh-copy-id命令。 - Panther
@bodhi.zazen 谢谢,但是我已经转移了钥匙,那不是问题。 - Pattle
4你必须告诉ssh客户端实际使用你生成的密钥。不,它默认会在默认路径中查找密钥,例如~/.ssh/id_rsa。此外,使用密钥代理完全是可选的,并且与我所看到的问题无关。 - gertvdijk
@gertvdijk,你在这里做出了一些没有事实支持的假设 - 我们还不知道系统上发生了什么。 - guntbert
如果SSH不自动执行,则系统进行了一些未报告的操作。因此,可以假设默认行为是正常的。但是使用“-vvv”可以很好地了解客户端SSH的操作。我希望用户再次使用ssh-copy-id传输密钥。我认为问题在服务器端。 - Anders
如何在同一命令中传递密码短语 - Kiran Reddy
如果ssh-agent已经在使用不同的密钥,那么它可能无法在~/.ssh/id_rsa中看到新的密钥。您需要再次使用ssh-add命令。我认为,如果ssh-agent中存在任何密钥,则默认情况下将忽略该密钥作为ssh的默认密钥。 - Mnebuerquo

还要检查/etc/ssh/sshd_configPasswordAuthentication的值,如果是no,将其改为yes。之后不要忘记重新启动ssh服务。

30OP并不打算使用密码身份验证。他们有一些意识,并且正在使用公钥/私钥。 - ctrl-alt-delor
2这解决了我的问题,在某个云服务器上,启用SSH登录后,密码登录会自动禁用... - Eric
OP没有遇到这个问题,但其他遇到类似问题的人(比如我自己)可能会通过谷歌搜索到这个问题。我正在尝试在我的防火墙内设置一个带有密码认证的测试服务器。有人可能会说这是不明智的做法,但我想知道我有这个选择的权利。 - Dr Phil

我最近在我的Web服务器上遇到了这个问题。

通常情况下,我会在所有的服务器上保留一个授权密钥列表,位于~/.ssh/authorized_keys2。根据我的经验,sshd默认会查找~/.ssh/authorized_keys~/.ssh/authorized_keys2

对于我的Web服务器,/etc/ssh/sshd_config文件中有这样一行:

AuthorizedKeysFile    %h/.ssh/authorized_keys

替代

AuthorizedKeysFile    %h/.ssh/authorized_keys2

我选择了后者,重新启动了我的ssh守护进程,并成功解决了使用公钥登录ssh的问题。

非常感谢,这帮助我弄清楚了这一行在配置文件中完全被注释掉了! - Christian.D

另一个可能的原因可能是在/etc/ssh/sshd_conf中的AllowedUsers配置。注意:列表是以空格分隔的(不是逗号分隔),这是我吃过苦头才知道的。
AllowUsers user1 user2 user3

还要确保用户的主目录(在服务器上)实际上属于通过ssh登录的用户(在我的情况下设置为root:root)。
应该是:
sudo chown username:username /home/username;

我能够使用本地Linux桌面上的用户(例如abc)的公钥/私钥与远程服务器上的用户(例如def@123.456.789)进行SSH连接。我只需要确保本地用户拥有本地的.ssh文件(例如abc:abc,而不是root:abc)。 - Michael Millar

如果您可以独立访问machineA和machineB(例如从machineC),则以下方法可能有效。
如果ssh-copy-id无法工作,则可能已禁用密码身份验证。以下是一种解决方法。
将machineA的公钥添加到machineB的授权密钥(即~/.ssh/authorized_keys)中,这样您就可以从machineA进行ssh连接。对于scp也适用。
使用以下命令生成密钥对:ssh-keygen
在machineA上执行cat ~/.ssh/id_rsa.pub
示例输出:
ssh-rsa AAAAB3NzaSGMFZW7yB anask@mahineA
复制打印出的密钥(按下⌘ Command+C或CRTL+C),然后将其添加到machineB的~/.ssh/authorized_keys文件中。
例如,在machineB上执行以下操作:
echo 'ssh-rsa AAAAB3NzaSGMFZW7yB anask@mahineA' >> ~/.ssh/authorized_keys

这个对我起作用了- 结果证明是最简单的方法。 - dollar bill

這個方法也適用於Ubuntu 16.04。
問題出在sshd_config文件中。
以下是終極解決方案:
以root身份登錄到您的Ubuntu服務器。
vi /etc/ssh/sshd_config

现在请滚动到底部,将值从“no”更改为“yes”。
它应该看起来像这样:
将“no”更改为禁用隧道明文密码。
PasswordAuthentication yes
service sshd reload

生效。

现在您可以使用以下命令简化一个密钥,来自您的本地机器(即笔记本电脑等)

所以为了打开一个新的终端窗口且不登录服务器,只需使用此命令:

ssh-copy-id john@serverIPAddress

(将john替换为您的用户名)。

您应该可以继续进行。