在尝试使用 SSH 连接到我的 EC2 实例时,我收到“连接被拒绝”或“连接超时”错误。如何解决此问题?

4 分钟阅读
0

在尝试使用 SSH 连接到 Amazon Elastic Compute Cloud(Amazon EC2)实例时,我收到“连接被拒绝”或“连接超时”错误。

简述

错误消息:“ssh: connect to host ec2-X-X-X-X.compute-1.amazonaws.com port 22: Connection timed out”。这条错误消息来自 SSH 客户端。该错误表示服务器没有响应客户端,因此客户端程序放弃了(超时)。以下是此错误的常见原因:

  • 安全组或网络 ACL 不允许访问。
  • 实例的操作系统上有防火墙。
  • 客户端和服务器之间有防火墙。
  • 主机不存在。

错误消息:“ssh: connect to host ec2-X-X-X-X.compute-1.amazonaws.com port 22: Connection refused”。这条消息来自远程主机。以下是此错误的常见原因:

  • 主机已到达实例,但 SSH 端口上没有侦听的服务。
  • 防火墙进行了阻止,并被设置为拒绝包,而非将其丢弃。

解决方法

“连接超时”错误

对于“连接超时”错误,请验证以下内容:

**注意:**最后两个验证步骤需要实例的操作系统级别访问权限。

“连接被拒绝”错误

对于“连接被拒绝”错误,请验证以下内容:

  • 实例上没有拒绝 SSH 连接的防火墙。
  • SSH 进程守护程序 (sshd) 在端口 22 运行并侦听。

**注意:**这两个验证步骤都需要实例的操作系统级别访问权限。

如果实例通过两次运行状况检查,请在您的配置中使用以下列出的四种方法之一

  • 方法 1: 使用适用于 Linux 的 EC2 Serial Console。
  • 方法 2: 使用 AWS Systems Manager 会话管理器。
  • 方法 3: 运行 AWSSupport-TroubleshootSSH 自动化运行手册。
  • 方法 4: 使用用户数据脚本。

方法 1: 使用适用于 Linux 的 EC2 Serial Console

如果进行了配置,则可以使用适用于 Linux 的 EC2 Serial Console,对支持的基于 Nitro 实例类型的操作系统级别问题进行故障排除。Serial Console 允许您排查启动问题、网络配置和 SSH 配置问题。您可以使用 Amazon EC2 控制台或 AWS 命令行界面(AWS CLI)访问 Serial Console。

在使用 Serial Console 之前,请在账户层面授予对其的访问权限。然后,创建 AWS Identity and Access Management(IAM)策略,授予对 IAM 用户的访问权限

**注意:**使用 Serial Console 的每个实例都必须至少包含一个具有 sudo 访问权限且使用密码的 Linux 用户。

有关配置适用于 Linux 的 EC2 Serial Console 的更多信息,请参阅配置 EC2 Serial Console 的访问权限。如果 Linux 账户未配置登录密码,则必须运行 ssm-user,为具有 sudo 访问权限的账户重置密码。有关运行 ssm-user 命令的更多信息,请参阅在 Linux 和 macOS 上管理 ssm-user sudo 账户权限

完成配置后,使用配置了密码的 Linux 用户通过 EC2 Serial Console 连接到 EC2 实例。

接着,运行以下命令。这些命令验证 SSH 连接是否没有被操作系统防火墙或 TCP 包装器阻止。这些命令还会验证 sshd 服务是否在端口 22 上运行和侦听。

1.    如果您配置了 iptables 规则,则运行以下命令,在 iptables 中添加一条规则,在默认端口 22 上接受所有 SSH 连接:

$ sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

由于最佳做法是使用安全组而不是基于操作系统的防火墙,因此可以完全禁用防火墙。要停用基于操作系统的防火墙,请使用以下任一命令集(具体取决于您的操作系统):

**重要信息:**以下命令会刷新所有主要的 iptables 规则。这些命令还会添加允许传入 SSH 连接的规则。此外,这些命令还会将主链的默认策略更改为 ACCEPT,因此刷新 iptables 规则不会影响实例网络连接。由于这些命令会刷新所有主要的 iptables,因此也会刷新所有现有规则。

使用 UFW 的发行版(Ubuntu、Debian)

$ sudo iptables -F
$ sudo iptables -P INPUT ACCEPT
$ sudo ufw disable

使用 firewalld 的发行版(Red Hat、CentOS)

$ sudo iptables -F
$ sudo iptables -P INPUT ACCEPT
$ sudo systemctl disable firewalld

**注意:**重新获得实例的访问权限后,请检查您的防火墙配置(UFW、firewalld、iptables)。

2.    验证 SSH 是否正在运行,并验证 SSH TCP 端口 (22) 是否处于侦听状态:

