Obtener la puerta de enlace predeterminada


Estoy escribiendo un programa que muestra al usuario su dirección IP, máscara de subred y puerta de enlace predeterminada. Puedo obtener los dos primeros, pero para el último, esto es lo que encontré:

GatewayIPAddressInformationCollection gwc = 
    System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].GetIPProperties().GatewayAddresses;

Que, por supuesto, devuelve una colección de GatewayIPAddressInformation. Entonces, si un equipo tiene varias puertas de enlace, ¿cómo puedo determinar cuál es la puerta de enlace predeterminada?

En la práctica, solo he visto que esta colección contiene una sola entrada, pero ya que se implementa como una colección, es lógico pensar que algunos equipos contienen varias puertas de enlace, ninguna de las cuales está marcada como "Predeterminada". Entonces, ¿hay una manera de determinar el predeterminado o es todo solo conjeturas?

Author: Frecklefoot, 0000-00-00

3 answers

Debe ser la primera dirección de puerta de enlace válida y habilitada de la primera interfaz de red habilitada:

public static IPAddress GetDefaultGateway()
{
    return NetworkInterface
        .GetAllNetworkInterfaces()
        .Where(n => n.OperationalStatus == OperationalStatus.Up)
        .Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .SelectMany(n => n.GetIPProperties()?.GatewayAddresses)
        .Select(g => g?.Address)
        .Where(a => a != null)
         // .Where(a => a.AddressFamily == AddressFamily.InterNetwork)
         // .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0)
        .FirstOrDefault();
}

También he añadido algunas comprobaciones comentadas adicionales que han sido señaladas como útiles por otras personas aquí. Puede comprobar el AddressFamily para distinguir entre IPv4 e IPv6. Este último se puede usar si tiene problemas con una dirección 0.0.0.0 que se devuelve.

Dicho esto, la forma recomendada de hacer esto utiliza GetBestInterface para encontrar una interfaz para enrutar a un dirección IP específica. Si ya tienes una dirección IP de destino en mente, entonces es mejor usar esto, por lo que también he incluido un ejemplo de eso a continuación:

[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
private static extern int GetBestInterface(UInt32 destAddr, out UInt32 bestIfIndex);

public static IPAddress GetGatewayForDestination(IPAddress destinationAddress)
{
    UInt32 destaddr = BitConverter.ToUInt32(destinationAddress.GetAddressBytes(), 0);

    uint interfaceIndex;
    int result = GetBestInterface(destaddr, out interfaceIndex);
    if (result != 0)
        throw new Win32Exception(result);

    foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        var niprops = ni.GetIPProperties();
        if (niprops == null)
            continue;

        var gateway = niprops.GatewayAddresses?.FirstOrDefault()?.Address;
        if (gateway == null)
            continue;

        if (ni.Supports(NetworkInterfaceComponent.IPv4))
        {
            var v4props = niprops.GetIPv4Properties();
            if (v4props == null)
                continue;

            if (v4props.Index == interfaceIndex)
                return gateway;
        }

        if (ni.Supports(NetworkInterfaceComponent.IPv6))
        {
            var v6props = niprops.GetIPv6Properties();
            if (v6props == null)
                continue;

            if (v6props.Index == interfaceIndex)
                return gateway;
        }
    }

    return null;
}
 30
Author: caesay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 15:47:37

La primera dirección IP devuelta por el comando traceroute será la puerta de enlace .También puede usar este hecho para obtener gateway.Puedes encontrar una buena implementación de tracerout aquí: TraceRoute y Ping en C#

 3
Author: harsini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:39

Sé que esta es una pregunta un poco más antigua, pero, acababa de llegar a la necesidad de recuperar la dirección IPV4 de la puerta de enlace local. La respuesta aceptada no se ajusta a la factura cuando se trata de mi propio sistema, así que la modifiqué a suite y estoy seguro de que otros también podrán usar esta solución.

Dado que todavía no tengo suficiente rep para comentar, me veo obligado a agregar esto como una"pregunta":

public static IPAddress 
 2
Author: ,
Warning: date() expects parameter 2 to be long, string given in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61