【问题标题】:How to use Python's ipaddress module to find if subnet/ip is within a bigger subnet?如何使用 Python ipaddress 模块查找子网/ip 是否在更大的子网中?
【发布时间】:2020-12-18 04:02:33
【问题描述】:
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}")

此操作失败,None 用于 internal_subnets 列表中的最后一个子网。那么,如何再次遍历 internal_subnet 列表中的前两个?

最终输出应该是 10.0.19.1/32 和 192.168.20.0/16 是 internal_subnets 的一部分。

请指教。

【问题讨论】:

  • 运行您发布的代码会导致:“ValueError: 192.168.0.0/8 has host bits set”

标签: python python-3.x ip-address


【解决方案1】:

由于某种原因,您编写的代码并行地遍历 internal_subnetsmy_sg_subnets。这就像这样:在第一次迭代时,它从第一个列表中获取第一个元素,并从第二个列表中获取第一个元素。在第二次迭代中,它从第一个列表中获取第二个元素,从第二个列表中获取第二个元素,依此类推。 相反,您需要遍历 internal_subnets,然后检查 my_sg_subnets 中的任何元素是否是子网。所以这个代码看起来像这样:

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

它按预期工作。这是输出:

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

为什么你的代码抛出ValueError: 192.168.0.0/8 has host bits set

我们知道每个 IP_v4 地址以及每个 IP_v4 网络掩码都只是 4 个字节的信息。所以让我们用二进制格式表示192.168.0.0地址和8网络掩码。

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

例如,如果您的网络的 IP 地址为 10.0.0.0,网络掩码为 8(或更大), 它会起作用,如果用二进制表示:

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

你会看到一切正常,因为地址后面没有设置位 其网络掩码的结尾。

此外,如果您为网络 10.0.0.0 设置网络掩码“7”,它也会起作用。但它可能会导致您可能不需要的问题,您会看到 11.0.0.0 地址在这个 10.0.0.0 网络内

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

希望它能让你更好地理解它是如何工作的

【讨论】:

  • 嵌套for循环没有问题。但是,如果 OP 真的想使用itertools(与他们的原始代码相同),则有itertools.product,如for my_ip, big_ip in product(my_sg_subnets, internal_subnets):
  • 谢谢!让我检查一下。此外,了解网络掩码 /8 很有趣,因为我们的几个网络是真正的 /8(在 AWS 安全组中)。这比我们需要的要大得多!但是,让我看看这个。非常感谢!
猜你喜欢
  • 2012-01-01
  • 2012-04-17
  • 2021-11-05
  • 1970-01-01
  • 2012-08-26
  • 2021-06-20
  • 2017-10-07
  • 2022-06-21
  • 2010-12-02
相关资源
最近更新 更多