Start Debugging

¿.NET 10 hizo explotar tu lista de NICs? Filtrar GetAllNetworkInterfaces() sin engañarte a ti mismo

Cómo filtrar GetAllNetworkInterfaces() en .NET 10 cuando los adaptadores virtuales de Hyper-V, Docker, WSL y VPNs inundan la lista. Incluye un filtro en dos etapas con compensaciones explícitas.

Si acabas de migrar una app de .NET 8 a .NET 10 y de pronto NetworkInterface.GetAllNetworkInterfaces() devuelve 80 adaptadores en vez de 10, no lo estás imaginando. Esto apareció en un hilo del 7 de enero de 2026, con exactamente el tipo de dolor del mundo real que hace que cambios de comportamiento “menores” se sientan como cambios disruptivos: interfaces virtuales de Hyper-V, Docker, WSL, VPNs, loopback y otros adaptadores del sistema empiezan a desplazar a los dispositivos Ethernet y Wi-Fi “reales”.

Fuente: NetworkInterface.GetAllNetworkInterfaces breaking change (r/dotnet)

La verdad incómoda: “físico” es una heurística

System.Net.NetworkInformation no te da un único booleano oficial del estilo “esto es una NIC física” en el que puedas confiar entre máquinas, drivers y características de Windows. La estrategia más segura es construir un filtro que se ajuste a las necesidades de tu producto, y hacer ese filtro auditable y testeable.

Empieza con señales estrictas que normalmente correlacionan con “útil para conectividad”:

Luego agrega exclusiones más blandas y específicas del entorno (Docker, Hyper-V, WSL, VPN) como segunda etapa.

Un filtro en dos etapas que es explícito sobre las compensaciones

El hilo propuso este enfoque (recortado y algo endurecido por legibilidad):

using System.Net.NetworkInformation;

var candidates = NetworkInterface.GetAllNetworkInterfaces()
    .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
    .Where(nic => nic.NetworkInterfaceType is
        NetworkInterfaceType.Ethernet or
        NetworkInterfaceType.Wireless80211 or
        NetworkInterfaceType.GigabitEthernet)
    .Where(nic => !LooksVirtual(nic))
    .ToArray();

static bool LooksVirtual(NetworkInterface nic)
{
    var desc = (nic.Description ?? "").ToLowerInvariant();
    var name = (nic.Name ?? "").ToLowerInvariant();

    string[] keywords =
    {
        "virtual", "hyper-v", "vmware", "virtualbox",
        "docker", "vpn", "tap-", "wsl", "pseudo"
    };

    return keywords.Any(k => desc.Contains(k) || name.Contains(k));
}

¿Es chapucero? Sí. Pero también es honesto: reconoce que estás codificando una política.

Para hacerlo menos frágil, evita depender solo de strings:

Depúralo como un incidente de producción, no como una curiosidad

Cuando tu conteo de adaptadores cambia entre versiones de .NET, trátalo como una diferencia de comportamiento observable:

.NET 10 te da la lista cruda. Tu app sigue teniendo que decidir qué significa “real”.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Volver