我在尝试使用 SSH 连接到 EC2 实例时收到“连接被拒绝”或“连接超时”错误。如何解决此问题?
我在尝试使用 SSH 连接到 Amazon Elastic Compute Cloud (Amazon EC2) 实例时收到“连接被拒绝”或“连接超时”错误。
简短描述
错误消息:“ssh:连接到主机 ec2-X-X-X-X.compute-1.amazonaws.com 端口 22: 连接超时”。这条错误消息来自 SSH 客户端。该错误表示服务器没有响应客户端,因此客户端程序放弃了(超时)。以下是此错误的常见原因:
- 安全组或网络 ACL 不允许访问。
- 实例的操作系统上有防火墙。
- 客户端和服务器之间有防火墙。
- 主机不存在。
错误消息:“ssh:连接到主机 ec2-X-X-X-X.compute-1.amazonaws.com 端口 22: 连接被拒绝”。这条消息来自远程主机。以下是此错误的常见原因:
- 主机已到达实例,但没有服务在 SSH 端口上侦听。
- 防火墙进行了阻止,并且设置为拒绝包,而不是将其丢弃。
解决方法
“连接超时”错误
对于“连接超时”错误,请验证以下内容:
- 实例的 IP 地址或主机名正确。
- 实例正在通过运行状况检查。
- 实例的安全组允许 TCP 端口 22 上的传入流量。
- 实例子网的网络 ACL 允许 TCP 端口 22 上的传入流量,并且允许传出流量使用临时端口。
- 实例子网的的路由表配置正确,可在 EC2 实例和 SSH 客户端之间提供连接。
- 没有防火墙阻止 SSH 客户端和 EC2 实例之间的连接。
- SSH 不会被实例的 TCP 包装程序阻止(在 Red Hat 网站上)。
**注意:**最后两个验证步骤需要实例的操作系统级别访问权限。
“连接被拒绝”错误
对于“连接被拒绝”错误,请验证以下内容:
- 实例上没有拒绝 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 的实例类型的操作系统级别问题。串行控制台有助于解决启动问题、网络配置和 SSH 配置问题。您可以使用 Amazon EC2 控制台或 AWS 命令行界面(AWS CLI)访问串行控制台。
在使用串行控制台之前,在账户级别授予其访问权限。然后,创建 AWS Identity and Access Management (IAM) 策略,授予 IAM 用户访问权限。
**注意:**使用串行控制台的每个实例都必须至少包含一个具有 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 代理 ping 状态”必须为在线。有关会话管理器的详细信息,以及先决条件的完整列表,请参阅设置会话管理器。
要确认 SSH 连接没有被防火墙或 TCP 包装程序阻止,并且 sshd 服务正在端口 22 上运行和侦听,请执行以下操作:
1. 打开 AWS Systems Manager。
3. 执行方法 1 中的步骤 1 - 4: 使用适用于 Linux 的 EC2 Serial Console。
4. 如果不再需要会话管理器会话,请将其关闭。
方法 3: 运行 AWSSupport-TroubleshootSSH 运行手册
AWSSupport-TroubleshootSSH 自动化运行手册会在实例上安装适用于 Linux 的 Amazon EC2Rescue 工具。此工具会检查并尝试解决阻止 Linux 主机通过 SSH 进行远程连接的问题。
要运行 AWSSupport-TroubleshootSSH 运行手册,请执行以下操作:
1. 打开 AWSSupport-TroubleshootSSH 页面。
2. 选择运行此自动化(控制台)。
要了解更多信息,请参阅我在尝试使用 SSH 连接我的 EC2 实例时收到错误。如何使用 AWSSupport-TroubleshootSSH 自动化工作流来解决 SSH 连接问题?
方法 4: 使用用户数据脚本
如果所述方法均不适用于您的环境,则使用 EC2 用户数据脚本。EC2 用户数据脚本会关闭操作系统级别防火墙和 TCP 包装程序,然后重启 sshd 服务。
重要事项:
- 此过程需要停止和启动 EC2 实例。如果实例将任何数据都存储到实例存储卷上,则该等数据将在停止实例后被删除。
- 如果实例是 Amazon EC2 自动扩缩组的一部分,则终止实例也可能会停止自动扩缩组内的实例。
- 如果实例由使用 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、firewalld、iptables)。
要移除用户数据,请执行以下操作:
1. 完成以下部分中的步骤 1-4:方法 4: 使用用户数据脚本部分。
2. 在编辑用户数据对话框中删除用户数据脚本。
相关信息
如何解决从互联网连接 Amazon EC2 实例的连接超时错误?
相关内容
- 已提问 10 个月前lg...
- 已提问 10 个月前lg...
- 已提问 5 个月前lg...
- AWS 官方已更新 4 个月前
- AWS 官方已更新 5 个月前
- AWS 官方已更新 1 年前