疑难解答常见的 SSH 错误:连接被拒绝和权限被拒绝
安全外壳(SSH)是远程系统管理的基础,提供加密通信以访问服务器。然而,遇到连接错误会立即中断工作效率。用户面临的最常见和最令人沮丧的两个错误是 "连接被拒绝"(Connection Refused)和 "权限被拒绝"(Permission Denied)。
本指南将引导您系统地诊断和解决这些问题。通过了解典型原因——从网络阻塞到错误的身份验证配置——您可以快速恢复对远程计算机的安全访问。我们将涵盖基本的检查,从验证服务器状态到调试身份验证机制。
理解错误:拒绝(Refused) vs. 权限拒绝(Denied)
区分这两个主要的错误消息至关重要,因为它们指向截然不同的根本原因:
- 连接被拒绝 (Connection Refused): 这通常意味着网络连接已到达服务器,但没有任何进程在指定的端口上监听,或者操作系统主动拒绝了连接尝试。
- 权限被拒绝 (Permission Denied): 这意味着 SSH 服务(sshd)成功接收了连接请求,但基于服务器配置,身份验证尝试(密码或密钥)失败。
第一部分:疑难解答连接被拒绝
"连接被拒绝"(Connection Refused)(常显示为 ssh: connect to host <hostname> port 22: Connection refused)通常指向服务器端阻止守护进程接受入站连接的问题。
1. 验证 SSH 守护进程(sshd)状态
最常见的拒绝原因是 SSH 服务器进程未运行或已崩溃。
可操作步骤(在远程服务器上):
使用 systemctl 检查服务状态(在现代 Linux 发行版中很常见):
systemctl status sshd
如果状态显示 inactive 或 failed,请启动服务:
sudo systemctl start sshd
# 使其在启动时自动启动
sudo systemctl enable sshd
2. 检查监听端口和配置
默认情况下,SSH 在 TCP 端口 22 上运行。如果为了安全加固而更改了端口,您必须在连接时指定正确的端口,或确保服务器正在监听预期的端口。
A. 查看 sshd_config
检查 SSH 配置文件,通常位于 /etc/ssh/sshd_config。查找 Port 指令:
# /etc/ssh/sshd_config 示例
Port 2222 # 如果不是 22,您需要在客户端指定
如果您更改了此文件,必须重启 sshd 服务才能使更改生效。
B. 验证监听套接字
使用 ss 或 netstat 确认 sshd 正在预期的接口和端口上积极监听。我们在此检查端口 22:
# 使用 ss(在现代系统上首选)
sudo ss -tuln | grep 22
# 预期显示监听状态的输出:
# LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
如果端口 22 没有显示任何内容,则表示守护进程未运行,或者配置为监听不同的地址/端口。
3. 防火墙和网络检查
在流量到达 sshd 进程之前阻止流量的防火墙通常会导致超时,但有时也会表现为连接被拒绝。确认服务器端防火墙规则至关重要。
常用防火墙命令(Ubuntu/Debian 上的 UFW):
允许 SSH 流量:
# 检查当前状态
sudo ufw status
# 允许默认端口 22 上的流量
sudo ufw allow ssh
# 或者按端口号
sudo ufw allow 22/tcp
# 重新加载防火墙规则
sudo ufw reload
⚠️ 关于外部防火墙的警告:如果您从远程网络连接,请确保任何中间网络设备、云安全组(如 AWS 安全组或 Azure NSG)或硬件防火墙都已明确允许 SSH 端口上的流量。
第二部分:疑难解答权限被拒绝
如果您成功连接到服务器但立即收到 "权限被拒绝 (publickey,password)"(Permission denied (publickey,password)),则问题完全在于身份验证。
1. 检查用户名和密码
这是最简单的检查,但常常被忽略:
- 用户名:您使用的是目标系统的正确用户名吗?Root 登录可能已被禁用。
- 密码:如果使用密码身份验证,请检查大小写锁定键(Caps Lock)、输入错误,并确保帐户未被锁定。
客户端检查:要查看详细的调试输出,请使用 verbose 标志运行客户端:
ssh -vvv user@hostname
此输出将清楚地显示客户端尝试了哪些身份验证方法以及服务器拒绝了哪些。
2. 基于密钥的身份验证失败
基于密钥的身份验证更优越,但配置错误是权限被拒绝的常见原因。
A. .ssh 目录权限不正确
SSH 对文件权限非常严格,以确保安全。如果权限过于开放,服务器将完全忽略密钥文件。
在远程服务器上(修复权限):
# 用户主目录的权限通常没问题,但请检查 .ssh 文件夹
chmod 700 ~/.ssh
# authorized_keys 文件只能由所有者写入
chmod 600 ~/.ssh/authorized_keys
B. 密钥不存在或格式不正确
确保您的公钥(id_rsa.pub 或类似文件)已正确追加到目标用户的服务器 ~/.ssh/authorized_keys 文件中。每个密钥必须独占一行,密钥字符串中间不能插入换行符。
C. 服务器配置禁用了密钥
检查服务器上的 /etc/ssh/sshd_config,确保允许密钥身份验证:
PubkeyAuthentication yes
# 如果您依赖密码,请确保未禁用密码身份验证
PasswordAuthentication yes
3. 服务器端日志调查
当身份验证失败时,服务器日志是最终的真相来源。查找与失败登录尝试相关的消息。
常用日志位置:
- Debian/Ubuntu:
/var/log/auth.log - RHEL/CentOS/Fedora:
/var/log/secure
使用 grep 过滤最近的连接尝试:
# 在 RHEL/CentOS 系统上
sudo grep 'Failed password' /var/log/secure
# 或者查看一般的 SSH 活动
sudo tail -f /var/log/secure
日志消息通常会明确说明为何密钥被拒绝(例如,选项错误、未找到匹配的密钥或用户上下文不正确)。
可靠 SSH 访问的最佳实践总结
- 使用密钥对:在验证密钥访问后,在
sshd_config中禁用密码身份验证(PasswordAuthentication no)。 - 更改默认端口:将 SSH 迁移出端口 22 可减少自动扫描的噪音。
- 使用
PermitRootLogin no:强制通过普通用户进行管理访问,迫使使用sudo。 - 备份配置:在对
/etc/ssh/sshd_config进行重大更改之前,务必备份原始文件:
bash sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F) - 本地测试:进行配置更改后,如果可能,请在服务器本地测试连接,然后再断开当前会话,以免将自己锁在外面。
通过系统地检查服务状态、网络路径和身份验证配置层,您可以迅速解决远程访问管理中固有的令人沮丧的 Connection Refused 和 Permission Denied 错误。