【问题标题】:Python IP range to IP range matchPython IP范围到IP范围匹配
【发布时间】:2018-01-04 01:12:46
【问题描述】:

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

Example: 10.0.1.0/18 in 123.1.0.0/8 

如果存在,我需要它返回 True,否则返回 False。

【问题讨论】:

    标签: python ip-address


    【解决方案1】:

    从 Python 3.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 中不再存在。尽情享受吧!

    【讨论】:

    • 这仅适用于“/32”IP 不是范围。正确阅读问题
    • 感谢重叠建议,这正是我正在寻找的东西
    【解决方案2】:
    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 集合能够显示任何重叠或包含(子集/超集关系)。

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

    等等

    【讨论】:

    • 我需要一个范围不匹配第三个IP,请正确阅读问题
    • 先生:我们三个人正在尝试回答您的问题,您对我们大多数人的回答是:正确阅读问题。我可能建议这个问题可以更仔细地表述:可能有一个更具体的例子来说明“检查来自网络范围的一个 Ip 是否存在于其他 Ip 范围的子网中”的意思。这可能有助于我们所有人提供满足您需求的答案。
    • 感谢您的回答
    【解决方案3】:

    我认为question 中接受的答案应该对您有所帮助:

    如果您因任何原因无法访问此链接,这里就是答案:

    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)
    

    返回 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
    

    答案的灵感来自我链接的问题,如果它对你有用,请给人们点赞。

    【讨论】:

    • 使用 netaddr 你只能测试 "/32" Ip 你不能搜索范围到范围
    • 没问题谢谢:)
    猜你喜欢
    • 2013-04-20
    • 2011-02-11
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 2018-11-01
    • 2013-06-03
    • 2011-09-14
    • 2016-08-30
    相关资源
    最近更新 更多