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 等均已进行脱敏或使用文档示例地址替换,与真实生产网络无关。

此博客中的热门博文

酷狗音乐MP3下载助手 - 下载状态修复版

下载谷歌浏览器

Office 微软官方部署流程