快速解决 SSH 连接被拒绝错误
SSH(Secure Shell)是远程服务器管理的支柱,它允许您的本地计算机与远程服务器之间进行安全加密的通信。然而,遇到 ssh: connect to host <IP_ADDRESS> port 22: Connection refused 错误可能是一个令人沮丧的障碍,阻碍您访问关键系统。
本文提供了一个全面、循序渐进的指南,用于诊断和解决常见的“连接被拒绝”错误。我们将探讨主要的罪魁祸首,从不活跃的 SSH 守护程序到配置错误的防火墙和不正确的服务器设置,为您提供快速重新获得服务器访问权限所需的知识和命令。
了解“连接被拒绝”错误
当您收到 Connection refused 错误时,这表明您的 SSH 客户端已成功到达远程服务器,但服务器明确拒绝了指定端口上的连接。这与 Connection timed out 错误(客户端根本无法联系到服务器)或 No route to host 错误(网络路径损坏)是不同的。
“被拒绝”状态直接指向 服务器端 的问题,该问题正在主动阻止 SSH 服务接受连接。这通常涉及 SSH 守护程序未运行、防火墙阻止连接或 SSH 服务本身的配置错误。
“连接被拒绝”的常见原因
有几个因素可能导致 SSH 连接被拒绝。了解这些有助于缩小故障排除过程的范围:
- SSH 守护程序 (
sshd) 未运行:最常见的原因。SSH 服务器进程可能已崩溃、停止或未能在启动时启动。 - 防火墙阻止端口 22(或自定义端口):服务器的防火墙(例如 UFW、firewalld、iptables)正在阻止 SSH 端口上的传入连接。
- SSH 守护程序配置不正确:
sshd_config文件可能配置错误,导致 SSH 守护程序监听在不同的端口、错误的网络接口上,或拒绝特定用户/方法的连接。 - 网络连接问题(对于“被拒绝”而言较少见):虽然对于“被拒绝”错误来说可能性较小,但基础网络问题有时可能会意外地显现出来。
- SELinux 或 AppArmor 限制:SELinux 或 AppArmor 等安全增强功能可能正在阻止
sshd正常运行,尤其是在自定义配置或系统更改之后。
分步故障排除指南
让我们深入了解诊断和修复“连接被拒绝”错误的实用步骤。
第 1 步:验证服务器上的 SSH 守护程序状态
首先要检查的是 SSH 服务器守护程序 (sshd) 是否真正在远程计算机上运行。如果 SSH 完全不可用,您通常需要控制台访问权限(例如,通过云提供商的控制台或物理连接)来执行这些检查。
-
检查 SSH 守护程序状态:
在大多数现代 Linux 发行版(使用systemd的系统,如 Ubuntu、CentOS 7+、Debian 8+)上:
bash sudo systemctl status sshd
如果sshd未运行,输出将显示inactive (dead)或类似的状态。 -
启动 SSH 守护程序:
如果状态为非活动,请尝试启动服务:
bash sudo systemctl start sshd -
启用 SSH 守护程序在启动时启动:
为确保 SSH 在重启后自动启动,请启用它:
bash sudo systemctl enable sshd -
检查 SSH 守护程序日志:
如果sshd启动失败,其日志可以提供关键线索。对于systemd系统:
bash sudo journalctl -u sshd --since "10 minutes ago"
或者,检查常规身份验证日志:
bash sudo tail -f /var/log/auth.log # 或对于 RHEL/CentOS: sudo tail -f /var/log/secure
第 2 步:检查防火墙规则
服务器端防火墙通常是连接被拒绝的罪魁祸首。它可能正在阻止默认的 SSH 端口 (22) 或您尝试使用的自定义端口。您需要确保防火墙允许 SSH 端口上的传入连接。
-
识别您的防火墙:
常见的防火墙包括:- UFW (Uncomplicated Firewall):常见于 Ubuntu/Debian。
- firewalld:常见于 CentOS/RHEL 7+。
- iptables:Linux 的底层防火墙,可直接配置或通过前端配置。
-
检查防火墙状态和规则:
- UFW:
bash sudo ufw status verbose
查找允许port 22(或您的自定义 SSH 端口)流量的规则。如果列出了 SSH,请确保它是ALLOW(允许)。 - firewalld:
bash sudo firewall-cmd --list-all
检查services(服务)和ports(端口)部分是否有ssh或port 22/tcp。 - iptables:
bash sudo iptables -L -v -n
此输出可能很复杂。在INPUT链中查找与tcp dpt:22(或您的自定义端口)相关的DROP(丢弃)或REJECT(拒绝)规则。
- UFW:
-
通过防火墙允许 SSH 端口:
- UFW:
bash sudo ufw allow ssh # 允许端口 22 # 或者,对于自定义端口(例如 2222): sudo ufw allow 2222/tcp sudo ufw enable # 如果 UFW 未启用 - firewalld:
bash sudo firewall-cmd --permanent --add-service=ssh # 或者,对于自定义端口(例如 2222): sudo firewall-cmd --permanent --add-port=2222/tcp sudo firewall-cmd --reload - iptables:
直接添加iptables规则更复杂,并且除非保存否则是暂时的。如果可用,通常建议使用firewalld或ufw。用于快速测试(非持久性):
bash sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 如果您希望这些规则在重启后仍然存在,则需要保存它们。
警告: 修改防火墙规则时要谨慎,尤其是在通过 SSH 连接到远程服务器时。错误的规则可能会永久将您锁定在服务器之外。如果您有当前的 SSH 会话打开,请务必在关闭会话之前验证您的更改是否有效。
- UFW:
第 3 步:验证 SSH 配置 (sshd_config)
SSH 守护程序的配置文件 (/etc/ssh/sshd_config) 决定了服务的运行方式。此处的配置错误可能导致连接被拒绝。
-
定位
sshd_config:
主配置文件通常位于/etc/ssh/sshd_config。 -
检查关键设置:
使用文本编辑器(例如nano、vi)打开文件:
bash sudo nano /etc/ssh/sshd_config
查找以下指令:Port:这指定了sshd监听的端口。确保它与您尝试从客户端连接的端口匹配。如果它被注释掉(#),则默认为端口 22。ListenAddress:如果存在,它指定了sshd应该监听的 IP 地址。如果将其设置为内部 IP(例如127.0.0.1),而您是从外部网络连接,则会拒绝连接。要监听所有接口,它通常被注释掉或设置为0.0.0.0或::(用于 IPv6)。PermitRootLogin:如果设置为no,您将无法以 root 身份登录。虽然这在严格意义上不是“连接被拒绝”(它通常是连接 后 的权限被拒绝),但它会阻止成功的登录尝试。PasswordAuthentication:如果设置为no,则禁用密码身份验证,需要基于密钥的身份验证。
提示: 对
sshd_config进行任何更改后,您 必须 重新启动 SSH 服务才能使更改生效:
bash sudo systemctl restart sshd
第 4 步:网络连通性(基本检查)
虽然“连接被拒绝”通常意味着服务器已被联系到,但最好还是快速确认您的客户端机器到服务器 IP 地址的基本网络可达性。
-
Ping 服务器:
从您的客户端机器,尝试 ping 服务器的 IP 地址或主机名:
bash ping <SERVER_IP_ADDRESS_OR_HOSTNAME>
如果 ping 失败(100% 丢包),则您存在更根本的网络问题(例如,IP 不正确、服务器离线、网络路由问题),需要在 SSH 之前解决。 -
使用
nc或telnet(从客户端):
要测试从客户端的角度来看端口是否打开并正在监听:
```bash
# 使用 netcat (nc)
nc -zv22 使用 telnet
telnet
22
`` 如果nc显示Connection refused或telnet` 立即退出,则确认服务器正在该端口上主动拒绝,这又指向 SSH 守护程序或防火墙。
第 5 步:检查 SELinux 或 AppArmor(高级)
在某些强化环境中,或在自定义配置之后,SELinux(Security-Enhanced Linux)或 AppArmor 可能会阻止 sshd 正常运行,尤其是在您使用非标准 SSH 端口时。
-
检查 SELinux 状态:
bash sestatus
如果 SELinux 处于enforcing(强制)状态,您可能需要调整其策略以允许sshd在自定义端口上运行。
例如,允许端口 2222 用于 SSH:
bash sudo semanage port -a -t ssh_port_t -p tcp 2222 sudo systemctl restart sshd
(如果semanage不可用,请安装:在 Debian/Ubuntu 上使用sudo apt install policycoreutils-python-utils,在 CentOS/RHEL 上使用sudo yum install policycoreutils-python)。 -
检查 AppArmor 状态:
bash sudo aa status
如果 AppArmor 处于enforcing(强制)状态,请查看其日志(/var/log/syslog或dmesg),查找与sshd相关的任何拒绝信息。
第 6 步:再次查看服务器日志
尝试了前面的步骤后,请务必重新检查服务器日志中是否有任何与 sshd 相关的新错误消息。这是了解服务器当前状态的最终真相来源。
sudo journalctl -u sshdsudo tail -f /var/log/auth.log(或/var/log/secure)
查找指示服务为何可能未启动、连接为何被丢弃或任何其他相关信息的消息。
预防未来问题的最佳实践
- 定期更新操作系统:保持服务器的操作系统和软件包(包括
openssh-server)处于最新状态。 - 测试防火墙规则:在实施或修改防火墙规则后,请务必立即进行测试。
- 备份
sshd_config:在对/etc/ssh/sshd_config进行更改之前,请进行备份(sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak)。 - 使用管理控制台:对于云实例,请了解如何在 SSH 不可用时访问服务器的控制台(例如,AWS EC2 串行控制台、Google Cloud Console)来排查网络问题。
- 监控日志:定期查看
auth.log或secure日志,以发现异常活动或持续性错误。
结论
“连接被拒绝”错误虽然令人沮丧,但通常通过系统地检查 SSH 守护程序状态、防火墙规则和 sshd_config 文件即可轻松解决。通过遵循本指南中概述的步骤,您可以有效地诊断根本原因并恢复您的安全远程访问。请记住,始终谨慎应用更改并验证功能,以避免将自己锁定在服务器之外。
有了这些故障排除技术,您将能够很好地应对 SSH 连接问题,并对您的远程系统保持无缝控制。祝您 SSH 连接顺利!