先别急着去看网卡、改防火墙、重装系统。SSH连不上Ubuntu虚拟机这个问题,我前前后后排查过不下几十次,有帮同事救急的,也有自己半夜折腾的。其实90%的情况都逃不出几个固定套路,只要你愿意静下心来看一眼报错信息,很多问题在两分钟内就能定位。这篇文章我就把你可能遇到的所有坑,从网络层到服务层到认证层,一条条拆开讲清楚。
1. 先看报错文字:三类典型失败信息分别指向哪个环节
这是最容易被忽略、但价值最高的一步。很多人的做法是SSH连不上了,赶紧打开VMware把虚拟机重启一遍,结果没用;再检查一下网卡设置,还是没用;最后甚至把Ubuntu重装了,问题依旧。核心原因就是你根本没有读SSH告诉你什么。
SSH是个很老实的工具,它把所有失败原因都分成不同层次写在报错里。不同报错文字代表完全不同的故障区间,排查方向也完全不一样。
| 报错关键字 | 故障层次 | 优先排查方向 | 常见原因 |
|---|---|---|---|
Connection refused | 服务端应用层 | SSH服务没开、22端口没监听 | openssh-server没装、sshd没启动、防火墙REJECT |
Connection timed out | 网络层 | 数据包根本没到对方 | 网卡没配对、IP网段不同、防火墙DROP、VMware网络模式错误 |
No route to host | 网络层 | 路由不通 | 网关配置错误、虚拟网络编辑器配置损坏 |
Permission denied (publickey,password) | 认证层 | 账号密码或密钥不对 | 密码错误、sshd_config禁止密码登录、root被限制 |
REMOTE HOST IDENTIFICATION HAS CHANGED | 认证层 | known_hosts缓存冲突 | 系统重装、快照回滚、IP被别的机器占用 |
| 连接后立即断开 / 卡在登录后没反应 | 会话层 | shell初始化或服务配置问题 | 登录shell异常、DNS反解超时、资源耗尽 |
记住这个对应关系,你就有了定位问题的地图。
1.1 Connection refused:服务端根本没开门
字面意思就是连接被拒绝了,这说明你的网络是通的,请求顺利到达了对方的机器,但对方机器上没有程序在22端口监听。打个比方就是你按了门铃,屋里有人也知道你来了,但就是不开门。
这个报错出现时,你要检查的是虚拟机里面SSH服务是否安装、是否运行。这是新手最常见的翻车点,因为Ubuntu桌面版默认不会安装openssh-server,你装完系统直接就想SSH连上去,那肯定是不行的。
1.2 Connection timed out:你根本就没找到门
Connection timed out意味着你的数据包发出去之后石沉大海,没有任何回应。可能是虚拟机没开机、网络没连通、IP地址变了,也有可能是中间的防火墙悄悄把你的包丢了。
这里有个重要的概念区分:REJECT和DROP。如果防火墙规则是REJECT,客户端会立刻收到Connection refused;如果是DROP,客户端就只能傻等直到超时,报Connection timed out。所以看到timeout,第一反应应该是去查网络连通性,而不是去看SSH服务。
1.3 连接串起来了,但卡在认证环节
还有一类报错不是连不上,而是连上了但进不去。比如Permission denied。这说明网络通了、服务也正常跑着,但账号密码或者密钥验证没过。这种问题排查思路完全不同,后面第5章专门展开。
看到这里你应该明白了:SSH的报错信息不是乱写的,它就是一份故障分层地图。带着这张地图去排查,你永远不会做无用功。
2. 网络层排查:VMware NAT、桥接、仅主机三种模式下的连通性定位
网络层问题占了SSH连接失败的很大比例,尤其是VMware虚拟机,网络模式搞错了或者虚拟网络编辑器没配好,能整出各种奇怪的现象。
2.1 VMware三种网络模式的选型逻辑
VMware给虚拟机提供了三种网络模式,很多新手不理解它们之间的区别,于是就在默认选项里瞎选,最后网络完全不通。
NAT模式(默认):虚拟机在VMware创建的私有网段内(通常是192.168.xx.0/24),通过宿主机的网络地址转换访问外网。宿主机可以看到这个私有网段,虚拟机也能访问宿主机。这是最常用的模式,因为不需要宿主机和虚拟机在同一网段,也不会占用局域网IP资源。
用NAT模式时,有几个IP地址你必须知道:
- 虚拟机自己的IP:一般在192.168.xx.128~254之间(DHCP分配)
- 网关:通常是192.168.xx.2(VMware虚拟路由器)
- 宿主机侧对应网卡VMnet8:通常是192.168.xx.1
桥接模式:虚拟机就像是局域网里的一台独立电脑,直接使用和宿主机同一网段的IP。适用于需要局域网内其他真实设备直接访问虚拟机的场景。缺点是会占用真实IP,且如果路由器开启了AP隔离,虚拟机之间可能无法互通。
仅主机模式:虚拟机只能和宿主机通信,不能访问外网。适合完全隔离的测试环境,但如果你想在虚拟机里安装软件包,这模式就行不通了。
如果你只是做开发、跑服务,NAT模式是最省心的。但NAT模式有个容易踩的坑:VMware在分配网段时,不同版本默认网段不一样,有的版本是192.168.128.0/24,有的是192.168.188.0/24,还有的是192.168.217.0/24。你必须在VMware的虚拟网络编辑器里确认实际网段,不要凭空猜测。
2.2 ping不通时,按这三步顺序定位
不要一上来就凭感觉乱试,按照下面的顺序一步步排查:
第一步,在虚拟机里确认自己的IP地址。打开终端,执行ip addr查看网卡是否有IP。如果网卡没有IP,说明DHCP没生效或者网卡没启动。很多Ubuntu服务器版默认没有启用DHCP,需要手动编辑netplan配置。这一步能避免你拿着错误的IP在宿主机上猛敲命令。
第二步,在宿主机上ping虚拟机的IP。如果通了,说明宿主机到虚拟机的物理链路是通的;如果不通,进第三步。这里注意Windows防火墙可能会拦截ICMP请求导致ping不通,但SSH却可以连接。所以ping不通不代表SSH就一定连不上,反过来也一样。
第三步,在虚拟机里ping网关。比如ping 192.168.188.2。如果网关ping不通,说明虚拟机的路由有问题,或者VMware的NAT服务没有正常运行。去Windows的服务管理器里看看VMware NAT Service和VMware DHCP Service这两个服务是否启动,这是很多莫名奇妙网络不通的元凶。
2.3 一个容易忽略的物理前提:宿主机的VMnet网卡
在NAT模式下,宿主机通过VMnet8这张虚拟网卡与虚拟机通信。如果这张网卡被禁用了,那就算虚拟机IP再正确也没用。
排查方法:在Windows的命令行里执行ipconfig,看看有没有VMnet8的条目。如果没有,或者显示的是"媒体已断开连接",去控制面板 > 网络和 Internet > 网络连接里找到VMware Network Adapter VMnet8,启用它,并检查它的IP地址是否和VMware虚拟网络编辑器里配置的一致。
顺便说一个跟网络层无关但容易碰到的现象:有时候SSH连接会卡在输入密码前的那个阶段,等很久才提示输入密码,或者连接成功后敲命令明显有延迟感。这个大概率是SSH服务端在做DNS反解,也就是把连接方的IP解析成主机名,在局域网环境下这个解析会超时。解决方法是改一下sshd_config里的UseDNS no,后面第5章会讲。
3. 服务端检查:openssh-server 装没装、跑没跑、端口有没有在听
网络通了,那就该把目光转向虚拟机内部了。SSH服务这一层的问题是除了网络之外的第二大翻车点。
3.1 默认不安装的openssh-server:头号翻车点
Ubuntu桌面版默认是不安装SSH服务端的,服务器版在安装时如果没勾选也会缺。很多人用虚拟机装完Ubuntu桌面版后第一件事就是想用SSH连上去,结果自然是Connection refused。
检查命令:
dpkg -l | grep openssh-server如果没有任何输出,或者只看到ii状态但版本号很旧,那就直接安装:
sudo apt update sudo apt install openssh-server安装完成后,SSH服务会自动启动。这里有个小细节:在Ubuntu上服务名是ssh而不是sshd。你执行systemctl status sshd会提示找不到服务,但执行systemctl status ssh就是正常的。这个命名细节坑了不少从CentOS转过来的老手。
3.2 端口到底有没有在监听:ss vs netstat
确认SSH服务在运行后,还要确认22端口真的在监听。有些情况下服务显示active但端口没开(比如配置文件里改了Port但服务没重启成功,或者端口被别的进程占用)。
sudo ss -tlnp | grep :22看到类似LISTEN 0 128 0.0.0.0:22的输出才是正常的。注意这里必须是0.0.0.0:22,如果看到的是127.0.0.1:22,说明sshd只开启了本地回环监听,外人根本连不进来。这种情况通常是/etc/ssh/sshd_config里的ListenAddress配置错了。
如果端口没在监听,看一下服务的运行日志:
sudo journalctl -u ssh --no-pager -n 50日志会告诉你服务为什么没起来,可能是配置文件语法错误、端口被占用,或者其他依赖问题。
3.3 配置改错导致的"假连不上"
SSH连接失败还有一种不太常见但很迷惑人的情况:配置文件的Port被改成了非22端口。你还在傻傻地敲ssh user@ip,对方却在9527端口等你。
检查/etc/ssh/sshd_config,看看有没有非注释状态的Port配置。注意这个文件的注释默认很多,不要被带偏。如果你确实改了端口,连接时就要用ssh -p 9527 user@ip。
另一个高频坑是PermitRootLogin。如果你试图用root账号登录,而配置是PermitRootLogin prohibit-password(Ubuntu的默认值),密码登录会被拒绝。你需要用一个普通用户登录,然后su -切到root,或者把配置改成yes后重启服务。
4. 防火墙与安全策略:ufw、iptables、fail2ban 都在拦什么
网络通了、服务也开了,但连接还是失败?那就要看防火墙了。这个东西平时不吭声,关键时刻能让你怀疑人生。
4.1 ufw没放行22端口的问题
Ubuntu自带的防火墙是ufw。很多教程会让你sudo ufw enable开启防火墙,但没告诉你要提前放行SSH端口。结果防火墙一开,SSH连接立刻断了,然后卡在虚拟机面前手足无措。
查看防火墙状态:
sudo ufw status如果显示Status: active,看看输出里有没有22/tcp或者OpenSSH的ALLOW规则。没有就放行:
sudo ufw allow 22/tcp # 或者 sudo ufw allow OpenSSH这里有个细节值得说一下:ufw的默认策略是拒绝所有入站连接,所以如果你开了ufw却没放行22端口,从客户端看可能是Connection refused(如果ufw用了REJECT策略),也可能是timeout(如果DROP了)。不同Ubuntu版本策略略有差异,保险起见两个方向都检查一遍。
4.2 iptables的隐藏规则
ufw只是包在iptables外面的一层壳,实际生效的是iptables规则。有时候ufw显示没启动,但iptables里却有历史遗留的规则在拦着。
直接查看当前的iptables规则:
sudo iptables -L -n --line-numbers重点关注INPUT链。如果看到有DROP或REJECT的规则在22端口之前的行号位置,那就是它在捣乱。清理方法:
sudo iptables -D INPUT <行号>注意iptables规则是即时生效且不持久的,reboot之后规则会清空。如果你需要永久保存规则,要安装iptables-persistent并把当前规则导出。
4.3 fail2ban:你之前可能把自己给ban了
这个问题非常隐蔽。如果你在虚拟机上装过fail2ban,而且此前有过几次SSH密码输入错误,它会把你的IP加入黑名单。被ban之后的症状很迷惑——有时候是连接超时,有时候是连接被拒绝,而且大概率你在虚拟机的终端上检查SSH服务一切正常。
查看是否被ban:
sudo fail2ban-client status sshd输出里会有"Currently banned"列表。如果看到你的宿主机IP在里面,执行:
sudo fail2ban-client unban <你的IP>说实话fail2ban在局域网里有点用但不多。如果你只是自己开发用,我建议干脆别装,它省下的安全成本远不及它给你添的堵。
5. 认证卡点:密钥权限、known_hosts 和 sshd_config 的隐藏限制
前面的坑都排完了,SSH也连上了,但卡在输密码或者输完密码进不去,这时候问题出在认证环节。这条路上的坑更细碎,需要耐心。
5.1 Permission denied (publickey,password) 的逐项拆解
这个报错说明SSH服务端拒绝了你的凭据。可能是密码真的错了,也可能是服务端根本不接受密码登录。
先排除最普通的:密码错误。注意Linux终端输入密码时不显示任何字符,很多人在虚拟机里输错了都不知道。建议在虚拟机本机的终端里先确认你的密码能登录,省的做无用功。
如果密码没问题,查看/etc/ssh/sshd_config里这两个关键配置:
PasswordAuthentication yes PermitRootLogin prohibit-passwordPasswordAuthentication no意味着密码登录被禁用,只允许密钥登录。很多安全教程会让你关掉密码登录,但没提醒你用虚拟机的时候别关。PermitRootLogin prohibit-password意味着root账号不能直接用密码登录,只能密钥登录。很多人在这一步卡了很久,因为用root连不上就以为系统有问题,其实只是策略限制。
改完配置记得重启服务:
sudo systemctl restart ssh5.2 密钥登录时的权限地狱
密钥认证是另一个高频出问题的地方,而且权限问题占大头。SSH对密钥相关文件的权限要求非常严格,权限过宽直接拒绝加载。
标准权限应该是:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod 600 ~/.ssh/id_rsa # 私钥 chmod 644 ~/.ssh/id_rsa.pub # 公钥如果你把authorized_keys设成644,或者把~/.ssh设成755,SSH服务会直接无视这个文件,然后报Permission denied,你还一脸懵。
还有一个小坑:把公钥写入authorized_keys时,一定要写成一行完整的ssh-rsa AAAA...格式,不要手贱换行。公钥中间任何换行都会导致认证失败。
5.3 REMOTE HOST IDENTIFICATION HAS CHANGED:known_hosts冲突
这个报错遇到过的人一定印象深刻,它整段红字还加粗,告诉你"远程主机标识已更改",看着就很吓人。
它出现的原因是:SSH客户端会在~/.ssh/known_hosts文件里记录每个IP对应的主机指纹(host key)。如果虚拟机系统重装了、VMware快照回滚了、或者局域网里某个IP被另一台机器占用了,客户端发现指纹对不上,就会拒绝连接。
解决办法很简单,删掉那个IP的旧指纹记录:
ssh-keygen -R 192.168.188.128然后重新连接,输入yes确认新指纹即可。注意:如果你用VSCode远程开发插件,VSCode有自己独立的known_hosts管理方式,但报错逻辑和命令行SSH是一致的。
5.4 登录后立即断开或卡住的隐藏原因
有一种情况是SSH能连上,密码也正确,但登录后立即断开,或者卡在某个界面半天没反应。除了最明显的/etc/ssh/sshd_config里UseDNS no要加上、GSSAPIAuthentication no建议加上之外,还要检查用户的登录shell。
如果用户shell被改成了/usr/sbin/nologin或/bin/false,SSH登录成功后会在启动shell这一步被拒绝,表现为"连接已关闭"或直接闪退。查看用户shell:
chsh -l # 列出所有合法shell cat /etc/passwd | grep <用户名>如果/etc/passwd里对应行末尾是/usr/sbin/nologin,那就改回/bin/bash:
sudo usermod -s /bin/bash <用户名>6. VMware特有的冷门坑与一条龙排查命令清单
最后这部分讲讲VMware这个特定环境下的坑,顺便给一份可以直接照做的完整排查流程。
6.1 快照回滚和虚拟机克隆后的连锁反应
这个坑非常隐蔽,我在帮人排查时遇到过两次。如果你给虚拟机做过快照,然后在某个时间点回滚了,你会遇到两个问题:
一是MAC地址变了。回滚后的网卡MAC和客户端known_hosts里记录的指纹对应不上,触发REMOTE HOST IDENTIFICATION HAS CHANGED报错。用上面说的ssh-keygen -R即可解决。
二是Ubuntu的网卡名称变了。Ubuntu用netplan管理网络,配置文件名一般是/etc/netplan/01-network-manager-all.yaml或类似的名字。如果你在配置里写了固定的网卡名比如ens33,快照回滚后网卡变成了ens38,那虚拟机启动后这个网卡配置就不会被应用,导致没有IP或者IP不正确。
查看当前网卡真实名称:
ip addr然后修改netplan配置,把网卡名改对,或者干脆用通配符match:匹配MAC地址。改完执行:
sudo netplan apply6.2 VMware的后台服务也是隐形炸弹
VMware Desktop安装在Windows上的时候,会注册一堆Windows服务。跟网络相关的主要是:
VMware NAT ServiceVMware DHCP ServiceVMware USB Arbitration Service(这个跟SSH关系不大)
如果NAT服务没启动,虚拟机的网络会变得极其诡异,比如虚拟机自己显示有IP,但宿主机ping不通,虚拟机上不了网。很多人这时候会去折腾虚拟机的网络配置,其实看一眼Windows的服务列表就能解决问题。
在Windows上用Win+R输入services.msc打开服务管理器,找到这三个服务,确认是"正在运行"。如果停了,右键启动并设置为自动启动。
6.3 从零开始的完整排查命令清单(直接抄作业)
为了让这套经验可以直接落地,我把排查流程整理成一份可以按顺序执行的清单。建议在遇到SSH连接失败时,从头到尾走一遍,十有八九能把问题揪出来。
宿主机侧操作:
# 1. 确认VMnet8虚拟网卡状态 ipconfig /all # 2. 确认VMware NAT和DHCP服务运行中 services.msc # 3. 试着ping一下虚拟机IP ping 192.168.188.128虚拟机侧操作:
# 4. 确认网卡有IP且网关正确 ip addr ip route # 5. 检查SSH服务安装状态和运行状态 dpkg -l | grep openssh-server systemctl status ssh # 6. 检查22端口监听情况 sudo ss -tlnp | grep :22 # 7. 检查防火墙状态 sudo ufw status sudo iptables -L -n | grep :22 # 8. 查看SSH服务日志定位原因 sudo journalctl -u ssh --no-pager -n 50 tail -30 /var/log/auth.log客户端侧操作:
# 9. 用详细日志模式连接,观察卡在哪一步 ssh -vvv user@192.168.188.128 # 10. 遇到host key冲突时清理指纹 ssh-keygen -R 192.168.188.128整套流程走下来,常规的SSH连接失败问题基本都能定位。我自己的体会是,这个问题的难点从来不是单点原因有多复杂,而是你愿不愿意按照从"网络层到服务层再到认证层"的顺序逐步排查。很多人栽跟头都是因为跳过了某一步,直接凭感觉下结论,结果绕了一大圈才发现是最初级的错误。按这份清单走,你就能少走很多弯路。