为什么我在尝试使用 SSH 连接 EC2 实例时收到“服务器拒绝我们的密钥”错误?

上次更新时间:2020 年 4 月 1 日

我尝试使用 SSH 连接到我的 Amazon Elastic Compute Cloud (Amazon EC2) 实例,但我收到“服务器拒绝我们的密钥”错误。如何解决此问题?

简短描述

在多个原因下,您可能会收到服务器拒绝我们的密钥错误:

  • 您在连接到 EC2 实例时为 AMI 使用不正确的用户名。
  • 对于实例存在权限问题,或者您丢失了目录。
  • 尝试访问实例的用户已从服务器中删除。

解决方法

验证您在为您的 AMI 使用正确的用户名。

有关有效用户名的列表,请参阅排查实例连接问题 - 错误:服务器拒绝我们的密钥或者没有可用的支持验证方法

验证已为实例设置正确的权限,且没有丢失目录。

可以通过三种方法验证实例上的权限和目录:

方法 1:使用 AWS Systems Manager Session Manager 登录实例并检查权限

注意:必须安装 SSM 代理才能使用此方法。有关 Session Manager 和先决条件完整列表的更多信息,请参阅 Session Manager 入门

1.    打开 AWS Systems Manager 控制台

2.    启动会话

3.    使用 stat 命令确保目录下的文件权限正确。以下是正确权限的列表:

  • Linux 主目录(例如 /home)应为 (0755/drwxr-xr-x)
  • 用户的主目录(例如 /home/ec2-user/)应为 (0700/drwx------)
  • .ssh 目录权限(例如 /home/ec2-user/.ssh)应为 (0700/drwx------)
  • authorized_keys 文件权限(例如 /home/ec2-user/.ssh/authorized_keys)应为 (0600/-rw-------)。 

以下为 stat 命令及所生成输出的示例。在本示例中,ec2-user 为用户名。根据您的特定 AMI 更改用户名

$ stat /home/ec2-user/
  File: '/home/ec2-user/'
  Size: 4096      	Blocks: 8          IO Block: 4096   directory
Device: 10301h/66305d	Inode: 18322       Links: 3
Access: (0700/drwx------)  Uid: (  500/ec2-user)   Gid: (  500/ec2-user)

4.    如果此权限与上述值不匹配,则运行以下命令。

$ sudo chown root:root /home
$ sudo chmod 755 /home
$ sudo chown ec2-user:ec2-user /home/ec2-user -R
$ sudo chmod 700 /home/ec2-user /home/ec2-user/.ssh
$ sudo chmod 600 /home/ec2-user/.ssh/authorized_keys

5.    终止会话

6.    通过 SSH 连接到您的实例。

方法 2:自动更正导致错误的问题

运行 AWSSupport-TroubleshootSSH 自动化文档

AWSSupport-TroubleshootSSH 自动化文档 会在实例上安装 Amazon EC2Rescue 工具,然后检查并更正在使用 SSH 连接至 Linux 计算机时导致远程连接错误的部分问题。有关更多信息,请参阅如何通过 AWSSupport-TroubleshootSSH 自动化工作流程排查 SSH 连接问题?

方法 3:使用用户数据修复实例权限

重要提示:

  • 如果您的实例属于实例存储支持的实例或者拥有包含数据的实例存储卷,请不要执行需要停止和重新启动 EC2 实例的程序。此恢复过程需要您停止并启动您的实例。这样做意味着实例存储卷上的数据丢失。有关更多信息,请参阅确定实例的根设备类型
  • 如果您的实例是 Amazon EC2 Auto Scaling 组的一部分,或者您的实例由使用 AWS Auto Scaling 的服务(例如 Amazon EMR、AWS CloudFormation、AWS Elastic Beanstalk 等)启动,则停止实例可能会导致实例终止。在这种情况下,是否会发生实例终止取决于您的 Auto Scaling 组的实例缩减保护设置。如果您的实例是 Auto Scaling 组的一部分,请在开始执行解决步骤之前,暂时从 Auto Scaling 组中删除该实例
  • 停止和重新启动实例会更改实例的公有 IP 地址。在将外部流量路由到您的实例时,最佳做法是使用弹性 IP 地址而不是公有 IP 地址。
  • 如果您的实例根设备为实例存储卷,您无法使用用户数据更改 SSH 密钥。有关更多信息,请参阅确定实例的根设备类型
  • 更新实例的用户数据将应用于支持 cloud-init 指令的所有分发。要使这些指令成功,必须安装并配置 Cloud-init。有关 cloud-init SSH 模块的更多信息,请参阅配置 SSH 和 SSH 密钥

1.    打开 Amazon EC2 控制台,然后选择您的实例。

2.    依次选择操作实例状态停止

注意:如果“停止”处于禁用状态,则表示要么实例已停止,要么其根设备是一个实例存储卷。

3.    依次选择操作实例设置查看/更改用户数据

4.    将以下脚本复制到用户数据字段中,然后选择保存。确保复制整个脚本,不要添加额外的空格。

注意:以下脚本使用用户名 ec2-user。将 ec2-user 更改为您的 AMI 的用户名

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
chown root:root /home
chmod 755 /home
chown ec2-user:ec2-user /home/ec2-user -R
chmod 700 /home/ec2-user /home/ec2-user/.ssh
chmod 600 /home/ec2-user/.ssh/authorized_keys
--// 

5.    启动实例,然后通过 SSH 连接到实例。

注意:默认情况下,每个实例运行一次用户数据脚本。此程序将更改默认行为,从而将公有密钥添加到实例的每次重启、停止或启动中。要恢复默认行为,请删除自定义的用户数据。作为最佳实践,请考虑允许用户数据在第一次启动实例后运行的安全启示。您可以使用 ModifyInstanceAttribute API 方法修改实例的用户数据。要限制对此方法的访问,请使用 AWS Identity and Access Management (IAM) 策略

检查用户是否已从服务器中删除

如果尝试访问实例的用户已从服务器中删除,则将该用户作为新用户添加回来。有关更多信息,请参阅如何将具有 SSH 访问权限的新用户账户添加到 Amazon EC2 Linux 实例?