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

2024-06-09 15:57:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道这里有一些类似的问题,但他们大多要么想找到范围本身(它使用一些库,比如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顺序,所以这应该总是工作,但有什么例外吗?


Tags: and方法ip语言truereturnifascii
3条回答

在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

代码比较字符串,而不是数字。我建议改用元组:

>>> ip_range = [(1,1,0,0), (1,1,255,255)]
>>> testip = (1,1,2,2)
>>> testip > ip_range[0] and testip < ip_range[1]
True
>>> testip = (1,3,1,1)
>>> testip > ip_range[0] and testip < ip_range[1]
False

您不能在点分隔的数字列表上进行字符串比较,因为您的测试将在输入时失败,例如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地址,则可以。由于您有一个IP地址的2元组,因此可以创建一个函数,该函数将start和end都作为参数,通过参数列表传递该元组,并仅用一个语句返回该元组(因为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)。

相关问题 更多 >