Python IP 范围与 IP 范围匹配

Python IP range to IP range match

有什么方法可以检查一个网络范围内的某些 IP 地址是否存在于另一个 IP 范围的子网中?

Example: 10.0.1.0/18 in 123.1.0.0/8 

如果存在,我需要它return True,否则为 False。

我认为这个question中接受的答案应该对你有帮助:

如果您出于任何原因无法参加link,答案如下:

import socket,struct

def makeMask(n):
    "return a mask of n bits as a long integer"
    return (2L<<n-1) - 1

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def networkMask(ip,bits):
    "Convert a network address to a long integer" 
    return dottedQuadToNum(ip) & makeMask(bits)

def addressInNetwork(ip,net):
   "Is an address in a network"
   return ip & net == net

address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)

Return True 或 False(在示例中,首先是 False,然后是 True)。

或在一个函数中:

import socket,struct

def addressInNetwork(ip,net):
   "Is an address in a network"
   ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
   netaddr,bits = net.split('/')
   netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
   return ipaddr & netmask == netmask

答案受到我 link 提出的问题的启发,如果它对你有用,请给人们点赞。

从Python3.3开始,可以使用标准库的ipaddress模块:

from ipaddress import IPv4Address, IPv4Network

IPv4Address('192.0.2.6') in IPv4Network('192.0.2.0/28')
# True
IPv4Address('10.0.1.0') in IPv4Network('192.0.2.0/28')
# False

如果你的意思是如果网络重叠,使用overlaps:

In [14]: IPv4Network('10.0.1.0/24').overlaps(IPv4Network('192.0.2.0/28'))
Out[14]: False

请注意,此模块在 Python 3.3 中标记为临时模块,但在 3.6 中不再存在。好好享受吧!

from ipaddress import ip_address, ip_network

注意:其他答案具体指向 IPv4Address、IPv4Network,但 ip_address 和 ip_network 只需在需要时调用 IPv4 或 IPv6 版本。

addr = ip_address('10.0.1.0')

注意:您提供的示例网络不是真正的 /8 网络,因此 ip_network 将响应 ValueError: 123.1.0.0/8 has host bits set

错误

为了解决这个问题,通过强制 ipaddress 库基本上向下舍入到最近的网络地址,您可以设置 strict=False 并且 Python 将找到最近的、较低的地址 /8网络:123.0.0.0

netw = ip_network('123.1.0.0/8', strict=False)

print(addr in netw)

那么就只需要使用in关键字进行测试了。

如果要针对另一个网络范围内的每个地址测试网络范围内的每个地址,则:

net1 = ip_network('10.0.1.0/18', strict=False)
net2 = ip_network('123.1.0.0/8', strict=False)

for addr in net1:
    if addr in net2:
        print(addr, 'True')
    else:
        print(addr, 'False')

此外,网络可以转化为集合:

n1 = set(net1)
n2 = set(net2)

并且 Python 集能够显示任何重叠或包含(subset/superset 关系)。

n1.isdisjoint(n2)
n1.issubset(n2)
n2.issubset(n1)
n2.issuperset(n1)

等等