文章背景图

SSH 突然无法连接:从网络、端口、服务到密钥认证的系统排查

2026-08-08
13
- 字
- 分钟

SSH 无法连接必须先按故障阶段分类:域名解析、路由、TCP 端口、SSH 握手、认证、登录后会话。把所有问题都归因于“密钥权限”或“代理”会浪费大量时间。本文给出客户端与服务端两侧都可执行的系统排查流程。

一、先读懂错误信息

  • Connection timed out:通常是路由、安全组、防火墙、NAT、代理或端口未响应。

  • Connection refused:目标可达,但该端口没有监听或被主动拒绝。

  • Connection reset / closed:中间设备或服务端在握手期间关闭连接。

  • Permission denied:已经连到 SSH 服务,问题位于用户、密钥、认证策略或目录权限。

  • Host key verification failed:主机指纹变化,应先核实实例身份,不能直接忽略。

二、确认目标没有连错

date -Is
nslookup example.com
# Linux/macOS
dig +short example.com
# Windows PowerShell
Resolve-DnsName example.com

核对 IP、端口、用户名、环境、堡垒机和云实例状态。若域名解析到 198.18.0.0/15 等测试保留地址,常见原因是代理软件的 Fake-IP DNS;应检查代理模式、DNS 和绕过规则,而不是把该地址当真实服务器地址。

三、从客户端测试 TCP 可达性

# Windows PowerShell
Test-NetConnection <HOST> -Port 22
# Linux/macOS
nc -vz -w 5 <HOST> 22
traceroute <HOST>   # Windows 使用 tracert

Ping 失败不等于 SSH 不通,因为 ICMP 可能被禁;关键是 TCP 目标端口。比较同网络、手机热点和另一台主机的结果,可以区分本机代理、办公网出口和服务端问题。

四、用详细日志定位停在哪一步

ssh -vvv -o ConnectTimeout=10 -p 22 ubuntu@<HOST>

日志停在 Connecting 表示 TCP 尚未建立;出现 Remote protocol version 说明 SSH 握手已经开始;Offering public key 后仍失败说明进入认证阶段。排障日志可能包含用户名、路径和主机信息,对外分享前要脱敏。

五、检查代理、VPN 和 MobaXterm

系统浏览器能访问网页,并不代表 SSH 会自动使用同一个代理。检查 MobaXterm 会话的 Network settings、SSH gateway、Proxy、端口转发和全局代理;暂时禁用代理后用 IP 直连做对照。若必须经过堡垒机,使用明确的 ProxyJump 配置。

ssh -J jumpuser@bastion.example.com ubuntu@private-host
ssh -G ubuntu@<HOST> | grep -Ei 'hostname|port|user|proxy'

若代理使用 Fake-IP DNS,要为服务器域名设置直连/真实解析规则。不要把私钥上传给代理服务或粘贴到聊天工具。

六、云侧逐层检查

  • 实例处于运行状态,公网 IP/EIP 没有变化。

  • 安全组入站仅允许可信来源 IP 到实际 SSH 端口。

  • 网络 ACL 入站和出站都允许请求及临时返回端口。

  • 公网子网有到 Internet Gateway 的路由;私网主机应通过 VPN、专线或堡垒机进入。

  • 源地址是否因公司出口、VPN 或家庭宽带变化。

不要为了排障长期把 22 端口开放到 0.0.0.0/0。临时规则也应限制源 IP、记录负责人并设置删除时间。

七、通过云控制台进入服务器后检查监听

如果 SSH 完全不可达,优先使用云厂商串口控制台、会话管理或救援模式进入,而不是反复尝试密码。

sudo ss -lntp | grep -E ':22'
sudo systemctl status ssh --no-pager   # Ubuntu/Debian
sudo systemctl status sshd --no-pager  # RHEL/CentOS
sudo journalctl -u ssh -u sshd --since "30 min ago" --no-pager
sudo sshd -t

sshd -t 无输出通常表示语法检查通过。修改配置后先验证,再 reload;保留现有已登录会话用于回滚,切勿先退出唯一管理通道。

八、防火墙、封禁和监听地址

sudo ufw status verbose
sudo firewall-cmd --list-all 2>/dev/null
sudo nft list ruleset
sudo iptables -S
sudo fail2ban-client status sshd 2>/dev/null

