尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

VMware虚拟机SSH连接指南:NAT直连、端口转发与排错

VMware虚拟机SSH连接指南:NAT直连、端口转发与排错 从宿主机直接敲一条 ssh 命令就能连进 VMware 里的 Ubuntu这事听起来不难但真操作起来你会发现网上说法乱七八糟有人让你改桥接有人让你做端口转发还有人直接说 NAT 模式连不上虚拟机。我当年第一次搞这个也绕了不少弯路后来把 VMware 的三种网络模式、宿主机侧的端口转发、虚拟机侧的 SSH 服务配置全部理了一遍才彻底搞明白哪些说法对、哪些是误导。这篇文章就把这套完整链路讲清楚先解决网络层怎么通再解决 SSH 服务怎么起最后补充排错方法和 VSCode 远程开发的实际接入。适合 Windows 宿主机 VMware Workstation 跑 Linux 虚拟机或者 Linux 宿主机 VMware Fusion/Workstation 的读者参考。1. 先搞清楚你为什么要 SSH 进虚拟机需求决定了网络方案很多教程一上来就让你选网络模式但你如果不知道自己到底想要什么样的连通很容易选错方向。我自己总结下来从宿主机访问虚拟机的需求基本就三类每一类对应的网络方案完全不同。第一类是开发调试型。你在 Windows 上写代码但代码要在 Linux 环境里跑比如验证 shell 脚本、编译 C 程序、跑 Python 服务。这种场景你通常只需要宿主机自己访问虚拟机就行不要求局域网里的其他电脑也能连过来。这种情况下NAT 模式完全够用而且配置最少。第二类是服务对外型。你在虚拟机里搭了一个 Web 服务、数据库或者 API 接口不但要自己访问还要让局域网里的同事、其他设备也能通过宿主机或路由器访问到。这时候你就得考虑端口转发或者直接把虚拟机改成桥接模式。第三类是远程运维型。虚拟机可能是你从别人那里拷贝来的镜像或者是在服务器上批量跑的实例你需要通过 SSH 做日常管理、传文件不想每次都用 VMware 的图形界面打开控制台。这时候网络模式反而不重要重要的是把 SSH 服务端配好、网络和防火墙全部放通。想明白需求之后你再去选网络模式就不会纠结。而且这里有一个必须强调的前提SSH 能不能连上取决于网络层通不通、22 端口能不能到达、SSH 服务在不在跑三者缺一不可。很多人在网上搜ssh访问vmware虚拟机搜到一堆端口转发教程结果折腾半天发现根本不需要端口转发——他要用的是第一种场景直接连 NAT 的 IP 就行。所以这篇文章的章节顺序就是按这个思路排的先让你搞清楚自己属于哪一种需求再告诉你每种需求对应的最优解。2. VMware 三种网络模式快速扫盲选错模式后面全是坑VMware Workstation 里创建虚拟机的时候会让你选网络连接方式常见的就是 NAT、桥接、仅主机三种。很多人一路回车默认用了 NAT但也有人为了让宿主机能访问虚拟机直接把虚拟机改成桥接结果虚拟机起不来、IP 也拿不到这就是典型的选错模式。我先用比较好懂的方式把三种模式讲清楚。NAT 模式虚拟机和宿主机之间有一块虚拟交换机默认是 VMnet8虚拟机在这个虚拟交换机的私有网段里拿 IP对外通信时由 VMware 的 NAT 服务做地址转换。你可以把 NAT 理解成一个小区门卫虚拟机是小区里的住户门卫帮他收发快递网络数据。虚拟机可以访问外网外网也能把响应数据送到虚拟机但外部设备没法直接主动找到虚拟机——因为虚拟机的地址是小区内部地址外面根本不知道有这个门牌号。桥接模式虚拟机直接连到宿主机所在的物理局域网和宿主机就像两台并排接在同一个路由器上的电脑各自从路由器获取 IP。这时候虚拟机有了和宿主机同一个网段的地址局域网里的任何设备都能直接访问它前提是路由器分配 IP、没有开 AP 隔离。桥接模式相当于虚拟机从小区里搬出来自己拥有了一个公开门牌号。仅主机模式虚拟机只和宿主机之间有虚拟交换机默认是 VMnet1它没有门卫帮它访问外网虚拟机对外是隔离的只能和宿主机以及同一台宿主机上的其他仅主机虚拟机通信。三种模式的对比我用表格列一下方便你参照选型模式虚拟网卡虚拟机能否访问外网宿主机能否访问虚拟机局域网其他设备能否访问虚拟机典型场景NATVMnet8能通过宿主机 NAT 转发能直连虚拟机 IP 即可默认不能需要端口转发宿主机开发调试桥接和物理网卡绑定能直接走路由器能直连虚拟机 IP 即可能直连虚拟机 IP 即可Web 服务对外展示仅主机VMnet1不能能直连虚拟机 IP 即可不能隔离测试环境网上一堆宿主机连不上虚拟机的案例绝大多数问题不是模式选错了而是模式选的没问题、但 IP 段、防火墙、SSH 服务这几个细节没处理好。所以我建议你先按这张表确认自己的模式没有搞错再往下走。另外提醒一句VMware Workstation 的虚拟网络编辑器锁定和权限问题很常见。如果你打开编辑 - 虚拟网络编辑器想改网段发现按钮是灰的、改不了那是因为你没用管理员权限运行 VMware。Windows 下请右键 VMware Workstation 图标选择以管理员身份运行再进去改网络设置。这个细节网上叫wmware 17虚拟机没有配置和打开选项根源就是权限不够。3. 最简单的本地主机直连方案NAT 模式下直接 SSH 虚拟机 IP现在说一个很多教程搞错、甚至直接说错的核心结论NAT 模式下宿主机是可以直接 SSH 连虚拟机的不需要做任何端口映射。为什么能连你打开 VMware 的虚拟网络编辑器看一下NAT 模式绑定的是 VMnet8 这块虚拟网卡宿主机上会多出一个 VMnet8 地址默认是 192.168.x.1虚拟机在同一个私有网段里拿地址比如 192.168.x.128。宿主机访问 192.168.x.128 的时候数据从 VMnet8 虚拟网卡出发直接发到 VMnet8 虚拟交换机然后到达虚拟机。整个通信过程都在宿主机内部的虚拟网络里完成根本不经过 NAT 地址转换。那为什么网上有人说NAT 连不上因为他们说的外网设备访问虚拟机。如果你在局域网里拿另一台物理电脑去 SSH 虚拟机那确实连不上因为那台电脑和虚拟机不在同一个网段。但宿主机自己访问是没问题的。实际步骤如下创建 Ubuntu 虚拟机网络模式保持默认的 NAT虚拟机里执行ip addr查看当前 IP记下来比如192.168.88.128确认宿主机 VMnet8 的地址在同一网段Windows 上执行ipconfig找到 VMware Network Adapter VMnet8 那一项看到 IP 是192.168.88.1之类的就说明没问题宿主机打开终端Windows 的 CMD、PowerShell 都行执行ping 192.168.88.128能通再继续执行ssh user192.168.88.128按提示输入密码。这个方案最大的优点就是零配置只要虚拟机把 SSH 服务装好、防火墙放行 22 端口就行。这也是我最推荐给开发调试型用户的做法不用改任何网络设置也不用记什么端口映射。但它也有个前提条件VMware 的 NAT 网段不要和宿主机所在的物理局域网网段冲突。比如你的公司局域网是192.168.88.0/24而 VMware NAT 默认恰好也是192.168.88.0/24就会出问题。最好手动把 NAT 网段改成一个不太常见的私有网段比如192.168.137.0/24或者10.10.88.0/24。改的时候右键 VMware 用管理员身份打开虚拟网络编辑器选中 VMnet8把子网 IP 改掉再把 DHCP 设置里的地址池跟着改保存后重启虚拟机生效。还有一个容易踩的坑如果你之前用过桥接模式虚拟机里可能配的是静态 IP切回 NAT 之后 IP 不会自动更新SSH 就会连不上。这时候去虚拟机里把网络配置改成 DHCP或者手动改成 NAT 网段的地址再重启网络就行。4. 网络不通时再上端口转发NAT 端口映射的完整配置如果你遇到的情况是宿主机 ping 不通虚拟机或者你希望能通过宿主机 IP 一个自定义端口来访问虚拟机比如你在生成环境里只需要开放宿主机的一个端口其他端口全部封闭这时候才需要做端口转发。还有另一种常见需求一台宿主机上跑了好几台虚拟机每台虚拟机的 IP 都是 NAT 私有网段里的地址为了让别的机器可以通过宿主机的一个公网/局域网 IP 访问这些虚拟机就需要给每台虚拟机映射一个不同的宿主机端口。端口转发的原理是宿主机在某个端口上监听收到数据后原封不动地转给虚拟机的指定 IP 和指定端口。比如宿主机监听2222端口把数据转发给虚拟机的192.168.88.128:22这样别人 SSH 到宿主机2222端口实际上就连接到了虚拟机的22端口。4.1 Windows 宿主机上用 netsh 做端口转发Windows 宿主机最方便的端口转发方式是用系统自带的netsh命令不需要装任何额外工具。以管理员身份打开 CMD 或 PowerShell执行netsh interface portproxy add v4tov4 listenport2222 listenaddress0.0.0.0 connectport22 connectaddress192.168.88.128这行的意思是宿主机在所有网卡的2222端口上监听把数据转发到192.168.88.128的22端口。注意listenaddress0.0.0.0表示监听所有网卡这样局域网里的其他机器也能通过宿主机 IP 的2222端口访问这台虚拟机。添加完规则后还要在 Windows 防火墙里放行这个端口否则外部请求会被拦截netsh advfirewall firewall add rule nameSSH-VM-2222 dirin actionallow protocolTCP localport2222查看当前所有端口转发规则用netsh interface portproxy show all删除某条规则用netsh interface portproxy delete v4tov4 listenport2222 listenaddress0.0.0.0测试的时候就执行ssh user宿主机IP -p 2222。如果你在宿主机本机测试宿主机IP填127.0.0.1或者localhost都行。4.2 Linux 宿主机上修改 NAT 配置做端口转发如果你是在 Linux 上装了 VMware Workstation改 NAT 配置文件的路径一般是/etc/vmware/vmnet8/nat/nat.conf。用 sudo 编辑这个文件找到[incomingtcp]这一段默认是空的[incomingtcp] # 2222 192.168.88.128:22把注释去掉改成[incomingtcp] 2222 192.168.88.128:22保存后重启 VMware 的 NAT 服务sudo systemctl restart vmware-networks-configuration或者如果这个服务名称不对可以试试sudo vmware-networks --restart然后测试ssh user127.0.0.1 -p 2222。4.3 关于 VMware 自带的端口转发设置面板在 VMware Workstation 的虚拟网络编辑器里选中 VMnet8点NAT 设置会看到一个端口转发的表格。我可以明确告诉你这个面板的限制比较多它只预设了几个服务类型而且有些版本你手动填端口转发规则之后并不生效尤其是在 Windows 宿主机上很多用户反馈加了规则但连不上最后还得回到 netsh 方案。所以我的建议是Windows 宿主机直接用 netshLinux 宿主机直接改 nat.conf不要去依赖 VMware 图形界面里的端口转发面板少踩一个坑。端口转发方案适合要在宿主机上开放固定端口给外部访问的安全敏感场景。比如你只想让局域网同事通过宿主机 IP 的2222端口访问虚拟机而不愿意把虚拟机的 IP 暴露出去那 NAT netsh 是很好的组合。但如果你只是想自己从宿主机 SSH 进去直接第 3 章的做法就够了不需要绕这一圈。5. 桥接与仅主机模式另外两条路的适用边界既然有更简单的 NAT 直连方案为什么还要桥接答案很现实NAT 直连只有宿主机自己能访问公司其他同事的电脑要访问虚拟机走 NAT 就得通过你宿主机转发还得配置端口映射麻烦。有些场景你反而希望虚拟机独立出现在局域网里有自己的 IP这就是桥接的用武之地。5.1 桥接模式下的 SSH 直连桥接模式下虚拟机直接向路由器请求 IP和宿主机在同一个物理网段。比如你的宿主机 IP 是192.168.3.10路由器 DHCP 给虚拟机分配了192.168.3.50那么宿主机直接ssh user192.168.3.50就能连上局域网里其他电脑也一样能直接连。但这个方案有两个比较头疼的问题。第一个是虚拟机 IP 不固定DHCP 分配可能每次都变。我建议在虚拟机里给网卡配置静态 IP指定一个路由器 DHCP 地址池之外的地址比如路由器 DHCP 是192.168.3.100到192.168.3.200你可以把虚拟机手动设为192.168.3.50避免冲突。第二个是部分企业 Wi-Fi 或交换机开启了 AP 隔离/端口隔离虚拟机即使拿到 IP其他设备也 ping 不通这是网络策略问题不是 VMware 能解决的。桥接模式还有一个很多人忽略的坑宿主机如果同时连接了多个网络比如 Wi-Fi 有线VMware 桥接时选择绑定的物理网卡容易选错导致虚拟机网络不通。在虚拟网络编辑器里选中桥接模式桥接到那一栏要选择宿主机实际使用的物理网卡。5.2 仅主机模式的本地局域网模拟仅主机模式经常被误解很多人以为它不能上网所以没用。其实它是搭建隔离测试环境的好工具。仅主机模式下宿主机和虚拟机通过 VMnet1 虚拟网卡连接组成一个封闭的虚拟局域网虚拟机无法访问外部网络但宿主机可以直接 SSH 进虚拟机。我实际用它做过一件事在宿主机上同时跑三台虚拟机分别模拟内网环境里的三台服务器三台虚拟机之间可以相互通信但外部完全访问不到这个网络测试就非常干净。在这种模式下你需要手动给虚拟机配置静态 IP网段用 VMnet1 的网段通常也是192.168.x.0/24然后宿主机直接 SSH 虚拟机的 IP 即可。注意仅主机模式下虚拟机如果要访问外网得额外设置 NAT 或代理否则apt install都没法用。三种模式放在一起比较我的选型建议是能 NAT 直连就 NAT 直连最省事需要局域网访问就用桥接需要隔离测试就用仅主机。不要三种模式来回切换切一次就等于把虚拟机的网络重新配置一次很容易引入新问题。6. Ubuntu SSH 服务端的三个隐藏门槛安装、放行、自启网络层解决之后真正挡住大多数人的其实是虚拟机里的 SSH 服务端没配对。Ubuntu 桌面版默认不带 openssh-server这是个很容易忽略的细节。你在宿主机上执行ssh user192.168.88.128如果提示Connection refused那大概率就是虚拟机里压根没装 SSH 服务。在 Ubuntu 虚拟机的终端里执行sudo apt update sudo apt install -y openssh-server装完以后检查服务状态sudo systemctl status ssh看到active (running)就说明服务已经起来了。但这里有个隐藏门槛这次能连不代表重启虚拟机之后还能连。需要把 SSH 服务设置成开机自启sudo systemctl enable ssh第二个隐藏门槛是防火墙。Ubuntu 22.04 及之后的版本默认没有启用 ufw所以很多教程不讲防火墙这步但如果你之前装过 ufw 或者启用过防火墙22 端口默认是不放行的。执行以下命令放行 SSHsudo ufw allow 22/tcp sudo ufw enable注意ufw enable以后如果只放行了 22那其他端口比如 80、443 都会被挡掉到时候 Web 服务访问不了别怪 VMware是防火墙规则写全了就行。用sudo ufw status查看当前规则。第三个隐藏门槛是 SSH 服务可能起来了但根本没监听在 22 端口。检查方式是sudo ss -tlnp | grep ssh正常能看到一行LISTEN 0 128 0.0.0.0:22和[::]:22。如果这里显示的是127.0.0.1:22而不是0.0.0.0:22说明 sshd 只监听了本机回环地址外部永远连不上。这种情况通常是因为/etc/ssh/sshd_config里配了ListenAddress 127.0.0.1把它注释掉然后sudo systemctl restart ssh重启服务。再检查一下登录用户的权限。如果你用的是 Ubuntu 默认安装时创建的那个用户直接用那个用户登录没问题。如果你希望允许 root 登录需要修改/etc/ssh/sshd_config里的PermitRootLogin为yes然后重启 ssh。但我的建议是生产环境别开 root 远程登录用普通用户加 sudo 就行安全很多。整个虚拟机侧配置做完以后我通常会用一条命令在宿主机上验证ssh -v user虚拟IP-v参数会打印详细的连接过程很容易定位卡在哪一步。如果看到Connection refused就是服务端没起或者端口不对看到Permission denied就是用户名或密码错误看到Connection timed out大概率是网络层还没通往下看排查章节。7. 从连不上到连通一次完整的 SSH 排错链路复盘前面讲了很多配置但实际动手的时候一定会遇到各种连不上的情况。这一章我用一套标准排错链路按顺序执行基本能把 90% 的问题定位出来。我以一个 Windows 宿主机 NAT 模式 Ubuntu 22.04 虚拟机为例假设虚拟机的 IP 是192.168.88.128。第一步宿主机 ping 虚拟机。在宿主机命令行执行ping 192.168.88.128能通说明网络层没问题继续第二步。不通先执行ipconfig看宿主机 VMnet8 的 IP 是不是192.168.88.1如果 VMnet8 没显示或者网段不对去虚拟网络编辑器里把 VMnet8 恢复默认如果 VMnet8 正常但 ping 不通检查 Windows 防火墙是否拦截了 ICMP 回显临时关掉防火墙再 ping 一下试试。第二步宿主机检测虚拟机的 22 端口。在宿主机执行telnet 192.168.88.128 22如果提示Connection refused或Unable to connect说明 SSH 服务没起来或者端口没监听。如果命令停在SSH-2.0-OpenSSH_...这种 banner 上说明端口通了直接Ctrl ]退出 telnet继续第三步。第三步检查虚拟机里的 SSH 服务状态。到虚拟机终端执行sudo systemctl status ssh sudo ss -tlnp | grep 22服务没起来就sudo systemctl start ssh服务起来了但没监听0.0.0.0:22按第 6 章的方法改sshd_config。第四步检查虚拟机防火墙。在虚拟机里执行sudo ufw status如果显示Status: active看看有没有22/tcp ALLOW的规则。没有就sudo ufw allow 22/tcp。第五步检查宿主机上的 VMware NAT 服务。这一步非常容易被忽略。Windows 宿主机上打开服务管理器services.msc找VMware NAT Service和VMware DHCP Service确保这两个服务状态是正在运行。有几次我 ping 不通虚拟机最后发现是 VMware NAT Service 挂了手动启动以后一切正常。第六步检查网段冲突。如果你发现宿主机 VMnet8 的 IP 和你物理局域网 IP 一样比如都是192.168.88.x网络就乱了。第 3 章说过把 NAT 网段换掉就行。这六步是按从底层到上层的顺序来的物理网络 - 协议栈 - 端口 - 服务 - 防火墙 - 系统服务。每次遇到连不上的情况我很少直接去怀疑 SSH 配置而是按这个顺序走一遍基本五分钟内能定位。如果你跳步去看 SSH 配置反而容易陷入死循环。8. 进阶操作VSCode Remote-SSH 与多虚拟机端口规划SSH 通了以后大多数人下一个需求就是用 VSCode 远程开发毕竟在虚拟机里装个完整桌面环境再跑 VSCode 太重了直接在宿主机上用 Remote-SSH 连过去才是正确姿势。VSCode 里安装Remote-SSH扩展发布者是 Microsoft按F1输入Remote-SSH: Connect to Host再输入user192.168.88.128回车后它会打开一个新的 VSCode 窗口远程连接成功后左下角会显示SSH: 192.168.88.128。此时你在左侧打开文件夹其实就是虚拟机里的目录终端也是虚拟机里的终端可以直接执行 Linux 命令。这个方案我每天都在用宿主机保持 Windows 的流畅操作代码跑在 Linux 环境里两边都不耽误。VSCode 远程连接首次会要求输密码如果觉得每次输密码烦就配置 SSH 密钥免密登录。Windows 10 以上自带ssh-keygen先执行ssh-keygen -t rsa -b 4096一路回车生成密钥然后把公钥复制到虚拟机。Windows 下没有ssh-copy-id手动执行type $env:USERPROFILE\.ssh\id_rsa.pub | ssh user192.168.88.128 mkdir -p ~/.ssh cat ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys之后连接虚拟机就不用输密码了。对于经常连接的虚拟机我建议在宿主机C:\Users\你的用户名\.ssh\config里写一个配置块比如Host ubuntu-vm HostName 192.168.88.128 User ubuntu Port 22保存后在 VSCode 的 Remote-SSH 列表里就能直接选ubuntu-vm连接不用每次输 IP 和用户名。这个 config 文件还能配置ServerAliveInterval 60来保持长连接防止 SSH 一段时间不操作就断开。VSCode 远程开发时有个常见提示此扩展在此工作区中被禁用因为其被定义为在远程扩展主机中运行。这个其实是 VSCode 的扩展机制问题有些扩展设计为只能在本地窗口运行你远程打开后它不会加载不是 SSH 连接的问题。遇到这种提示直接忽略就行真正影响远程开发的是那些需要安装在远程端的扩展VSCode 会自动提示你Install in SSH: ...点一下就会装到虚拟机里。最后说下多虚拟机端口规划。一台宿主机上跑多台虚拟机时端口转发规则如果随便加很容易乱。我自己的习惯是建一个表把每台虚拟机 IP、映射端口、映射用途记清楚比如虚拟机名称虚拟机 IP宿主机映射端口用途ubuntu-dev192.168.88.1282201SSHubuntu-web192.168.88.1292202SSH 8080 - 80ubuntu-db192.168.88.1302203SSH 3306 - 3306规划的原则是一台虚拟机至少一个不冲突的宿主机端口用于 SSHWeb、数据库等应用端口再单独映射。这样既方便排查也方便后续写脚本统一管理。我在实际使用中最大的体会是SSH 访问 VMware 虚拟机这件事80% 的问题出在网络模式理解不清晰和虚拟机侧 SSH 服务没配好这两件事上。先把第 3 章的 NAT 直连方案跑通再根据需求决定要不要做端口转发或改桥接整个过程会顺畅很多。希望这次写下来的内容能帮你少走我当时走过的那些弯路。
返回列表