你尝试登录时,SSH立即停止并显示connect to host example.com port 22: Connection refused。该错误发生在SSH检查你的密钥或密码之前,因此更改认证设置无法解决此问题。

立即拒绝意味着目标地址上没有进程监听该端口,或者防火墙或网络设备主动拒绝了请求。常见原因包括SSH服务器已停止、主机或端口错误、监听器绑定到其他地址、防火墙拒绝规则或端口转发指向了错误的机器。连接挂起然后超时则不同,因为此时没有收到任何响应。

本指南首先介绍可从客户端执行的检查,然后深入服务器端的SSH服务、监听端口、防火墙和网络路径。

快速参考

如需可打印的快速参考,请参阅SSH速查表。

检查项命令
确认目标地址getent ahosts example.com
显示SSH连接详细信息ssh -vvv user@example.com
测试默认SSH端口nc -vz example.com 22
检查22端口上的监听器sudo ss -ltnp 'sport = :22'
显示有效的SSH端口和地址sudo sshd -T | grep -E '^(port|listenaddress) '
在Ubuntu或Debian上检查SSHsudo systemctl status ssh.service ssh.socket
在Fedora或RHEL上检查SSHsudo systemctl status sshd
检查UFW规则sudo ufw status numbered
检查firewalld服务sudo firewall-cmd --list-services

从客户端确认主机和端口

在更改服务器之前,先确认主机名解析到你期望的地址:

终端
getent ahosts example.com

如果结果指向旧服务器或错误的公共地址,请更正DNS记录或直接连接到预期的IP地址。即使真实服务器上的SSH运行正常,连接到错误的主机也可能导致拒绝。

接下来,使用详细输出运行SSH:

终端
ssh -vvv user@example.com

相关行如下所示:

输出
debug1: Connecting to example.com [203.0.113.10] port 22.
ssh: connect to host example.com port 22: Connection refused

客户端将example.com解析为203.0.113.10,并从22端口收到立即拒绝。你可以在不启动SSH登录的情况下测试TCP端口:

终端
nc -vz example.com 22

如果服务器使用自定义端口,请改为测试并连接到该端口:

终端
nc -vz example.com 2222
ssh -p 2222 user@example.com

主机名也可能具有不同的IPv4和IPv6地址。当一条DNS记录可能指向错误的服务器时,请测试每个地址族:

终端
ssh -4 user@example.com
ssh -6 user@example.com

其余检查需要你通过云控制台、虚拟机控制台、物理终端或其他管理渠道访问服务器。

检查SSH是否正在监听

监听套接字是判断服务器能否在22端口接受SSH连接的最快方法。在服务器上运行此命令:

终端
sudo ss -ltnp 'sport = :22'

正常的监听器显示为sshd或systemd,具体取决于发行版是持续运行守护进程还是使用套接字激活。如果命令返回空结果,则说明没有进程在22端口上接受连接。

要查看有效OpenSSH配置中的端口和地址,请运行:

终端
sudo sshd -T | grep -E '^(port|listenaddress) '

典型输出如下所示:

输出
port 22
listenaddress [::]:22
listenaddress 0.0.0.0:22

输出显示SSH配置为在所有IPv6和IPv4地址的22端口上运行。如果报告了其他端口,请使用-p选项连接,并验证防火墙允许该端口。如果需要更正配置,请参阅我们关于更改SSH端口的指南。

检查SSH服务或套接字

Linux发行版对OpenSSH使用不同的systemd单元名称。Ubuntu和Debian使用ssh.service,而Fedora、RHEL及其衍生版使用sshd.service。

在Ubuntu和Debian上,检查服务:

终端
sudo systemctl status ssh.service

Ubuntu 22.10及更高版本默认使用ssh.socket,因此也请检查该单元:

终端
sudo systemctl status ssh.socket

当ssh.socket处于活动状态并拥有22端口时,ssh.service在客户端连接之前可能保持非活动状态。在这种设置下,单独的服务非活动状态并不表示有问题。如果套接字被禁用或停止,请启用并启动它:

终端
sudo systemctl enable --now ssh.socket

在没有ssh.socket的系统上,请改为启用并启动服务:

终端
sudo systemctl enable --now ssh

在Fedora、RHEL及其衍生版上,请检查并启动sshd:

终端
sudo systemctl status sshd
sudo systemctl enable --now sshd

如果单元报告failed,请验证SSH服务器配置:

终端
sudo sshd -t