确认 sshd 是监听 0.0.0.0/:: 或目标网卡,而不是只监听 localhost。检查 fail2ban、安全代理和 TCP Wrappers 类策略是否封禁了当前出口 IP。解除封禁前确认来源可信,并追查为何触发。

九、密钥认证与权限

客户端私钥只应由当前用户读取;服务端 authorized_keys 及其父目录必须由目标用户拥有,且不能对组或其他用户可写。

# 客户端 Linux/macOS
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
ssh-keygen -y -f ~/.ssh/id_ed25519 | head
# 服务端
sudo -u <USER> stat -c '%U:%G %a %n' ~<USER> ~<USER>/.ssh ~<USER>/.ssh/authorized_keys
sudo chown -R <USER>:<USER> ~<USER>/.ssh
sudo chmod 700 ~<USER>/.ssh
sudo chmod 600 ~<USER>/.ssh/authorized_keys

Windows 上要通过文件属性或 icacls 移除多余继承权限,并确认 MobaXterm 选择了正确私钥格式。不要反复转换密钥覆盖原文件;先备份并通过公钥指纹核对。

十、服务端认证策略

sudo sshd -T | grep -Ei 'port|listenaddress|pubkeyauthentication|passwordauthentication|permitrootlogin|allowusers|denyusers|authorizedkeysfile|maxstartups'
sudo journalctl -u ssh -u sshd --since "10 min ago" | tail -100
getent passwd <USER>
sudo passwd -S <USER>

sshd -T 展示最终生效值,可发现 Include 和 Match 块覆盖。核对用户名、shell、账户锁定、AllowUsers/DenyUsers、PubkeyAuthentication 和 AuthorizedKeysFile。Ubuntu 云镜像常用 ubuntu,其他镜像可能是 ec2-user、debian 或 rocky。

十一、SELinux、磁盘和系统资源

df -hT
df -i
free -h
systemctl --failed
getenforce 2>/dev/null
ls -Zd ~<USER>/.ssh ~<USER>/.ssh/authorized_keys 2>/dev/null
sudo restorecon -Rv ~<USER>/.ssh 2>/dev/null

磁盘或 inode 满会导致日志、临时文件和会话创建失败;内存耗尽或进程数达到上限也会让连接被关闭。SELinux 标签异常时使用 restorecon 恢复策略标签,不要直接永久关闭 SELinux。

十二、连接建立后立即断开

ssh -vvv -tt ubuntu@<HOST> /bin/bash --noprofile --norc
sudo tail -n 100 /var/log/auth.log 2>/dev/null
sudo tail -n 100 /var/log/secure 2>/dev/null

重点检查 shell 是否存在、home 是否可访问、.bashrc/.profile 是否包含 exit 或失败命令、PAM、磁盘空间、MaxSessions 和命令限制。用最小 shell 测试可以区分认证成功后的环境问题。

十三、安全修改与回滚流程

  1. 保持一个已登录会话不关闭,并准备云控制台备用通道。

  2. 备份配置,单次只改一个变量。

  3. 执行 sshd -t,确认无错误后 reload 而不是 restart。

  4. 新开终端验证登录、sudo、文件传输和堡垒链路。

  5. 失败立即恢复备份并 reload;验证成功后再关闭旧会话。

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d%H%M%S)
sudo sshd -t && sudo systemctl reload sshd  # Ubuntu 服务名可能为 ssh

十四、故障检查清单

  • □ 已根据错误信息确定网络、握手、认证或会话阶段

  • □ 域名、真实 IP、端口、用户名和出口 IP 已核对

  • □ 代理/VPN/Fake-IP 与直连结果已对比

  • □ 云安全组、ACL、路由和主机防火墙已逐层检查

  • □ sshd 监听、配置语法、日志和最终认证策略已确认

  • □ 密钥所有权、权限、指纹和 SELinux 标签已确认

  • □ 修改前保留可用会话,验证后再结束旧通道

总结

SSH 排障最有效的方法是按连接阶段缩小范围:先确认目标与 TCP,再看握手、认证和会话。代理、密钥权限只是其中两个分支;用客户端 -vvv、服务端日志和云网络证据相互印证,才能安全恢复而不扩大暴露面。

原创

SSH 突然无法连接:从网络、端口、服务到密钥认证的系统排查

本文链接: SSH 突然无法连接:从网络、端口、服务到密钥认证的系统排查

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录