2010-02-16 13 views
10

Aquí está el escenario ... Tengo una tabla de subredes. (ver más abajo) Tengo una dirección IP. Me gustaría saber a qué subred pertenece la dirección IP en función de una búsqueda en la tabla. Esta asociación se usará para determinar en qué ubicación se encuentra el usuario. Es un espacio de red privado, por lo que no se aplicarán las búsquedas estándares de internet para la ubicación. ¿Cuál sería el mejor enfoque? ¿Tendría que dividir la dirección IP en sus partes numéricas y en una comparación bit a bit de todas las subredes? O ¿hay herramientas incorporadas en la API de Java que podrían facilitar mi vida al comparar la dirección IP con la máscara de subred?Coincidencia de una dirección IP con una tabla de máscaras de subred ... ¿Cuál es el mejor enfoque en Java?

Estoy buscando la mejor manera de comparar ipaddress a una máscara de subred determinada y determinar si esto coincide, o no, no. Opcionalmente. También se agradecerá cualquier consejo sobre cómo almacenar la lista y buscar con operaciones mínimas.

Lo ideal sería que estaría haciendo algo similar a esto:

List subnetInfo = null; 

subnetInfo = findSubnet('192.168.0.1'); //value null if nothing found 

.... 

//return null if nothing found 
List findSubnet(String ipaddress) { 
    List subnetDetails = null; 
    .... code here ... 
    return subnetDetails; 
} 

Tabla 1: Muestra la lista de subredes

dk-ballerup-gen-off-v411  10.172.80.0/21 NANR-denmark-ballerup-metallbuen66-ground-first-floors-incl-dhcp-(sr14585203) 
ae-dubai-ofssl-gen-off-v410 10.172.88.0/24 NANR-arab-emirates-ofssl-iflex-general-office-v410-(sr12781477) 
ru-stpetersburg-gen-off-v411 10.172.89.0/24 NANR-russia-stpetersburg-general-office-incl-dhcp (bsteinba) 

Respuesta

3

Apache Commons Net tiene un SubnetUtils para este tipo de cosas, incluida la determinación de si una dirección IP determinada se encuentra dentro de una subred determinada.

ejemplo trivial:

String[] subnetsMasks = { ... }; 
    Collection<SubnetInfo> subnets = new ArrayList<SubnetInfo>(); 
    for (String subnetMask : subnetsMasks) { 
     subnets.add(new SubnetUtils(subnetMask).getInfo()); 
    } 

    String ipAddress = ...; 
    for (SubnetInfo subnet : subnets) { 
     if (subnet.isInRange(ipAddress)) { 
      System.out.println("IP Address " + ipAddress + " is in range " + subnet.getCidrSignature()); 
     } 
    } 
+0

¿Por qué necesitarías una API para algo que puedas consultar con el operador &? ... por lo que las máscaras de red se * llaman * máscaras de red ... – EJP

+3

Porque convertir una máscara CIDR en un número es el tipo de tarea que se puede equivocar fácilmente. ¿Por qué volver a implementarlo, cuando puede sacarlo de la estantería? – skaffman

+0

Estás bromeando, ¿verdad? Ni siquiera tiene que convertir los bytes en un entero, solo puede enmascarar los bytes en un bucle. Alrededor de 4 líneas de código. – EJP

3

Recuerde, que la dirección IP es sólo un valor int por razones históricas representadas como 4 octetos en forma decimal.

Por la misma razón, la subred es realmente un rango de ints consecutivos desde la dirección de red a una dirección de difusión.

Por lo tanto, si su objeto de dirección IP tiene un convertidor int, simplemente puede verificar si ese entero está dentro del rango de la subred haciendo comparaciones int simples.

0

Si su tabla es una tabla SQL Y su base de datos es PostgreSql, puede utilizar PostgreSQL types y functions.

Bueno, eso es un montón de condiciones ...

0

Girar la dirección IP y la máscara de red en enteros y Y juntos. Si el resultado es igual a la dirección IP, es una dirección en esa máscara de red. Tenga en cuenta que puede obtener más de una coincidencia si sus máscaras de red no son distintas.

+1

Esto solo es válido para IPv4. La misma técnica funciona para IPv6, pero las direcciones no son ints. Ni siquiera son largos. Son números de 128 bits, que Java representa como una matriz de bytes. –

0

he construido en la parte superior de la solución skaffman un método.Para aquellos que están interesados ​​en una solución de goma de la copia:

/** 
    * Checks if client ip equals or is in range of ip networks provided by 
    * semicolon separated list 
    * 
    * @param clientIp in numeric form like "192.168.0.10" 
    * @param ipList like "127.0.0.1;192.168.0.0/24;10.0.0.0/8" 
    * @return true if client ip from the list os ips and networks 
    */ 
    protected boolean evaluateIp(String clientIp, String ipList) { 
     BusinessLogger log = getLog(); 
     log.debug("Evaluate ip "); 
     if (ipList == null) { 
      log.info("No ip address provided in ApiPrivilege"); 
      return false; 
     } 
     String[] subnetMasks = ipList.split(";"); 
     for (String subnetMask : subnetMasks) { 
      subnetMask = subnetMask.trim(); 
      if (eq(subnetMask, clientIp)) 
       return true; 
      if (subnetMask.contains("/")) { 
       if (new SubnetUtils(subnetMask).getInfo().isInRange(clientIp)) 
        return true; 
      } 
     } 
     return false; 
    } 
-3

Incluya la siguiente frasco de su pom.xml en

*<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-web</artifactId> 
    <version>3.0.7.RELEASE</version> 
</dependency>* 

un resorte que proporciona la biblioteca de arriba para apoyar el IPv4 e IPv6.

A continuación se muestra el fragmento de código para comprobar si ip cae bajo subred determinada.

System.out.println(matches("192.168.2.1", "192.168.2.1/11")); 
System.out.println( matches("192.168.2.1", "192.168.2.0/32")); 
System.out.println( matches("192.168.2.5", "192.168.2.0/24")); 
System.out.println( matches("fe80:0:0:0:0:0:c0a8:11", 
    "fe80:0:0:0:0:0:c0a8:1/120")); 
System.out.println( matches("fe80:0:0:0:0:0:c0a8:11", 
    "fe80:0:0:0:0:0:c0a8:1/128")); 
System.out.println(matches("2401:4900:1780:0:0:0:0:11", 
    "2401:4900:1780:0:0:0:0:0/44")); 


private static boolean matches(String ip, String subnet) { 
    IpAddressMatcher ipAddressMatcher = new IpAddressMatcher(subnet); 
    return ipAddressMatcher.matches(ip); 
} 
+1

Si tiene una nueva pregunta, por favor, haga clic en el botón [Ask Question] (https://stackoverflow.com/questions/ask). Incluye un enlace a esta pregunta si ayuda a proporcionar contexto. - [De la crítica] (/ review/low-quality-posts/19032814) – shadow

+0

Esto realmente no responde la pregunta. Si tiene una pregunta diferente, puede formularla haciendo clic en [Preguntar pregunta] (https://stackoverflow.com/questions/ask). También puede [agregar una recompensa] (https://stackoverflow.com/help/privileges/set-bounties) para atraer más atención a esta pregunta una vez que tenga suficiente [reputación] (https://stackoverflow.com/help/ que-reputación). - [De la crítica] (/ review/low-quality-posts/19032814) – Daniel

+0

Perdón por la publicación incorrecta. Ahora he editado para corregir la respuesta. –

Cuestiones relacionadas