Как определить MAC-адрес реальной физической сетевой карты, а не виртуальных сетевых интерфейсов, созданных VPN (.NET C #)

StackOverflow https://stackoverflow.com/questions/1567377

Вопрос

Предыстория

Я пытаюсь получить уникальный идентификатор с компьютера и хочу иметь возможность каждый раз надежно возвращать один и тот же MAC-адрес.Поверьте мне, у меня есть свои причины использовать MAC-адрес, и я прочитал много сообщений об альтернативных методах уникального идентификатора (и да, я рассматривал, нет ли у них сетевых карт).

Проблема

Проблема в .NET, я все равно не вижу способа определить, является ли конкретный сетевой интерфейс физической аппаратной сетевой картой из чего-то вроде "минипорта Nortel IPSECSHM Adapter - Packet Scheduler", который добавляется при подключении к определенным 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) Выберите наиболее подходящий тип...Это не удается, потому что в основном все отображается как "Ethernet", включая адаптеры Wi-Fi и подключение к Интернету для моего iPhone.

3) Выберите сетевую карту, у которой есть IP-адрес.Терпит неудачу по нескольким причинам:1) Сетевая карта может быть не подключена к локальной сети 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
Это было полезно?

Решение

Это мой метод:он использует тот факт, что физическая карта подключена к интерфейсу 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-адреса - это идентификатор производителя.Вы могли бы занести в черный список определенные идентификаторы производителя, которые, как известно, не подходят для ваших целей, и игнорировать эти интерфейсы.

Полагаться на скорость вряд ли будет хорошей идеей, потому что нет никаких причин, по которым интерфейс VPN не мог бы сообщить о себе как о имеющем гигабитную скорость.

MAC-адреса - это физические аппаратные адреса.Я не могу протестировать на этом компьютере, но я не думаю, что вы получите новый MAC-адрес, если будет добавлено виртуальное соединение, потому что это не реальное аппаратное обеспечение.Это будет другое соединение, но не другой MAC-адрес.

Таким образом, гарантия того, что вы каждый раз получаете один и тот же MAC-адрес, зависит от того, что к компьютеру подключены одни и те же аппаратные средства и вы используете один и тот же алгоритм для выбора из этого оборудования.

Я также рассматривал эту проблему и считаю, что без постоянного состояния будет трудно поддерживать стабильный MAC.

Решение, с которым я играю, - это взять первый сетевой адаптер, найденный в заказе адаптеров, и использовать его и сохрани это.Затем при последующих поколениях 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));
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top