如何确定实际物理网卡的 MAC 地址——而不是 VPN 创建的虚拟网络接口 (.NET C#)

发布于 2024-08-07 06:03:58 字数 2246 浏览 10 评论 0原文

背景

我试图从计算机中获取唯一标识符,并希望每次都能可靠地返回相同的 MAC 地址。相信我,我有使用 MAC 地址的理由,并且阅读了许多关于替代唯一 id 方法的帖子(是的,我考虑过他们是否没有任何网卡)。

问题

问题出在 .NET 中,无论如何我都无法判断特定的 NetworkInterface 是否是来自“Nortel 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 地址对于给定的机器,它最不可能改变。独立于诸如是否连接到 wifi...通过某种类型的系绳连接进行连接...或者他们安装一些新的 VPN 软件来添加新接口等因素。

考虑的策略

1) 选择第一个“Up”接口。这在我的笔记本电脑上失败了,因为“数据包微型端口”始终处于打开状态。此外,如果我将手机连接到笔记本电脑,这也会显示为第一张卡。

2)选择最合适的类型...这失败了,因为基本上所有内容都显示为“以太网”,包括 WiFi 适配器和我的 iPhone 网络共享互联网连接。

3) 选择有IP 地址的NIC。失败有多种原因:1) 网卡可能未连接到 LAN 2) 多个网卡可能具有 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

Background

I'm trying to get obtain a unique identifier out of a computer and want to be able to reliably return the same MAC address each time. Trust me I have my reasons for using MAC address and have read many posts about alternate unique id methods (and yes i've considered if they don't have any network cards).

Problem

The problem is in .NET i don't see anyway to tell whether a specific NetworkInterface is a physical hardware network card from something like a "Nortel IPSECSHM Adapter - Packet Scheduler Miniport" which get added when you connect to certain VPNs or WiFi networks.

I know how to get the Mac Addresses by using code similar to this:

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
    }

Understandably there is no 100% way to make sure i'd be getting an internal network card but i'd like to pick the MAC address to return which for a given machine which is least likely to change. Independent of factors such as -- whether it's connected to wifi... gets connected via some type of tether connection... or they install some new vpn software which adds a new interface.

Strategies Considered

1) Choose the first interface that is "Up". This fails on my laptop because the "Packet Miniport" is always up. Additionally, if I tether my phone to my laptop this also shows up as the first card.

2) Choose the most appropriate type... This fails b/c basically everything shows up as "Ethernet" including WiFi Adapters and my iPHone tethering internet connection.

3) Pick the NIC which has an IP address. Fails for several reasons: 1) Network card might not be connected to LAN 2) There are multiple nics which might have IP Addresses.

4) Just send all MAC addresses... Problem is the list would change based on installed software and it'll be difficult to compare.

5) Pick the mac address with the fastest speed. I think this is probably my best bet. I think it's safe to say that the fastest interface is usually going to be the most permanent.

Alternatively, there may be some other way to detect physical cards in .NET or I'd consider invoking other API calls if you could recommend one that will provide different information.

Any other ideas?

To demonstrate here is the output of my sample code above when I have my iphone tethered:

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

Without Iphone Connected:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烟酉 2024-08-14 06:03:58

这是我的方法:
它利用物理卡连接到 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;
    }
}

This is my method:
it uses the fact that physical card is connected to PCI interface

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;
    }
}
风筝有风,海豚有海 2024-08-14 06:03:58

MAC 地址的前三个字节是制造商 ID。您可以将已知不适合您的目的的某些制造商 ID 列入黑名单,并忽略这些接口。

依赖速度可能不是一个好主意,因为 VPN 接口没有理由不能报告自己具有千兆位速度。

The first three bytes of the MAC address are a manufacturer ID. You could blacklist certain manufacturer IDs known to be unsuitable for your purposes, and ignore those interfaces.

Relying on the speed is not likely to be a good idea, because there's no reason why a VPN interface couldn't report itself as having gigabit speed.

信愁 2024-08-14 06:03:58

MAC地址是物理硬件地址。我无法在这台电脑上进行测试,但我认为如果添加虚拟连接,您不会获得新的 MAC 地址,因为它不是实际的硬件。这将是另一个连接,但不是另一个 MAC 地址。

因此,保证每次都获得相同的 MAC 地址取决于连接到计算机的相同硬件以及您使用相同的算法从该硬件中进行选择。

MAC addresses are physical hardware addresses. I can't test on this pc, but I don't think you will get a new MAC address if a virtual connection is added because it's not an actual piece of hardware. It will be another connection, but not another MAC address.

So guaranteeing that you get the same MAC address every time depends on the same pieces of hardware being attached to the machine and you using the same algorithm to pick from that hardware.

吐个泡泡 2024-08-14 06:03:58

我也一直在研究这个问题,并且相信如果没有持久状态,将很难维持稳定的 MAC。

我正在尝试的解决方案是采用适配器订单中找到的第一个 NIC 并使用它并保存它。然后,在后续的 UUID 生成中,如果在堆栈中的任何位置找到了保存的 MAC(即使不是第一个),则使用保存的 MAC。这样,适配器顺序就可以移动,并且我们不用担心会破坏任何依赖于稳定 MAC 的内容(例如许可模块)。

如果在堆栈中找不到保存的 MAC,它将被丢弃,我们只需使用绑定顺序中的第一个 MAC 并重新开始。

I've been looking at this problem as well, and believe that without persistent state it's going to be difficult to maintain a stable MAC.

The solution I'm toying with is take the first NIC found in the adapter order and use that and save it. Then on subsequent UUID generations, use the saved MAC if it's found anywhere in the stack even if not the first. This way the adapter order can move around and we don't worry about blowing up whatever depends on the stable MAC (such as a licensing module).

If the saved MAC is not found in the stack, it's discarded and we just use the first MAC in the binding order and start over.

白鸥掠海 2024-08-14 06:03:58
 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));
    }
 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));
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文