如何通过编程过滤掉虚拟机的IP地址?
过滤虚拟机网卡以获取物理以太网IP地址的解决方案
问题背景
现有一段用于获取以太网IP地址的代码,但系统安装虚拟机时可能返回虚拟机的IP地址:
public static IPAddress GetEthernetIpAddress() { foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { if (ni.OperationalStatus == OperationalStatus.Up) { if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet) { foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == AddressFamily.InterNetwork) { return ip.Address; } } } } } return default; }
尝试过两种不可靠的过滤方案:
- 检查网卡是否存在网关:网上称虚拟机网卡无网关,但实际验证不准确,代码如下:
if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() == null) - 检查网卡名称包含“vEthernet”:依赖名称关键词的方式稳定性差,无法覆盖所有虚拟机场景。
在NetworkInterface或UnicastIPAddressInformation官方文档中未找到有效过滤方法,以下是可行的解决思路:
可行过滤方案
1. 通过硬件ID(PnP设备ID)识别虚拟网卡
虚拟机网卡的硬件描述或PnP设备ID通常包含厂商标识(如VMware、VirtualBox、Hyper-V),可通过WMI查询网卡的硬件信息进行过滤:
using System.Management; public static bool IsPhysicalNetworkInterface(NetworkInterface ni) { var physicalAddress = ni.GetPhysicalAddress().ToString(); if (string.IsNullOrEmpty(physicalAddress)) return false; var query = new ObjectQuery($"SELECT * FROM Win32_NetworkAdapter WHERE MACAddress = '{physicalAddress.Replace("-", ":")}'"); using (var searcher = new ManagementObjectSearcher(query)) { foreach (ManagementObject obj in searcher.Get()) { // 检查设备描述是否包含虚拟机厂商关键词 string description = obj["Description"]?.ToString() ?? ""; if (description.Contains("VMware") || description.Contains("VirtualBox") || description.Contains("Hyper-V")) { return false; } // 检查PNPDeviceID是否包含虚拟设备标识 string pnpId = obj["PNPDeviceID"]?.ToString() ?? ""; if (pnpId.Contains("VMware") || pnpId.Contains("VMS_VSP") || pnpId.Contains("VirtualBox")) { return false; } } } return true; }
在原代码中加入该过滤条件:
public static IPAddress GetEthernetIpAddress() { foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { if (ni.OperationalStatus == OperationalStatus.Up && ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet && IsPhysicalNetworkInterface(ni)) { foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == AddressFamily.InterNetwork) { return ip.Address; } } } } return default; }
2. 结合网卡连接状态过滤
物理以太网网卡通常处于MediaConnectionState.Connected状态,虚拟机网卡(如Host-Only模式)可能处于断开或虚拟连接状态:
using System.Net.NetworkInformation; public static bool IsConnectedPhysicalEthernet(NetworkInterface ni) { if (ni.NetworkInterfaceType != NetworkInterfaceType.Ethernet) return false; var ifEntry = ni.GetIfEntry(); return ifEntry.MediaConnectionState == MediaConnectionState.Connected; }
3. 通过默认路由验证物理网卡
物理网卡通常关联默认路由,虚拟机网卡(如内部网络模式)可能没有默认路由:
using System.Net.NetworkInformation; public static bool IsDefaultRouteInterface(NetworkInterface ni) { var ipProps = ni.GetIPProperties(); foreach (var route in ipProps.GetIPv4Properties().GetIPv4Routes()) { // 默认路由的目标网络为0.0.0.0 if (route.DestinationPrefix.Equals(IPAddress.Parse("0.0.0.0")) && route.NextHop.Equals(IPAddress.Parse("0.0.0.0"))) { return true; } } return false; }
总结
最可靠的方案是结合硬件ID(PnP设备ID)的检查,虚拟机网卡的硬件标识具有唯一性,不易被伪造或变更;可再结合连接状态和路由信息进行二次验证,确保获取的是物理以太网的IP地址。
内容的提问来源于stack exchange,提问作者Mickael Bergeron Néron
相关产品推荐
相关产品推荐

