sks
sks

Reputation: 53

How to use Python's ipaddress module to find if subnet/ip is within a bigger subnet?

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}")

This fails with a None for the last subnet in the internal_subnets list. So, how do I iterate again through the first two in the internal_subnet list?

The final output should be 10.0.19.1/32 and 192.168.20.0/16 are part of internal_subnets.

Please advise.

Upvotes: 2

Views: 1651

Answers (1)

user14203455
user14203455

Reputation:

For some reason you wrote your code that it iterates through internal_subnets and my_sg_subnets in parallel. This works like this: on first iteration it grabs first element from first list, and first element from second list. On second iteration it grabs second element from first list and second element from second list, and so on. Instead, you need to iterate through internal_subnets, and then check if any element from my_sg_subnets is a subnet. So code for this looks like this:

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}")

And it works as expected. Here's the output:

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

Why your code threw ValueError: 192.168.0.0/8 has host bits set

We know that every IP_v4 address is just 4 bytes of information, as well as every IP_v4 netmask. So let's represent 192.168.0.0 address and 8 netmask in binary format.

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

For example if your network had ip address of 10.0.0.0 and netmask of 8 (Or bigger), it will work, and if represent it in binary:

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

you'll see that everything is okay, because address has no bits set after the end of its netmask.

Also if you set netmask "7" for network 10.0.0.0, it will work as well. But it can cause a problem that you won't probably need, you'll see that 11.0.0.0 address is inside of this 10.0.0.0 network

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

Hope it'll give you better understanding of how this works

Upvotes: 3

Related Questions