无输出表示配置测试通过。如果OpenSSH打印错误,请在重启单元之前更正报告的行。你还可以在Ubuntu和Debian上检查当前启动日志:

终端
sudo journalctl -u ssh.service -u ssh.socket -b

对于Fedora和RHEL,请使用sshd单元名称:

终端
sudo journalctl -u sshd -b

安装OpenSSH服务器

某些最小安装仅包含SSH客户端而不包含服务器。如果systemctl报告SSH单元不存在,请安装openssh-server软件包。

Ubuntu、Debian及其衍生版 #

更新软件包索引并安装服务器软件包:

终端
sudo apt update
sudo apt install openssh-server

该软件包通常会在安装过程中启动相应的SSH服务或套接字。请使用ss再次检查22端口,而不是假设监听器已成功启动。

Fedora、RHEL及其衍生版 #

安装服务器软件包,然后启用并启动sshd:

终端
sudo dnf install openssh-server
sudo systemctl enable --now sshd

检查监听地址

SSH可能正常运行,但仅监听回环接口或某个私有地址。在这种情况下,本地连接正常,而连接到服务器的其他地址则会被拒绝。

查看sshd -T输出中的listenaddress行。诸如127.0.0.1:22之类的值仅接受本地IPv4连接。OpenSSH从/etc/ssh/sshd_config读取其主配置,也可能读取/etc/ssh/sshd_config.d/下的文件。监听在回环地址上的服务只能从服务器本身访问,无法从其他任何位置访问。

在更改Port或ListenAddress之前,请保持控制台访问畅通,并使用sudo sshd -t验证新配置。在使用套接字激活的Ubuntu系统上,套接字还必须重新加载生成的监听配置。上面链接的端口更改指南按顺序涵盖了服务和套接字的步骤。

检查防火墙

防火墙导致立即拒绝的可能性低于缺少监听器。静默丢弃流量的规则通常最终会导致Connection timed out,而显式的REJECT规则可能返回Connection refused。在确认服务和端口之后,请检查防火墙。

如果服务器使用UFW,请以编号方式列出其规则:

终端
sudo ufw status numbered

当SSH使用22端口时,允许标准的OpenSSH配置文件:

终端
sudo ufw allow OpenSSH

对于自定义端口,请改为允许确切的TCP端口:

终端
sudo ufw allow 2222/tcp

在使用firewalld的服务器上,首先检查活动区域中允许的服务:

终端
sudo firewall-cmd --list-services

如果缺少SSH,请将其添加到运行时和永久配置中:

终端
sudo firewall-cmd --add-service=ssh
sudo firewall-cmd --permanent --add-service=ssh

对于自定义端口,请在两个命令中使用--add-port=2222/tcp。我们的UFW防火墙指南更详细地说明了如何查看和管理规则。

检查端口转发和外部防火墙

如果SSH在同一台机器或本地网络上正常工作,但从互联网连接失败,则OpenSSH监听器可能已配置正确。请检查路由器或虚拟化平台是否将外部端口转发到服务器的当前私有地址和SSH端口。

同样的问题也可能发生在虚拟机、容器、负载均衡器或云防火墙上。请确认公共DNS指向预期的系统,并且每个转发规则使用与传递给ssh相同的端口。云防火墙规则通常会丢弃流量并导致超时,但拒绝请求或将其转发到错误主机的边缘设备可能会导致连接被拒绝。

故障排除

SSH配置更改后开始出现连接被拒绝
运行sudo sshd -t并更正报告的所有错误。在Ubuntu上启用socket激活时,在有效的Port或ListenAddress更改后,重新加载systemd并重启ssh.socket,然后在关闭控制台访问前使用ss验证监听器。

SSH通过localhost可以工作,但通过服务器地址失败
检查有效的ListenAddress值以及外部接口的防火墙规则。如果监听器仅限制为127.0.0.1或::1,则无法接受远程连接。

IPv4可以工作,但IPv6被拒绝
服务器可能有一个AAAA记录,但没有对应的IPv6监听器。比较ssh -4和ssh -6,然后更正DNS记录或配置SSH以监听预期的IPv6地址。

仅有某个客户端地址被拒绝
可能是源地址特定的防火墙规则或Fail2ban等工具正在拒绝该地址。检查防火墙规则,如果安装了Fail2ban,请使用sudo fail2ban-client status sshd检查SSH jails。

SSH可以到达服务器,但报告Permission denied
网络路径和监听器正常工作,问题已转移到身份验证阶段。请遵循SSH Permission denied (publickey)指南进行操作。