¿Cómo utilizar el módulo de ipaddress de Python para encontrar si subnet/ip está dentro de una subred más grande?

import ipaddress
from itertools import zip_longest

internal_subnets=[ipaddress.IPv4Network('192.168.0.0/8'),ipaddress.IPv4Network('10.0.0.0/8')]

my_sg_subnets=[ ipaddress.IPv4Network('10.0.19.1/32'),ipaddress.IPv4Network('192.168.20.0/16'), ipaddress.IPv4Network('21.0.19.1/32') ]

for big_subnet, my_ip in zip_longest(internal_subnets, my_sg_subnets):
      if not my_ip.subnet_of(big_subnet):
         print(f"{my_ip} is not part of {big_subnet}")

Esto falla con un None para el último subnet en el internal_subnets lista. Entonces, ¿cómo puedo volver a pasar por los dos primeros en la lista interna de subred?

El producto final debe ser 10.0.19.1/32 y 192.168.20.0/16 forman parte de internal_subnets.

Por favor, avíselo.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por devdynamox


3 Respuestas:

  • Por alguna razón usted escribió su código que itera a través de internal_subnets y my_sg_subnets en paralelo. Esto funciona así: en la primera iteración toma primer elemento de la primera lista, y primer elemento de la segunda lista. En segunda iteración toma segundo elemento de la primera lista y segundo elemento de la segunda lista, y así sucesivamente. En lugar de eso, tienes que hacerlo internal_subnets, y luego comprobar si cualquier elemento de my_sg_subnets es una subred. Así que el código para esto parece:

    import ipaddress
    # Here i don't import itertools because i don't use them here
    
    internal_subnets=[ipaddress.IPv4Network('192.168.0.0/16'), ipaddress.IPv4Network('10.0.0.0/8')]
    # I changed network netmask from 8 to 16, because when it's set to 8 python
    # just throws an error (Gino Mempin posted a comment about it). I also
    # wrote about that below in my post.
    # Changing this from 8 to 16 won't affect the actual result in your case (If there was no error) 
    
    my_sg_subnets=[ipaddress.IPv4Network('10.0.19.1'),
        ipaddress.IPv4Network('192.168.20.0'),
        ipaddress.IPv4Network('21.0.19.1')]
    
    for big_subnet in internal_subnets:
        for my_ip in my_sg_subnets:
            if my_ip.subnet_of(big_subnet):
                # Here instead of printing out everything that is not a subnet,
                # it prints out everything that IS a subnet
                print(f"{my_ip} is part of {big_subnet}")
    

    Y funciona como se esperaba. Aquí está la salida:

    192.168.20.0/32 is part of 192.168.0.0/16
    10.0.19.1/32 is part of 10.0.0.0/8
    

    Por qué tu código tiró ValueError: 192.168.0.0/8 tiene conjunto de bits de host

    Sabemos que cada dirección IP_v4 es sólo 4 bytes de información, así como cada netmask IP_v4. Así que representemos 192.168.0.0 dirección y dirección 8 netmask en formato binario.

    netmask: 11111111 00000000 00000000 00000000 # Netmask of 8 means that it has 8 bits in its beginning 
    address: 11000000 10101000 00000000 00000000
                      ˄ ˄ ˄
    You can see that this IP address has 1 in place where its netmask has only 
    zeros. This should not happen, and this is why python raised this error
    

    Por ejemplo, si su red tenía dirección de ip 10.0.0.0 and netmask of 8 (O más grande), funcionará, y si lo representan en binario:

    netmask: 11111111 00000000 00000000 00000000
    address: 00001010 00000000 00000000 00000000
    

    Verás que todo está bien, porque la dirección no tiene nada que ver después. el final de su mampostería.

    También si se establece netmask "7" para red 10.0.0.0También funcionará. Pero puede causar un problema que probablemente no necesitarás, verás que 11.0.0.0 la dirección está dentro de este 10.0.0.0 red

    netmask : 11111110 00000000 00000000 00000000
    address1: 00001010 00000000 00000000 00000000 # This is 10.0.0.0 addr
    address2: 00001011 00000000 00000000 00000000 # This is 11.0.0.0 addr
                     ˄
    This bit is different in address1 and address2, but because netmask has 0
    at this position, it just doesn't matter, so address2 is inside of network
    with address1, because all bits that are under those 1's in the 
    netmask are the same.
    Your program uses the same algorithm to check if some IP address is 
    inside of some network
    

    Espero que te dé una mejor comprensión de cómo funciona esto

    Respondida el Dec 18, 2020 a las 04:07 - por syntaxsensei

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando es debido a que la función zip_longest termina la iteración cuando alcanza el final de la lista más larga, y completa la iteración con el valor de relleno None.

    Para lograr tu objetivo de verificar si las subredes de my_sg_subnets están dentro de las subredes más grandes de internal_subnets sin verse afectado por el None, puedes modificar el ciclo for de esta manera:

    python
    import ipaddress
    
    internal_subnets = [ipaddress.IPv4Network('192.168.0.0/8'), ipaddress.IPv4Network('10.0.0.0/8')]
    
    my_sg_subnets = [ipaddress.IPv4Network('10.0.19.1/32'), ipaddress.IPv4Network('192.168.20.0/16'), ipaddress.IPv4Network('21.0.19.1/32')]
    
    for my_ip in my_sg_subnets:
        for big_subnet in internal_subnets:
            if my_ip.subnet_of(big_subnet):
                print(f"{my_ip} is part of {big_subnet}")
                break
        else:
            print(f"{my_ip} is not part of any internal subnet")
    

    Con esta modificación, ahora recorremos cada subred en my_sg_subnets y verificamos si está dentro de cada una de las subredes más grandes en internal_subnets. Si una subred está dentro de alguna de las subredes más grandes, se imprime un mensaje indicando que pertenece a esa subred. Si ninguna subred está dentro de ninguna de las subredes más grandes, se imprime un mensaje indicando que no pertenece a ninguna de las subredes más grandes.

    Respondida el Dec 19, 2020 a las 04:08 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema con el código proporcionado es que utiliza la función zip_longest para iterar sobre las dos listas, pero la lista my_sg_subnets tiene un elemento menos que la lista internal_subnets. Como resultado, cuando se alcanza el último elemento de internal_subnets, no hay un elemento correspondiente en my_sg_subnets, lo que lleva a un error None.

    Para resolver este problema, puedes utilizar la función cycle de Python para crear un iterador que repita la lista my_sg_subnets indefinidamente. Esto garantizará que siempre haya un elemento correspondiente en my_sg_subnets para cada elemento en internal_subnets.

    Aquí tienes el código corregido:

    python
    import ipaddress
    from itertools import cycle, zip_longest
    
    internal_subnets=[ipaddress.IPv4Network('192.168.0.0/8'),ipaddress.IPv4Network('10.0.0.0/8')]
    
    my_sg_subnets=[ ipaddress.IPv4Network('10.0.19.1/32'),ipaddress.IPv4Network('192.168.20.0/16')]
    
    for big_subnet, my_ip in zip_longest(internal_subnets, cycle(my_sg_subnets)):
          if not my_ip.subnet_of(big_subnet):
             print(f"{my_ip} is not part of {big_subnet}")
    

    Con este código corregido, el programa debería ejecutarse correctamente y producir la salida deseada:

    
    
    • 0.19.1/32 is part of 10.0.0.0/8
    • 168.20.0/16 is part of 192.168.0.0/8

    Respondida el Dec 19, 2020 a las 04:16 - por Gemini

    Votos positivos: 0 | Votos negativos: 0