$ sudo systemctl restart sshd
$ sudo ss -tpln | grep -iE '22|ssh'
LISTEN 0 128 *:22 *:* users:(("sshd",pid=1901,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1901,fd=4))

**注意:**如果您的系统没有 ss 命令,则可以使用传统的 netstat 命令,其语法与前面示例中显示的语法相同。

3.    确保 TCP 包装器不会阻止 SSH 连接:

$ if [[ $( cat /etc/hosts.[ad]* | grep -vE '^#' | awk 'NF' | wc -l) -ne 0 ]];\
then sudo sed -i '1i sshd2 sshd : ALL: allow' /etc/hosts.allow; fi

4.    接下来,使用 SSH 连接到实例。

5.    如果不再需要 EC2 Serial Console 会话,请断开连接。

方法 2: 使用 AWS Systems Manager 会话管理器

注意:要使用此方法,实例必须是 SSM 托管实例,并且其 SSM Agent Ping 状态必须为在线。有关会话管理器的更多信息以及先决条件的完整列表,请参阅设置会话管理器

要确认防火墙或 TCP 包装器未阻止 SSH 连接,并且 sshd 服务在端口 22 上运行和侦听,请执行以下操作:

1.    打开 AWS Systems Manager

2.    使用会话管理器为实例启动会话

3.    执行方法 1 中的步骤 1 - 4: 使用适用于 Linux 的 EC2 Serial Console。

4.    如果不再需要会话管理器会话,请将其关闭。

方法 3: 运行 AWSSupport-TroubleshootSSH 运行手册

AWSSupport-TroubleshootSSH 自动化运行手册会在实例上安装适用于 Linux 的 Amazon EC2Rescue 工具。此工具可检查并尝试解决阻止通过 SSH 远程连接 Linux 主机的问题。

要运行 AWSSupport-TroubleshootSSH 运行手册,请执行以下操作:

1.    打开 AWSSupport-TroubleshootSSH 页面。

2.    选择运行此自动化(控制台)。

要了解更多信息,请参阅我在尝试使用 SSH 连接我的 EC2 实例时收到错误。如何使用 AWSSupport-TroubleshootSSH 自动化工作流程解决 SSH 连接问题?

方法 4: 使用用户数据脚本

如果所述方法均不适用于您的环境,请使用 EC2 用户数据脚本。EC2 用户数据脚本会关闭操作系统级别防火墙和 TCP 包装器,然后重启 sshd 服务。

重要信息:

  • 此过程需要停止和启动 EC2 实例。如果实例在实例存储卷上存有任何数据,则实例停止后这些数据会被删除。
  • 如果实例属于 Amazon EC2 Auto Scaling 组,则终止实例也可能会停止自动扩缩组内的实例。
  • 如果实例由使用 AWS Auto Scaling 的服务启动,则终止实例也可能会停止自动扩缩组内的实例。
  • 实例终止取决于自动扩缩组的实例缩容保护设置。如果实例属于自动扩缩组,则在执行解决步骤之前,请暂时将实例从自动扩缩组中移除
  • 停止和启动实例都会更改实例的公共 IP 地址。在将外部流量路由到实例时,最佳实践是使用弹性 IP 地址,而不是公共 IP 地址。

执行以下步骤为实例配置用户数据:

1.    打开 Amazon EC2 控制台

2.    从导航窗格中选择实例,然后选择计划连接的目标实例。

3.    停止实例

4.    依次选择操作实例设置编辑用户数据

5.    将以下用户数据脚本复制到编辑用户数据对话框中,然后选择保存

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
iptables -P INPUT ACCEPT
iptables -F
systemctl restart sshd.service || service sshd restart
if [[ $( cat /etc/hosts.[ad]* | grep -vE '^#' | awk 'NF' | wc -l) -ne 0 ]];\
then sudo sed -i '1i sshd2 sshd : ALL: allow' /etc/hosts.allow; fi
--//

6.    使用 SSH 连接到实例。

7.    将上述用户数据脚本设置为每次重启实例时运行。重新获得实例的访问权限后,移除用户数据脚本。

**注意:**上述命令会刷新所有主要的 iptables 规则。重新获得实例的访问权限后,请查看防火墙配置是否准确(例如 UFW、firewalldiptables)。

要移除用户数据,请执行以下操作:

1.    完成方法 4 中的步骤 1 - 4: 使用用户数据脚本部分。

2.    在编辑用户数据对话框中删除用户数据脚本。

相关信息

连接到您的实例时出错: 连接超时

如何解决来自互联网的 Amazon EC2 实例连接超时错误?

如何解决使用 SSH 连接到 Amazon EC2 Linux 实例时出现的问题?

为什么我的 EC2 Linux 实例无法访问且未能通过一次或两次状态检查?

AWS 官方
AWS 官方已更新 1 年前