Cómo determinar la dirección MAC de la tarjeta de red física real - las interfaces de red no virtuales creados por la VPN (.NET C #)

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

Pregunta

Fondo

Estoy intentando conseguir obtener un identificador único de un ordenador y quieren ser capaces de regresar de forma fiable la misma dirección MAC cada vez. Confía en mí Tengo mis razones para el uso de la dirección MAC y leído muchos mensajes acerca de los métodos alternativos de identificación únicos (y sí que he considerado si no tienen ningún tarjetas de red).

Problema

El problema está en .NET no veo de todos modos para decir si un NetworkInterface específico es una tarjeta de red de hardware físico de algo así como un "adaptador IPSECSHM Nortel - Programador de paquetes Minipuerto", que se añaden cuando se conecta a ciertas redes privadas virtuales o redes WiFi.

Yo sé cómo conseguir las direcciones MAC mediante el uso de un código similar al siguiente:

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

Es comprensible que no hay manera de 100% para asegurarse de que me gustaría estar recibiendo una tarjeta de red interna, pero me gustaría recoger la dirección MAC para devolver lo que para una máquina dada, que es menos probable que cambie . Independiente de factores tales como -. Si está conectado a Wi-Fi ... se conecta a través de algún tipo de conexión de correa ... o que instalan un nuevo software VPN que añade una nueva interfaz

estrategias consideradas

1) Selecciona la primera interfaz que es "arriba". Esta falla en mi portátil porque el "Paquete Minipuerto" es siempre hacia arriba. Además, si Tether mi teléfono a mi ordenador portátil esto también se muestra como la primera tarjeta.

2) Elegir el tipo más adecuado ... Esta falla b / c básicamente todo lo que se muestra como "Ethernet", incluyendo los adaptadores WiFi y mi conexión a Internet de la inmovilización.

3) Pick la NIC que tiene una dirección IP. Falla por varias razones: 1) La tarjeta de red no esté conectado a la LAN 2) Hay varias tarjetas de red que pueden tener direcciones IP

.

4) Sólo tiene que enviar todas las direcciones MAC ... El problema es que la lista sería cambiar en función del software instalado y va a ser difícil de comparar.

5) Recoger la dirección MAC con la velocidad más rápida. Creo que esto es probablemente mi mejor apuesta. Creo que es seguro decir que la interfaz más rápida es por lo general va a ser el más permanente.

Como alternativa, puede haber alguna otra manera de detectar tarjetas físicas en .NET o me gustaría considerar la invocación de otras llamadas a la API si se puede recomendar uno que proporcionará una información diferente.

¿Alguna otra idea?

Para demostrar aquí es la salida de mi código de ejemplo anterior, cuando tengo mi iphone atado:

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

Sin Iphone Conectado:

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
¿Fue útil?

Solución

Este es mi método: que utiliza el hecho de que la tarjeta física está conectada a la interfaz 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;
    }
}

Otros consejos

Los tres primeros bytes de la dirección MAC son un indicativo del fabricante. Se podría lista negra determinados ID de fabricante se sabe que son inadecuados para sus propósitos, e ignorar esas interfaces.

Basándose en la velocidad no es probable que sea una buena idea, porque no hay razón para que una interfaz de VPN no pudo informar a sí mismo como tener la velocidad gigabit.

Las direcciones MAC son direcciones físicas de hardware. No puedo probar en este equipo, pero no creo que obtendrá una nueva dirección MAC si se añade una conexión virtual, porque no es una verdadera pieza de hardware. Será otra conexión, pero no en otra dirección MAC.

Así que garantiza que obtener la dirección MAC de la misma cada vez que depende de las mismas piezas de hardware que se adjunta a la máquina y que utilizando el mismo algoritmo para elegir ese hardware.

He estado buscando en este problema también, y creo que sin estado persistente que va a ser difícil mantener un MAC estable.

La solución que estoy jugando con es tomar la primera NIC que se encuentra en el orden del adaptador y el uso que y guardarlo . A continuación, en las generaciones posteriores UUID, utilice el MAC salvado si se detecta cualquier lugar de la pila incluso si no el primero. De esta manera el orden adaptador puede moverse y que no se preocupe por la voladura de lo que sea depende del MAC estable (por ejemplo, un módulo de licencia).

Si el MAC no se encuentra guardado en la pila, es descartado y que sólo tiene que utilizar el primer MAC en el orden de enlace y empezar de nuevo.

 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));
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top