ESXi主机抓包这件事,很多运维兄弟一听就头大。倒不是技术上有多难,而是ESXi这层Hypervisor夹在物理网卡和虚拟机之间,网络流量路径比普通Linux主机复杂得多,一旦真要排查虚拟化环境里的网络问题,手边没有一套能用的抓包方案,就会非常被动。我经常遇到的情况是:虚拟机里面抓包看不到关键的报文,或者明明网卡上有流量但tcpdump就是没输出,最后折腾半天才发现是抓包的位置不对,或者工具用得不对。
这篇东西我会把ESXi主机上抓包的完整套路讲清楚,从底层流量的走向、选哪个网卡来抓、用pktcap-uw和tcpdump-uw这两个内置工具的具体命令,到哪些场景应该在哪一层抓包,再到常见的坑和排查思路,一次性梳理完。不管你是刚接触ESXi的新手,还是被东西向流量折腾过的老运维,这篇文章应该都能给你省下不少试错时间。
1. 抓包前你必须先弄懂ESXi的网络路径
1.1 ESXi抓包为什么不能照搬Linux那套
很多人在ESXi上抓包之前,脑子里默认是Linux的思维——直接用tcpdump -i eth0抓就完了。但ESXi并不是一个常规Linux系统,它虽然有tcpdump-uw这个命令,但整个网络栈跟标准Linux差别很大。
ESXi的网络结构大概是这样的:最底下是物理网卡,也就是vmnic0、vmnic1这些;物理网卡上面是vmkernel网络协议栈,管理网络、vMotion、存储流量都会走这个栈;再往上是标准交换机或者分布式交换机;交换机的端口组再连接虚拟机。所以同一份流量,在不同层级看到的报文内容是不一样的。
最常见的误区是在虚拟机里抓一次,又跑到ESXi主机上去抓一次,两次结果对不上,就开始怀疑是抓包姿势不对。其实是因为虚拟机网卡、虚拟交换机、vmkernel上行链路、物理网卡这几个位置,每一层都可能有自己的offload、vLAN裁剪或者过滤逻辑,同一包流量在不同位置看到的是不同“视角”。
所以正式抓包以前,一定要先问自己三个问题:我要排查的流量是发生在虚拟机和虚拟机之间,还是虚拟机和外部网络之间?流量会经过哪块物理网卡?我需要看到带vLAN标签的原始报文,还是只需要IP层及以上的内容?这三个问题确定了,抓包位置和工具基本就定了。
1.2 VMware内置抓包工具的定位
ESXi内置的抓包工具主要有两个:一个是pktcap-uw,这个工具是VMware官方推荐的,专门针对ESXi网络栈做包捕获的,功能非常强,可以挂在虚拟交换机、端口组、上行链路、vmkernel网卡等多个位置;另一个是tcpdump-uw,这个更接近传统Linux的tcpdump,语法基本一样,适合在vmkernel网卡上快速抓包。
很多人会问,那pktcap-uw和tcpdump-uw到底选哪个?我的习惯是这样的:如果在vmkernel网卡上抓管理流量,两个都行,tcpdump-uw用起来更顺手;但如果要抓虚拟机之间东西向流量,或者要看带vLAN标签的报文,就必须用pktcap-uw,它可以指定uplink、dvport、portgroup等参数,tcpdump-uw做不到这些。
还有一点要注意,两个工具都在 /usr/lib/vmware/vsan/bin/ 或者 /usr/lib/vmware/ 下面,但不同ESXi版本路径不完全一样。最好先执行which tcpdump-uw 和 which pktcap-uw 确认一下,省得找不到命令浪费时间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 抓包前的环境和工具准备
2.1 开启SSH并确认网卡编号
ESXi默认是关闭SSH的,所以第一步就是先把SSH打开。操作路径很简单:在vSphere Client里选中主机,进入“服务”标签页,找到TSM-SSH,点启动。或者直接在ESXi控制台按F2进入系统定制,选择Troubleshooting Options,把SSH启用。
这里有个小细节,如果你是通过远程操作ESXi而不是在物理控制台前,那一定要先确保管理网络通了再折腾SSH,不然把网络配置改坏了又是自找麻烦。
登录SSH以后,第一步不是急着抓包,而是先看网卡编号。用esxcli network nic list命令查看物理网卡列表,输出大概长这样:
bash复制Name PCI Device Driver Link Speed Duplex MAC Address MTU Description
------ ------------ ---------- ---- --------- ------ ----------------- ------- -----------------------
vmnic0 0000:02:00.0 ntg3 Up 10000Mbps Full xx:xx:xx:xx:xx:xx 1500 Intel(R) 10G...
vmnic1 0000:02:00.1 ntg3 Up 10000Mbps Full xx:xx:xx:xx:xx:xx 1500 Intel(R) 10G...
然后还要看vSwitch和端口组的关系,用esxcli network vswitch standard list。这个命令会列出所有标准交换机的上行链路、端口组、以及每个端口组对应的虚拟网卡ID。搞清楚vmnic编号以后,抓包的时候才不会选错网卡。
2.2 tcpdump-uw的快速上手
tcpdump-uw的用法跟Linux的tcpdump高度一致,常见的组合就是加 -i 指定网卡、-w 指定输出文件、-c 指定抓包数量。比如我想抓vmk0上的管理网络流量,可以这么写:
bash复制tcpdump-uw -i vmk0 -w /tmp/mgmt.pcap
这里一个小提示:ESXi的tcpdump-uw用的是pcap格式,但和Wireshark的兼容性完全没问题,抓到以后用scp下载到本地,拿Wireshark打开直接就能分析。抓包过程中如果不想抓太多,可以用-c参数限制数量,比如-c 100就是抓到100个包自动停。
另外,tcpdump-uw同样支持各种filter表达式,比如只抓特定IP、特定端口:
bash复制tcpdump-uw -i vmk0 -w /tmp/vmk0_http.pcap -c 500 'tcp port 80'
不过要注意,tcpdump-uw能抓的主要是vmkernel接口和主机自身的流量,如果你想抓虚拟机vNIC的流量,光靠tcpdump-uw是做不到的,得靠后面的pktcap-uw。
3. 四个高频场景的抓包实战
3.1 场景一:抓虚拟机之间的东西向流量
这是ESXi环境里最麻烦的一类排查。两个虚拟机在同一个ESXi主机上,互相通信的流量根本不会走到物理网卡上,所以你趴在物理交换机上做端口镜像完全没用,在ESXi的uplink上抓也看不到,必须在虚拟交换机层面抓。
pktcap-uw抓东西向流量的命令大概是这样的:
bash复制pktcap-uw --uplink vmnic0 --port 33554432 -w /tmp/vm_to_vm.pcap
但更实际的做法是先找到端口ID。两个虚拟机在同一个vSwitch上通信时,流量会进入这个vSwitch的某个端口,你需要找到对应虚拟机的端口。可以用esxcli network vswitch standard list拿到端口ID,然后用pktcap-uw指定这个端口去抓。
还有一种更简单的方法,如果你知道虚拟机对应的端口组名称,可以这样:
bash复制pktcap-uw --portgroup "VM Network" -w /tmp/portgroup.pcap
pktcap-uw直接挂在端口组上抓包,所有进入这个端口组的流量都会被捕获。这个方法尤其适合排查同一个端口组下面两个虚拟机之间的通信问题。说实话,这个参数比找端口ID省事太多。
3.2 场景二:抓物理网卡上的南北向流量
南北向流量就是虚拟机访问外部网络时的流量,这种情况抓包位置相对好定位,直接在物理网卡uplink上抓就行。比如虚拟机从vmnic0出去访问外部,就抓vmnic0:
bash复制pktcap-uw --uplink vmnic0 -w /tmp/north_south.pcap
注意,pktcap-uw在uplink上抓包时,抓到的报文是带vLAN tag的原始二层报文,会包含以太网头部和vLAN tag。如果你是拿Wireshark分析,Wireshark会自动识别vLAN;但如果你用其他命令行工具处理,可能需要自己留意vLAN ID信息。
这里有个很容易踩的坑:如果物理交换机端口配置了vLAN trunk,那你在uplink上抓包的报文会包含多个vLAN的流量。这时候你最好在pktcap-uw里面加上过滤条件,比如只抓vLAN 100的流量:
bash复制pktcap-uw --uplink vmnic0 --vlan 100 -w /tmp/vlan100.pcap
这样抓出来的包更干净,分析的时候不会眼花缭乱。
3.3 场景三:抓DHCP请求和802.1x认证这类关键报文
很多网络问题其实不是流量不通,而是某个协议报文丢了,比如虚拟机拿不到IP、802.1x认证失败。这种问题抓包的时候要看两个方向:客户端侧和服务器侧,同时抓,对比报文才能定位是哪个环节丢了。
在ESXi环境里,如果虚拟机通过DHCP拿不到地址,我一般会在虚拟机内部先抓一次(比如在客户机里用Wireshark或在Linux里用tcpdump),然后在ESXi的虚拟交换机端口组上也抓一次。如果客户端发DHCP Discover的报文已经被ESXi透传了,但虚拟机没有收到DHCP Offer,那问题很可能在外部的DHCP服务器或者中间网络设备上。
命令上可以这样,先启动uplink抓包:
bash复制pktcap-uw --uplink vmnic0 -w /tmp/dhcp.pcap 'udp port 67 or udp port 68'
然后去虚拟机内部同时抓一份:tcpdump -i eth0 -w /tmp/dhcp_client.pcap 'udp port 67 or udp port 68',两边一对比,谁丢了包一目了然。802.1x认证抓包其实也是一个逻辑,重点是先在客户端网卡和交换机侧同时抓EAPOL报文,然后观察报文在哪个阶段断了。
3.4 场景四:长时间抓包与文件导出
排查某些间歇性网络故障时,往往需要长时间抓包。ESXi主机本来资源就紧张,长时间抓包如果文件太大很容易把/tmp目录写满。我的习惯是先估算一下抓包速率,比如1秒钟大概几百KB,那抓10分钟就是几百MB,抓之前先df -h看一眼/tmp的剩余空间。
抓包命令建议加上文件轮转参数。pktcap-uw虽然没有像tcpdump -W那样直接的文件轮转参数,但可以用gzip压缩来减体积:
bash复制pktcap-uw --uplink vmnic0 -w /tmp/long.pcap -c 100000
或者抓完再用gzip压缩:gzip /tmp/long.pcap。实际抓包时用-c限制一下包数量,防止失控。
抓完以后用scp把文件从ESXi上下载下来:在你的本地机器上执行:
bash复制scp root@esxi-host-ip:/tmp/long.pcap ./long.pcap
提醒一句,默认root的scp需要开SSH,而且ESXi的scp速度一般,大文件建议先压缩再下载,能省一半时间起步。
4. 常见问题排查与避坑记录
4.1 抓不到包的几个典型原因
我自己实战中遇到最多的“抓不到包”,基本都逃不开下面几个原因。
第一,抓包位置不对。这个前面反复强调过,东西向流量你跑到uplink上抓,永远都是空包。东西向必须先定位虚拟交换机的端口,或者用端口组直接挂上去抓。
第二,虚拟机网卡类型的问题。如果虚拟机的网卡是VMXNET3,默认会开启硬件卸载功能,比如TCP分段卸载和校验和卸载。这些特性在虚拟化层做的时候会改变报文的内容,有些字段会跟原来不一样。这时候可以用esxcli network vswitch standard set修改vSwitch的参数,或者直接用pktcap-uw的--fulltrace参数,它会把进入虚拟端口前的原始包也抓下来。
第三,过滤表达式写错了。比如你明明想抓TCP 80端口,但写成tcp port 80却漏了icmp,然后发现80端口怎么没流量,其实只是filter写窄了。排查的时候,先不带任何过滤条件抓几秒看看到底有没有流量,再一步步把范围缩小。
4.2 抓包文件打不开或者时间对不上
有次我抓完包拿Wireshark打开,发现里面全是空闲包,或者时间戳混乱,一开始以为是ESXi的问题,后来才意识到是ESXi主机本身的时钟不准。ESXi如果没配NTP,默认时间跟实际时间差距可能很大,抓包分析的时候时间戳对不上会非常误导。
处理办法是:抓包之前先确认ESXi时间,执行date看一下,如果偏差大就先配好NTP再抓。NTP配置可以在vSphere Client的主机设置里指定,也可以用命令:
bash复制esxcli system ntp set --server=ntp.example.com
esxcli system ntp start
另外,抓包文件用Wireshark打开如果报“文件格式无法识别”,多半是抓包过程被中断导致文件头损坏。这种只能重抓,没有特别好的修复办法。也提醒各位,尽量不要用Ctrl+C停在半中间就立刻拔线,要等命令正常结束。
4.3 抓包命令本身占用资源过高的问题
ESXi主机的CPU和内存通常都是优先保障虚拟机的,抓包这种操作本质上是把网络栈里的报文复制一份出来,如果流量特别大,抓包进程会吃掉不少CPU。我在高流量生产环境上曾经碰到过抓包10分钟,宿主机CPU负载飙升的情况。
几个缓解手段:一是尽量在业务低峰期抓;二是抓包时加上过滤条件,用pktcap-uw的--csum 0参数关闭校验和计算,减轻CPU压力;三是限制包大小,比如-s 96只抓前96字节,足够看IP头部和TCP头部就够了,没必要每次抓完整报文。
顺带说一句,如果只是排查连通性问题,不需要分析应用层数据,-s 96这种截断抓法完全够用。如果是要分析HTTP、SQL这类上层协议内容,那还是老老实实抓全包。
跟ESXi抓包配套的还有一个容易忽略的点:虚拟机内部自己抓包时,要注意客户机操作系统的时间同步,虚拟机跑时间同步服务经常滞后,两边抓包都开着,时间对不上,对比就白做了。
5. 抓包完成后的排查分析小技巧
5.1 用Wireshark快速定位关键报文的思路
包抓到以后,先别急着在Wireshark里乱点。先把时间戳列调出来,确认两个抓包文件的时间基准是基本对齐的,然后再分析。
我自己排障的习惯是先看Statistics->Flow Graph,这个视图能很直观看到TCP的握手、重传、零窗口等状态,排查TCP层面的问题非常高效。另外一个就是Statistics->Conversations,按流量大小排序,能帮你快速定位是哪台设备和哪个端口占了最多流量。
如果是排查连接失败问题,重点看TCP三次握手有没有完成,SYN有没有回应。如果是应用层问题,用Follow TCP Stream看完整对话内容,很多时候业务数据里已经有提示了。
5.2 对比两侧抓包文件定位丢包点
两边抓包(比如ESXi的uplink和虚拟机内部)对比时,有个很实用的判断逻辑:如果ESXi uplink已经抓到客户端发出的包,但虚拟机内部却没有收到,那问题在虚拟化网络层或虚拟机网卡驱动;如果虚拟机和uplink都抓到了请求包,但外部设备没回应,那问题在外部网络。
这种两侧对比的方法应用范围很广,尤其是跨主机访问缓慢、丢包严重这类问题,单侧抓包永远查不清楚。我遇到很多回,都是用户说某一个IP访问超时,结果先在宿主机上抓,发现流量根本没到这台宿主机,再从上连交换机抓,才发现是路由或者防火墙的问题。抓包看起来是输入,实际上更像是在不断收敛问题的边界,每一次抓取都是在排除一个怀疑对象。
6. 再分享几个ESXi抓包的实用小经验
最后说几个用久了才会发现的细节。
一个是ESXi的/tmp目录空间有限,抓包文件别存在/tmp下面超过一天的量,抓完就赶紧下载走。如果确实需要抓很久,建议加crontab定期压缩清理,或者先计算好空间,别等到磁盘满了才发现,ESXi磁盘满会影响整个宿主机健康状态。
另一个是ESXi开启SSH是为了排查用的,排查完了记得关掉,生产环境原则上不要长期开着SSH。很多安全要求里都有一条就是“ESXi必须关闭SSH服务”,顺手做到位,省得后面被审计问起。
还有一个是关于虚拟机端口ID的,esxcli network vswitch standard list输出的Port ID可能会因为虚拟机的迁移或者网络的改动发生变化,所以快速定位的时候建议用端口组名称,而不是死记端口ID。尤其是分布式交换机环境,端口ID变化更频繁,用端口组更稳妥。
另外,pktcap-uw有一个很有用的选项是--stage,它可以指定在哪个网络处理阶段抓包。有次排查虚拟机收包半开连接的问题,我就用 --stage 0 在物理网卡驱动入口处抓了一份原始包,再用默认设置在虚拟交换机出口抓了一份,对比后发现是网卡驱动的接收队列丢包,这台虚拟化主机的网卡驱动版本最后背了锅。如果你对ESXi网络栈的各个处理阶段不熟,可以先跑一下pktcap-uw --help,详细看看stage的说明,再对症下药。
