2011-11-13 19 views
17

hasta ahora tengo este código:cómo determinar si una dirección IP es privada?

NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); 

foreach (NetworkInterface adapter in adapters) 
{ 
    IPInterfaceProperties properties = adapter.GetIPProperties(); 

    foreach (IPAddressInformation uniCast in properties.UnicastAddresses) 
    { 

    // Ignore loop-back addresses & IPv6 
    if (!IPAddress.IsLoopback(uniCast.Address) && 
     uniCast.Address.AddressFamily!= AddressFamily.InterNetworkV6) 
     Addresses.Add(uniCast.Address); 
    } 
} 

Cómo puedo filtrar las direcciones IP privadas, así? De la misma manera que estoy filtrando las direcciones IP de bucle invertido.

Respuesta

33

Una respuesta más detallada está aquí:

private bool _IsPrivate(string ipAddress) 
{ 
    int[] ipParts = ipAddress.Split(new String[] { "." }, StringSplitOptions.RemoveEmptyEntries) 
          .Select(s => int.Parse(s)).ToArray(); 
    // in private ip range 
    if (ipParts[0] == 10 || 
     (ipParts[0] == 192 && ipParts[1] == 168) || 
     (ipParts[0] == 172 && (ipParts[1] >= 16 && ipParts[1] <= 31))) { 
     return true; 
    } 

    // IP Address is probably public. 
    // This doesn't catch some VPN ranges like OpenVPN and Hamachi. 
    return false; 
} 
13

Los rangos de direcciones privadas se definen en RFC1918. Ellos son:

  • 10.0.0.0 - 10.255.255.255 (10/8 prefijo)
  • 172.16.0.0 - 172.31.255.255 (172,16/12 prefijo)
  • 192.168.0.0 - 192.168.255.255 (192,168/16 prefix)

Es posible que también desee filtrar las direcciones locales de los enlaces (169.254/16) tal como se definen en RFC3927.

4
10.0.0.0  - 10.255.255.255 (10/8 prefix) 
172.16.0.0  - 172.31.255.255 (172.16/12 prefix) 
192.168.0.0  - 192.168.255.255 (192.168/16 prefix) 

Utilice los rangos definidos en el RFC (según lo sugerido por Anders); que utilizar la expresión regular para detectar/eliminar la dirección IP privada de la lista.

Aquí hay un ejemplo de RegEx para detectar direcciones IP privadas. (No se ha probado por mí)

(^127\.0\.0\.1)| 
(^10\.)| 
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)| 
(^192\.168\.) 
+2

Posiblemente más fácil convertir a uint32 y luego usar operaciones bit a bit: '((dirección y 0xFF000000U) == 0x0A000000U) || ... '. Si hay una gran cantidad de direcciones para verificar, también debería ser más rápido. – Richard

+1

Sospecho que esto funcionará, pero las expresiones regulares son conceptualmente la herramienta incorrecta para probar si los enteros pequeños están en el rango correcto. Comparar números será mucho más eficiente que emparejar cadenas. – Anthony

+0

Convierta la IP actual a la representación numérica y luego vea si encaja en cualquiera de esas clases (use solo la comparación numérica). Funciona perfectamente para mí. – Edi

4

La mejor manera de hacer esto sería un método de extensión a la clase de dirección IP

/// <summary> 
    /// An extension method to determine if an IP address is internal, as specified in RFC1918 
    /// </summary> 
    /// <param name="toTest">The IP address that will be tested</param> 
    /// <returns>Returns true if the IP is internal, false if it is external</returns> 
    public static bool IsInternal(this IPAddress toTest) 
    { 
     byte[] bytes = toTest.GetAddressBytes(); 
     switch(bytes[ 0 ]) 
     { 
      case 10: 
       return true; 
      case 172: 
       return bytes[ 1 ] < 32 && bytes[ 1 ] >= 16; 
      case 192: 
       return bytes[ 1 ] == 168; 
      default: 
       return false; 
     } 
    } 

Entonces , se puede llamar al método en una instancia de la clase de dirección IP

bool isIpInternal = ipAddressInformation.Address.IsInternal(); 
3

Casos añadidos de IPv6 y localhost.

/* An IP should be considered as internal when: 

     ::1   - IPv6 loopback 
     10.0.0.0  - 10.255.255.255 (10/8 prefix) 
     127.0.0.0 - 127.255.255.255 (127/8 prefix) 
     172.16.0.0 - 172.31.255.255 (172.16/12 prefix) 
     192.168.0.0 - 192.168.255.255 (192.168/16 prefix) 
    */ 
    public bool IsInternal(string testIp) 
    { 
     if(testIp == "::1") return true; 

     byte[] ip = IPAddress.Parse(testIp).GetAddressBytes(); 
     switch (ip[0]) 
     { 
      case 10: 
      case 127: 
       return true; 
      case 172: 
       return ip[1] >= 16 && ip[1] < 32; 
      case 192: 
       return ip[1] == 168; 
      default: 
       return false; 
     } 
    } 
Cuestiones relacionadas