检查IP是否在Python中的CIDR范围内

新手上路,请多包涵

我知道这里有一些类似的问题,但他们主要是想找到范围本身(它使用了一些库,比如 stackoverflow 说的例子是我的问题的骗局)并且是另一种语言。

我有办法将子网转换为子网中 ip 范围的开头和结尾(好吧,措辞不好,就像 1.1.1.1/16 -> (1.1.0.0 , 1.1.255.255)

我现在想检查 1.1.2.2 是否在此子网内。我可以简单地做一个 >< 来比较吗?

 ip_range = ('1.1.0.0', '1.1.255.255')
if '1.1.2.2' >= ip_range[0] and '1.1.2.2' <= ip_range[1]:
     return True

当我测试它时,它可以工作,但我不知道它是否总是适用于任何 ipv4 ip。我假设我只是比较 ASCII order ,所以这应该总是有效的,但是有什么例外吗?

原文由 JChao 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

您不能真正对以点分隔的数字列表进行字符串比较,因为您的测试只会在输入时失败 1.1.99.99 因为 '9' 只是大于 '2'

 >>> '1.1.99.99' < '1.1.255.255'
False

因此,您可以通过理解表达式将输入转换为整数元组

def convert_ipv4(ip):
    return tuple(int(n) for n in ip.split('.'))

请注意缺少类型检查,但如果您输入的是正确的 IP 地址,那就没问题了。由于您有一个 2 元组的 IP 地址,您可以创建一个将开始和结束作为参数的函数,通过参数列表传递该元组,并仅使用一个语句返回它(因为 Python 允许比较链接)。也许像:

 def check_ipv4_in(addr, start, end):
    return convert_ipv4(start) < convert_ipv4(addr) < convert_ipv4(end)

测试一下。

 >>> ip_range = ('1.1.0.0', '1.1.255.255')
>>> check_ipv4_in('1.1.99.99', *ip_range)
True

使用这种方法,您可以延迟将其扩展到 IPv6,尽管需要与十六进制(而不是 int)进行相互转换。

原文由 metatoaster 发布,翻译遵循 CC BY-SA 3.0 许可协议

在 Python 3.3 及更高版本中,您应该使用 ipaddress 模块

 from ipaddress import ip_network, ip_address

net = ip_network("1.1.0.0/16")
print(ip_address("1.1.2.2") in net)    # True

原文由 kindall 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题