VMware 虚拟机能 Ping 内网但 TCP/HTTPS 不通:一次 VMware NAT Service 异常的完整排查与解决过程
最近遇到一个比较典型、但排查起来很容易绕进“路由配置”里的 VMware Workstation 网络问题。
故障表现非常特殊:
- Windows 宿主机访问目标内网服务器正常
- VMware 虚拟机可以 Ping 通目标服务器
- 虚拟机 Tracert 基本正常
- 虚拟机访问目标 TCP 端口却一直超时
- HTTPS 页面无法打开
- 同一个目标端口,宿主机直接访问完全正常
经过路由、MTU、TCP、VMware NAT、PktMon 抓包等一系列排查,最终定位到:
VMware NAT Service(vmnat.exe)运行异常,导致 VMnet8 中虚拟机的 TCP NAT 转发失效。重启 VMware NAT Service 后立即恢复。
下面记录完整的排查和解决过程。
一、网络环境说明
为了避免暴露真实网络信息,本文中的 IP 地址、MAC 地址、主机名、用户名等均已脱敏替换。
大致网络结构如下:
Windows 宿主机
│
├── 互联网网卡
│ └── 192.0.2.10
│ └── 默认网关 192.0.2.1
│
├── 内网网卡
│ └── 198.51.100.10
│ └── 内网网关 198.51.100.254
│
└── VMware VMnet8
└── 172.16.50.1
│
└── VMware NAT 网关 172.16.50.2
│
├── 虚拟机 A:172.16.50.101
└── 虚拟机 B:172.16.50.102
目标服务器使用示例地址:
203.0.113.187
目标 HTTPS 服务端口:
8443
虚拟机访问目标网段时,使用 VMware NAT 网卡:
203.0.113.0/24
↓
172.16.50.2
↓
VMware NAT
↓
宿主机内网出口
↓
198.51.100.254
二、最初的故障现象
首先在虚拟机中 Ping 目标:
ping 203.0.113.187
结果正常:
Reply from 203.0.113.187
Reply from 203.0.113.187
Reply from 203.0.113.187
Reply from 203.0.113.187
Lost = 0
也就是说:
ICMP:正常
接着测试 TCP 8443:
Test-NetConnection 203.0.113.187 -Port 8443
结果却是:
ComputerName : 203.0.113.187
RemoteAddress : 203.0.113.187
RemotePort : 8443
InterfaceAlias : Ethernet0
SourceAddress : 172.16.50.101
TcpTestSucceeded : False
也就是非常典型的:
Ping:正常
TCP:失败
浏览器打开:
https://203.0.113.187:8443/
同样一直等待,最后超时。
三、先检查虚拟机的路由
这种双网卡环境第一反应通常是路由问题,因此首先检查:
route print -4
目标网段已经存在静态路由,例如:
203.0.113.0 255.255.255.0 172.16.50.2
但单纯看 route print 还不够,继续使用 PowerShell 查看 Windows 实际会选择哪条路由:
Find-NetRoute -RemoteIPAddress 203.0.113.187
结果类似:
IPAddress : 172.16.50.101
InterfaceAlias : Ethernet0
DestinationPrefix : 203.0.113.0/24
NextHop : 172.16.50.2
也就是说,访问目标时:
源地址:172.16.50.101
下一跳:172.16.50.2
这与预期完全一致。
因此虚拟机的目标网段静态路由并没有选错。
四、为什么不能一直纠结默认路由 Metric
双网卡 Windows 环境经常会看到多个默认网关,例如:
0.0.0.0/0 → 192.0.2.1
0.0.0.0/0 → 172.16.50.2
于是很容易怀疑是不是 Metric 抢路。
实际上 Windows 路由选择首先遵循:
Longest Prefix Match,也就是最长前缀匹配。
例如:
203.0.113.0/24
一定比:
0.0.0.0/0
更加精确。
所以访问:
203.0.113.187
时,只要存在:
203.0.113.0/24 → 172.16.50.2
就会优先匹配这条 /24 路由。
因此本次问题并不是简单调整默认路由 Metric 就能解决的。
五、排查 MTU
TCP 超时有时与 MTU、PMTUD 或分片异常有关,因此继续检查:
netsh interface ipv4 show subinterfaces
VMware 网卡 MTU 为:
1500
然后测试最大的不分片 ICMP:
ping 203.0.113.187 -f -l 1472
为什么是 1472?
1472 字节数据
+ 20 字节 IPv4 Header
+ 8 字节 ICMP Header
= 1500 字节
测试结果全部成功,没有出现:
Packet needs to be fragmented
因此:
MTU 问题基本可以排除。
六、宿主机直接访问目标完全正常
接着在 Windows 宿主机测试同一个目标:
Test-NetConnection 203.0.113.187 -Port 8443
结果:
InterfaceAlias : 内网网卡
SourceAddress : 198.51.100.10
TcpTestSucceeded : True
继续使用 curl:
curl.exe -vk --noproxy "*" --connect-timeout 8 https://203.0.113.187:8443/
成功建立连接:
Connected to 203.0.113.187
HTTP/1.1 200 OK
这一步非常关键,它证明:
- 目标服务器正常
- 目标 8443 端口正常监听
- 宿主机到目标的内网路由正常
- HTTPS 服务正常
问题范围因此缩小到了:
虚拟机
↓
VMware VMnet8
↓
VMware NAT
↓
宿主机
七、检查 VMware NAT 配置
VMware Workstation 的 NAT 配置文件通常位于:
C:\ProgramData\VMware\vmnetnat.conf
读取配置:
Get-Content "C:\ProgramData\VMware\vmnetnat.conf"
关键内容类似:
[host]
ip = 172.16.50.2/24
hostIp = 172.16.50.1
device = VMnet8
也就是说:
VMnet8 网络:172.16.50.0/24
宿主机 VMnet8:
172.16.50.1
VMware NAT 网关:
172.16.50.2
配置本身没有发现明显错误。
八、检查 VMware NAT Service
首先确认 VMware 服务状态:
Get-Service |
Where-Object {
$_.Name -like "*VMware*" -or
$_.DisplayName -like "*VMware*"
} |
Format-Table Status,Name,DisplayName -Auto
可以看到:
VMware NAT Service Running
VMware DHCP Service Running
也就是说 VMware NAT Service 并没有停止。
继续看 vmnat.exe:
Get-Process vmnat |
Format-List Id,StartTime,CPU,Handles
这里开始发现异常。
九、vmnat.exe 的 CPU 与 Handles 明显异常
故障状态下发现 vmnat.exe:
Handles:超过 4000
累计 CPU 时间也异常高。
为了排除“只是因为运行时间长导致累计 CPU 较高”的情况,进行了 10 秒实时采样:
$p1 = Get-Process vmnat
$c1 = $p1.CPU
Start-Sleep 10
$p2 = Get-Process vmnat
[PSCustomObject]@{
PID = $p2.Id
CPU_Delta_10s = [math]::Round(($p2.CPU-$c1),2)
Handles = $p2.Handles
} | Format-List
故障时,10 秒内 vmnat.exe 的 CPU 时间增长异常明显。
于是继续查看线程。
十、发现 vmnat.exe 单线程持续占满 CPU
执行:
(Get-Process vmnat).Threads |
Sort-Object TotalProcessorTime -Descending |
Select-Object Id,ThreadState,
@{N="CPU_s";E={[math]::Round($_.TotalProcessorTime.TotalSeconds,2)}},
@{N="User_s";E={[math]::Round($_.UserProcessorTime.TotalSeconds,2)}},
@{N="Kernel_s";E={[math]::Round($_.PrivilegedProcessorTime.TotalSeconds,2)}} |
Format-Table -Auto
等待 5 秒:
Start-Sleep 5
然后再次查看线程 CPU。
最终发现其中一个线程一直处于:
ThreadState : Running
并且:
5 秒时间内
CPU 时间也增加约 5 秒
这意味着该线程基本相当于:
持续 100% 占用一个逻辑核心
而其他 vmnat.exe 线程基本都处于:
Wait
此时已经高度怀疑 VMware NAT 内部状态出现异常。
十一、最关键的证据:在虚拟机抓 TCP SYN
即使 vmnat.exe CPU 异常,也不能仅凭这一点就直接断言 NAT 有问题。
还需要确认:
虚拟机到底有没有真正把 TCP SYN 发出去?
Windows 自带的 PktMon 非常适合做这个测试。
在虚拟机管理员 PowerShell 执行:
pktmon stop
pktmon filter remove
pktmon filter add -p 8443
pktmon start --etw -c --pkt-size 0
然后另外打开一个 PowerShell:
Test-NetConnection 203.0.113.187 -Port 8443
等待数秒后停止抓包:
pktmon stop
转换 ETL:
pktmon format PktMon.etl -o C:\vm-8443.txt
筛选目标:
Select-String -Path C:\vm-8443.txt -Pattern "203.0.113.187","8443"
成功抓到了类似:
172.16.50.101.随机端口 > 203.0.113.187.8443:
Flags [S]
其中:
Flags [S]
就是 TCP SYN。
这证明:
虚拟机 Windows TCP/IP 栈已经正确创建连接,并且 SYN 已经发送给 VMware NAT 网关。
因此可以进一步排除:
- 虚拟机应用没有发请求
- 虚拟机 TCP 栈问题
- 目标网段静态路由选错
- 浏览器自身问题
十二、同时在宿主机抓包
接下来在宿主机管理员 PowerShell 抓包:
pktmon stop
pktmon filter remove
pktmon start --etw -c --pkt-size 0
然后虚拟机再次执行:
Test-NetConnection 203.0.113.187 -Port 8443
等待约 10 秒,在宿主机停止:
pktmon stop
转换:
pktmon format PktMon.etl -o C:\host-all.txt
搜索:
Select-String -Path C:\host-all.txt -Pattern "203.0.113.187"
结果却:
没有匹配到对应的 TCP 数据包
尤其没有发现预期的:
198.51.100.10:随机端口
↓
203.0.113.187:8443
TCP SYN
这一步非常关键。
十三、完整证据链已经形成
此时整个链路变成:
虚拟机应用
↓
Windows TCP/IP
↓
172.16.50.101
↓
TCP SYN
↓
172.16.50.2
VMware NAT
↓
×
↓
宿主机实体网卡
↓
目标服务器
已经明确确认:
虚拟机 SYN:存在
宿主机 NAT 后 SYN:没有出现
因此故障点高度集中到了:
vmnat.exe
负责的 NAT 转换及 TCP 会话处理层。
十四、为什么 Ping 通不能证明 NAT 正常
这是本次故障最容易误导人的地方。
很多人看到:
ping 目标IP
成功以后,会认为:
网络已经完全正常。
实际上只能证明:
ICMP 可达
并不能证明:
TCP NAT 正常
NAT 程序处理 TCP 时通常还需要维护:
- TCP 五元组
- 源端口转换
- 连接状态
- TIME_WAIT
- 返回映射
- 会话老化
- 状态表清理
因此即使 ICMP 仍然可以正常转发,TCP NAT 会话处理依然可能出现异常。
所以:
Ping 能通,只能证明 ICMP 可达,不能证明 TCP/HTTPS 一定正常。
十五、最终解决方法
在证据基本确认之后,没有:
- 重启 Windows
- 重装 VMware
- 重置 VMnet8
- 删除虚拟机网卡
- 继续修改静态路由
只执行了一条命令:
Restart-Service -DisplayName "VMware NAT Service"
然后确认服务:
Get-Service -DisplayName "VMware NAT Service"
状态:
Running
继续检查新的 vmnat.exe:
Get-Process vmnat |
Format-List Id,StartTime,CPU,Handles
可以明显看到:
PID 已变化
StartTime 已更新
CPU 接近 0
Handles 从 4000+ 降到约一百多
十六、重启 NAT 服务后的 CPU 状态
再次进行 10 秒采样:
$p1 = Get-Process vmnat
$c1 = $p1.CPU
Start-Sleep 10
$p2 = Get-Process vmnat
[PSCustomObject]@{
PID = $p2.Id
CPU_Delta_10s = [math]::Round(($p2.CPU-$c1),2)
Handles = $p2.Handles
} | Format-List
恢复后类似:
CPU_Delta_10s : 0.03
Handles : 160 左右
和故障状态形成非常明显的对比:
故障状态:
单线程长期接近 100%
Handles 超过 4000
恢复状态:
10 秒 CPU 仅增加约 0.03 秒
Handles 约一百多
十七、两台虚拟机同时恢复
虚拟机 A 再次执行:
Test-NetConnection 203.0.113.187 -Port 8443
结果:
SourceAddress : 172.16.50.101
TcpTestSucceeded : True
虚拟机 B:
Test-NetConnection 203.0.113.187 -Port 8443
结果:
SourceAddress : 172.16.50.102
TcpTestSucceeded : True
两台 VMnet8 虚拟机同时恢复。
这进一步证明:
问题不是某一台虚拟机自己的网络配置,而是宿主机 VMware NAT Service 的公共故障。
十八、最终故障结论
本次能够确认的故障点为:
VMware Workstation 的 VMware NAT Service(vmnat.exe)进入异常运行状态,造成 VMnet8 网络中虚拟机的 TCP NAT 转发异常。
故障时主要表现:
宿主机访问目标 TCP:正常
虚拟机 Ping:正常
虚拟机 Tracert:基本正常
虚拟机 TCP/HTTPS:超时
虚拟机 SYN:已经正常发送
宿主机 NAT 后 SYN:没有出现
vmnat.exe CPU:明显异常
vmnat.exe Handles:异常增多
重启 VMware NAT Service 后:
vmnat CPU 恢复
↓
Handles 恢复
↓
TCP NAT 恢复
↓
多台虚拟机同时恢复
十九、可能的诱因
宿主机实体网卡同时安装或绑定了多种网络相关组件,例如:
VMware Bridge Protocol
Npcap Packet Driver
VirtualBox NDIS6 Bridged Networking Driver
如果宿主机还安装了:
- VirtualBox
- Npcap / Wireshark
- OpenVPN
- 安全软件
- 其他虚拟交换机
- 抓包驱动
那么 Windows NDIS/WFP 网络栈会更加复杂。
不过需要特别说明:
本次只能确认 VMware NAT Service 是实际故障点,没有足够证据证明 Npcap、VirtualBox 或某个具体驱动就是导致 vmnat.exe 异常的根本原因。
因此不建议一遇到这种问题就直接卸载各种网络驱动。
二十、以后如何快速检查是不是同一个问题
如果以后再次出现:
虚拟机 Ping 正常
+
虚拟机 TCP/HTTPS 超时
+
宿主机访问同一目标正常
首先检查 vmnat.exe:
Get-Process vmnat |
Format-List Id,StartTime,CPU,Handles
再采样 10 秒:
$p1 = Get-Process vmnat
$c1 = $p1.CPU
Start-Sleep 10
$p2 = Get-Process vmnat
[PSCustomObject]@{
PID = $p2.Id
CPU_Delta_10s = [math]::Round(($p2.CPU-$c1),2)
Handles = $p2.Handles
} | Format-List
如果出现:
CPU 持续异常增加
Handles 达到异常高的数量
同时虚拟机 TCP 不通
但宿主机 TCP 正常
那么 VMware NAT Service 就应该成为重点排查对象。
二十一、一键检查 VMware NAT 状态脚本
可以保存下面的 PowerShell 脚本,用于快速检查:
$p1 = Get-Process vmnat -ErrorAction SilentlyContinue
if (!$p1) {
Write-Host "VMware NAT Service 未运行。" -ForegroundColor Red
exit
}
$c1 = $p1.CPU
Write-Host "正在检测 VMware NAT,请等待 10 秒..." -ForegroundColor Cyan
Start-Sleep 10
$p2 = Get-Process vmnat -ErrorAction SilentlyContinue
if (!$p2) {
Write-Host "检测过程中 vmnat.exe 已退出。" -ForegroundColor Red
exit
}
$delta = [math]::Round(($p2.CPU-$c1),2)
Write-Host ""
Write-Host "VMware NAT 状态" -ForegroundColor Cyan
Write-Host "---------------------------"
Write-Host "PID :" $p2.Id
Write-Host "启动时间 :" $p2.StartTime
Write-Host "10秒 CPU 增量 :" $delta
Write-Host "Handles :" $p2.Handles
Write-Host "Threads :" $p2.Threads.Count
if ($delta -gt 8 -or $p2.Handles -gt 2000) {
Write-Host ""
Write-Host "检测到 vmnat.exe 状态异常,建议进一步检查。" -ForegroundColor Red
}
else {
Write-Host ""
Write-Host "vmnat.exe 当前状态未发现明显异常。" -ForegroundColor Green
}
需要注意:
CPU 8 秒、Handles 2000 只是本次故障总结出来的经验告警值,并不是 VMware 官方阈值。
实际判断应该结合:
- CPU 增量
- Handles
- TCP 测试
- 宿主机与虚拟机对比
- 实际抓包结果
二十二、快速恢复命令
如果已经确认 VMware NAT Service 确实异常,可以使用管理员 PowerShell:
Restart-Service -DisplayName "VMware NAT Service"
然后检查:
Get-Service -DisplayName "VMware NAT Service"
应该显示:
Status : Running
最后在虚拟机重新测试:
Test-NetConnection 203.0.113.187 -Port 8443
正常应该变成:
TcpTestSucceeded : True
注意:重启 VMware NAT Service 会中断当前使用 VMnet8 NAT 的连接,因此有重要任务运行时应选择合适时间操作。
二十三、以后如何降低再次出现的概率
1. 保持 VMware Workstation 更新
建议在合适的维护窗口升级 VMware Workstation 到当前稳定版本。
升级时通常也会一起更新:
VMware NAT
VMware Bridge
VMware Virtual Ethernet Adapter
相关虚拟网络驱动
2. 减少不需要的网络过滤驱动
如果一台 Windows 同时安装:
VMware
VirtualBox
Npcap
VPN
抓包软件
安全软件
其他虚拟交换机
网络栈复杂度会明显提高。
如果某些组件已经长期不用,可以在维护窗口考虑清理。
但不要为了排查问题,一次性关闭所有网络驱动。
3. 不要因为 Ping 正常就停止排查
以后看到:
Ping:成功
TCP:失败
正确的理解应该是:
ICMP 可达
但是 TCP 连通性仍然存在问题
建议直接测试:
Test-NetConnection 目标IP -Port 目标端口
4. 不要一开始就疯狂修改 Windows 路由
正确排查顺序应该是:
route print -4
↓
Find-NetRoute
↓
确认 SourceAddress
↓
确认 NextHop
↓
再决定是否修改路由
如果:
SourceAddress 正确
NextHop 正确
DestinationPrefix 正确
就应该继续向 NAT、TCP、驱动和抓包层排查,而不是反复修改 Metric。
二十四、推荐的完整排查顺序
① Ping 目标
↓
② Test-NetConnection IP -Port PORT
↓
③ route print -4
↓
④ Find-NetRoute -RemoteIPAddress IP
↓
⑤ 宿主机测试相同目标 TCP
↓
⑥ 检查 MTU
↓
⑦ 检查 VMware NAT Service
↓
⑧ 检查 vmnat.exe CPU / Handles
↓
⑨ 虚拟机使用 PktMon 抓 TCP SYN
↓
⑩ 宿主机使用 PktMon 抓 NAT 后数据
↓
⑪ 确认数据包具体消失在哪一层
这种逐层定位方式,比下面这种“碰运气”式处理可靠很多:
不停改路由
重置网卡
删除虚拟网卡
重装 VMware
直接重启 Windows
二十五、本次问题的核心逻辑图
┌──────────────────────────────┐
│ VMware 虚拟机 │
│ 172.16.50.101 │
└──────────────┬───────────────┘
│
│ Ping ✓
│ TCP SYN ✓
▼
┌──────────────────────────────┐
│ VMware NAT │
│ 172.16.50.2 │
│ vmnat.exe │
│ │
│ CPU 异常 │
│ Handles 异常 │
└──────────────┬───────────────┘
│
│ TCP NAT ×
▼
┌──────────────────────────────┐
│ Windows 宿主机 │
│ 内网出口 │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ 目标服务器 │
│ 203.0.113.187:8443 │
│ │
│ 宿主机直连 ✓ │
└──────────────────────────────┘
执行:
Restart-Service -DisplayName "VMware NAT Service"
以后:
vmnat.exe CPU 恢复正常
↓
Handles 恢复
↓
TCP NAT 恢复
↓
虚拟机 A 恢复
↓
虚拟机 B 恢复
总结
这次 VMware 网络故障最值得记录的经验,并不是简单的:
网络不通就重启 VMware NAT Service。
而应该是:
当 VMware NAT 模式虚拟机可以 Ping 目标,但 TCP/HTTPS 不通,而宿主机访问同一目标完全正常时,应重点检查 VMware NAT 的 TCP 会话处理是否异常。
特别是同时存在下面几个条件:
虚拟机 Ping 正常
虚拟机 TCP 超时
宿主机 TCP 正常
虚拟机已经抓到 SYN
宿主机没有看到 NAT 后的 SYN
vmnat.exe CPU 长时间异常
vmnat.exe Handles 异常增长
那么问题就非常接近:
VMware NAT Service / vmnat.exe
本次最终通过:
Restart-Service -DisplayName "VMware NAT Service"
恢复。
重启服务后:
vmnat.exe CPU 恢复正常
Handles 从数千下降到一百多
多台 VMnet8 虚拟机的 TCP 8443 同时恢复
一句话快速判断
虚拟机 Ping 通
+
虚拟机 TCP 不通
+
宿主机 TCP 正常
+
vmnat.exe CPU / Handles 明显异常
=
优先检查 VMware NAT Service
说明:本文所有 IP 地址、主机名、MAC 地址、用户名、进程 PID 等均已进行脱敏或使用文档示例地址替换,与真实生产网络无关。