如何确定实际的物理网卡的MAC地址 - 通过VPN的(.NET C#)创建的不是虚拟的网络接口
-
21-09-2019 - |
题
背景
我试图让获得一个唯一的标识符了电脑,并希望能够可靠地返回每次都相同的MAC地址。相信我,我有我的理由使用MAC地址,看了很多帖子有关备用唯一ID的方法(是的,我考虑过,如果他们没有任何网络卡)。
问题
问题是在.NET中我看不到反正讲一个具体的NetworkInterface是来自像一个“北电IPSECSHM适配器 - 数据包计划程序微型端口”物理硬件网络卡,当您连接到某些VPN的或得到补充WiFi网络。
我知道如何通过使用类似的代码来此获得的MAC地址:
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
}
可以理解的是,没有100%的方式以确保我会得到一个内部网络卡,但<强>我想挑MAC地址返回其对于给定的机器,其是最有可能发生变化。独立的因素,如 - 无论是Wi-Fi连接...被通过某种类型的绳索连接的连接......或者他们安装了一些新的VPN软件增加了一个新的接口
策略考虑
1)选择所述第一接口是“向上”。这种失败对我的笔记本电脑,因为“包微型端口”始终是。此外,如果我系绳我的手机给我的笔记本电脑,这也显示为第一张卡片。
2)选择最合适的类型......这失败B / C基本都显示为“以太网”包括WiFi适配器和我的iPhone网络共享互联网连接。
3)挑选,其具有一个IP地址的NIC。失败有以下几个原因:1)网络卡可能不被连接到LAN 2)有多个NIC,其可能具有的IP地址
。4)只要发送所有MAC地址......问题是,名单会改变基础上安装的软件,这将是很难比较。
<强> 5)选取以最快的速度的MAC地址。我想这可能是我最好的选择。我认为这是肯定地说,最快的接口通常将是最持久的。
另外,可能有一些其他的方式来检测.NET物理卡或我会考虑调用其他的API调用,如果你能推荐一个,将提供不同的信息。
<强>任何其他的想法吗
要证明这里是我的样本代码的输出时,我有我的iPhone拴以上:
DEBUG - NIC Down Ethernet 500000 0021E98BFBEF Apple Mobile Device Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Ethernet 10000000 444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000 00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Loopback 10000000 MS TCP Loopback interface
无iPhone连接:
DEBUG - NIC Up Ethernet 10000000 444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000 00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Loopback 10000000 MS TCP Loopback interface
解决方案
这是我的方法: 它使用物理卡被连接到PCI接口的事实
ManagementObjectSearcher searcher = new ManagementObjectSearcher
("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDeviceID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();
foreach (ManagementObject obj in mObject)
{
string pnp = obj["PNPDeviceID"].ToString();
if (pnp.Contains("PCI\\"))
{
string mac = obj["MACAddress"].ToString();
mac = mac.Replace(":", string.Empty);
return mac;
}
}
其他提示
前三个字节的MAC地址是一个制造商ID。你可以黑名单知道您的目的是不适合某些制造商的ID,而忽略了这些接口。
依靠速度是不太可能是一个好主意,因为没有理由为什么一个VPN接口无法报告本身具有千兆速度。
MAC地址是物理硬件地址。我不能在这台电脑测试,但我不认为如果添加了虚拟连接,因为它不是一个实际的硬件,你会得到一个新的MAC地址。这将是另一个连接,但不是另一个MAC地址。
因此保证您得到相同的MAC地址的每个的时间取决于片相同硬件被附接至机器和您使用相同的算法从该硬件来接。
我一直在寻找这个问题为好,相信没有持久状态也将是难以维持稳定的MAC。
我正在与玩弄该解决方案是采取在适配器顺序,并使用该找到的第一个NIC,并保存它。然后在随后的UUID代,使用保存的MAC,如果它的任何地方发现了堆即使不是第一个。通过这种方式,适配器顺序可以移动,我们不担心炸毁上稳定的MAC任何取决于(如牌模块)。
如果在堆栈中没有找到MAC保存,它丢弃,我们只使用第一MAC绑定顺序并重新开始。
public static string GetMacAddressPhysicalNetworkInterface()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher
("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND" +
" PNPDeviceID IS NOT NULL AND" +
" PhysicalAdapter = true");
ManagementObjectCollection mObject = searcher.Get();
string macs = (from ManagementObject obj in mObject
let pnp = obj["PNPDeviceID"].ToString()
where !(pnp.Contains("ROOT\\"))
//where pnp.Contains("PCI\\") || pnp.Contains("USB\\")
select obj).Select(obj => obj["MACAddress"].ToString())
.Aggregate<string, string>(null, (mac, currentMac) => mac + currentMac.Replace(":", string.Empty) + ",");
return !string.IsNullOrEmpty(macs) ? macs.Substring(0, macs.Length - 1) : macs;
}
public static NetworkInterface GetPhysicalNetworkInterface(string macAddressPhysicalNetworkInterface)
{
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(currentNetworkInterface => string.Equals(currentNetworkInterface.GetPhysicalAddress().ToString(), macAddressPhysicalNetworkInterface, StringComparison.CurrentCultureIgnoreCase));
}