如何检查ip是否在Python网络中?


100

给定一个IP地址(例如192.168.0.1),如何在Python中检查它是否在网络中(例如192.168.0.0/24)?

Python中是否有用于IP地址操作的通用工具?诸如主机查找,将IP地址添加到int,将网络地址与netmask转换为int之类的东西?希望可以在标准Python库中找到2.5。


对于非常老的2.x答案,这个问题似乎可以接受,但对于3.x来说已经过时了。请参阅如何为“ Python /熊猫比较IP地址/ CIDR”组织和分配规范?
smci

@smci我不明白为什么;phihag在stackoverflow.com/a/1004527/1709587上的答案对于Python 3来说是一个很好的答案,自2014年以来一直存在。我已回滚您的编辑,使该答案无效。
Mark Amery

@Staale-您应该在此处将答案更新为没有严重错误的答案。其他答案使用内置库以1/10的代码数量完成同一件事,而没有任何错误。
艾迪生

Answers:


30

本文说明您可以使用socketstruct模块完成此操作,而无需付出太多额外的努力。我在文章中添加了一些内容,如下所示:

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)

输出:

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

8
此外,struct.unpack('L',socket.inet_aton(ip))[0]在架构上会失败,在这种架构中,“ L”解压缩为不同于4个字节的字节,无论字节序如何。
2009年

5
继续使用Rafal的评论,要使其在64位Python解释器上运行,请将问题所在的行替换为:return struct.unpack('<L',socket.inet_aton(ip))[0]
nitwit 2012年

11
我认为您的解决方案存在一个严重的错误:(addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True我在64位操作系统中将“ L”转换为“ <L”)
Taha Jahangir 2012年

20
注意:此解决方案存在一个严重的错误:addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
Taha Jahangir,2012年

6
这个答案有一个错误。见回答:stackoverflow.com/questions/819355/...
Debanshu昆都

156

我喜欢使用netaddr

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "Yay!"

正如arno_v在评论中指出的那样,新版本的netaddr这样做如下:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "Yay!"

>>> netaddr.all_matching_cidrs(“ 192.168.0.1”,[“ 192.168.0.0/24","212.11.64.0/19”])[IPNetwork('192.168.0.0/24')]

22
或在新版本中:从netaddr导入IPNetwork,在IPNetwork(“ 192.168.0.0/24”)中导入IPAddress IPAddress(“ 192.168.0.1”)
arno_v 2013年

140

使用ipaddress从3.3开始在stdlib中在2.6 / 2.7的PyPi上):

>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True

如果您想以这种方式评估很多 IP地址,则可能需要先计算网络掩码,例如

n = ipaddress.ip_network('192.0.0.0/16')
netw = int(n.network_address)
mask = int(n.netmask)

然后,对于每个地址,使用以下任一方法计算二进制表示形式

a = int(ipaddress.ip_address('192.0.43.10'))
a = struct.unpack('!I', socket.inet_pton(socket.AF_INET, '192.0.43.10'))[0]
a = struct.unpack('!I', socket.inet_aton('192.0.43.10'))[0]  # IPv4 only

最后,您可以简单地检查:

in_network = (a & mask) == netw

2
当心,python-ipaddr对我们而言表现得很慢,因此在某些经常需要大量比较的情况下可能不合适。YMMV,所以请对自己进行基准测试。
drdaeman 2012年

在某些版本中,您可能需要提供unicode字符串而不是Python str类型,例如ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
Moondoggy

1
我担心该方法正在网络中的地址列表上进行迭代,但是ipaddress模块__contains__通过比较网络和广播地址的整数表示来覆盖该方法以有效地实现该方法,因此请放心,如果您担心。
avatarofhope2 '18


10

这段代码在Linux x86上对我有用。我还没有真正考虑到持久性问题,但是我已经对“ ipaddr”模块进行了测试,该模块使用了针对8个不同网络字符串测试的200K IP地址,并且ipaddr的结果与此代码相同。

def addressInNetwork(ip, net):
   import socket,struct
   ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
   netstr, bits = net.split('/')
   netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
   mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
   return (ipaddr & mask) == (netaddr & mask)

例:

>>> print addressInNetwork('10.9.8.7', '10.9.1.0/16')
True
>>> print addressInNetwork('10.9.8.7', '10.9.1.0/24')
False

好又快。不需要一些简单逻辑操作的库。
克里斯·科斯顿

7

使用Python3 ipaddress

import ipaddress

address = ipaddress.ip_address("192.168.0.1")
network = ipaddress.ip_network("192.168.0.0/16")

print(network.supernet_of(ipaddress.ip_network(f"{address}/{address.max_prefixlen}")))

说明

你可以把的IP地址作为网络具有最大可能子网掩码(/32对于IPv4,/128IPv6的)

检查是否192.168.0.1192.168.0.0/16本质上与检查是否192.168.0.1/32是的子网相同192.168.0.0/16


...不确定此答案为何不在顶部(尚未)。
Filippo Vitale

6

我尝试了Dave Webb的解决方案,但遇到了一些问题:

最根本的是-应该通过将IP地址与掩码进行“与”运算来检查匹配项,然后检查结果是否与网络地址完全匹配。请勿将IP地址与网络地址进行与操作。

我还注意到,仅假设一致性会节省您的时间,就忽略Endian行为,仅适用于八位位组边界(/ 24,/ 16)上的掩码。为了使其他掩码(/ 23,/ 21)正常工作,我在struct命令中添加了“大于”,并更改了用于创建二进制掩码的代码,使其以全“ 1”开头并向左移动(32-mask )。

最后,我添加了一个简单的检查,检查网络地址对于掩码是否有效,如果无效,则仅打印警告。

结果如下:

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]
    ipaddr_masked = ipaddr & (4294967295<<(32-int(bits)))   # Logical AND of IP address and mask will equal the network address if it matches
    if netmask == netmask & (4294967295<<(32-int(bits))):   # Validate network address is valid for mask
            return ipaddr_masked == netmask
    else:
            print "***WARNING*** Network",netaddr,"not valid with mask /"+bits
            return ipaddr_masked == netmask

这似乎可以在64位上可靠地工作(“ L”失败,因为值是32位),并以合理的顺序返回值(对于ipd192.168.0.1,ipaddr将为0xC0A80001)。它还应对“ 192.168.0.1/24”作为“ 192.168.0.1”的网络掩码(不是标准的,但可能且易于纠正)
IBBoard 2012年

在Python 2.4上完美工作
xlash

6

我不喜欢在不需要模块时使用它们。这项工作仅需要简单的数学运算,因此这是我执行该工作的简单函数:

def ipToInt(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res

def isIpInSubnet(ip, ipNetwork, maskLength):
    ipInt = ipToInt(ip)#my test ip, in int form

    maskLengthFromRight = 32 - maskLength

    ipNetworkInt = ipToInt(ipNetwork) #convert the ip network into integer form
    binString = "{0:b}".format(ipNetworkInt) #convert that into into binary (string format)

    chopAmount = 0 #find out how much of that int I need to cut off
    for i in range(maskLengthFromRight):
        if i < len(binString):
            chopAmount += int(binString[len(binString)-1-i]) * 2**i

    minVal = ipNetworkInt-chopAmount
    maxVal = minVal+2**maskLengthFromRight -1

    return minVal <= ipInt and ipInt <= maxVal

然后使用它:

>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',24) 
True
>>> print isIpInSubnet('66.151.97.193', '66.151.97.192',29) 
True
>>> print isIpInSubnet('66.151.96.0', '66.151.97.192',24) 
False
>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',29) 

就是这样,这比包含模块的上述解决方案要快得多。


{TypeError}'map' object is not subscriptable。您需要o = list(o)之后o = map(int, ip.split('.'))
gies0r

5

2.5版的标准库中没有此文件,但是ipaddr使此操作非常容易。我相信它是在3.3下的ipaddress名称。

import ipaddr

a = ipaddr.IPAddress('192.168.0.1')
n = ipaddr.IPNetwork('192.168.0.0/24')

#This will return True
n.Contains(a)

在这里的所有众多选择中,这是我最喜欢的(在发表评论时,2017年)。谢谢!
rsaw

5

公认的答案不起作用...这让我很生气。掩码是向后的,不适用于不是简单8位块的任何位(例如/ 24)。我修改了答案,效果很好。

    import socket,struct

    def addressInNetwork(ip, net_n_bits):  
      ipaddr = struct.unpack('!L', socket.inet_aton(ip))[0]
      net, bits = net_n_bits.split('/')
      netaddr = struct.unpack('!L', socket.inet_aton(net))[0]
      netmask = (0xFFFFFFFF >> int(bits)) ^ 0xFFFFFFFF
      return ipaddr & netmask == netaddr

这是一个返回点分二进制字符串以帮助可视化遮罩的函数ipcalc

    def bb(i):
     def s = '{:032b}'.format(i)
     def return s[0:8]+"."+s[8:16]+"."+s[16:24]+"."+s[24:32]

例如:

python的屏幕截图


4

马克的代码几乎是正确的。该代码的完整版本是-

def addressInNetwork3(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(int(bits))))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-mask,32):
        bits |= (1 << i)
    return "%d.%d.%d.%d" % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

显然来自与上述相同的来源...

一个非常重要的注意事项是,第一个代码有一个小故障-IP地址255.255.255.255也显示为任何子网的有效IP。我花了点时间使这段代码能够正常工作,感谢Marc的正确回答。


尝试和测试。从本页上的所有套接字/结构示例中,这是唯一正确的示例
Zabuzzman

4

依靠“结构”模块可能会导致字节序和类型大小方面的问题,而这并不是必需的。socket.inet_aton()也不是。Python可与点分四进制IP地址配合使用:

def ip_to_u32(ip):
  return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)

我需要针对每个允许的源网络对每个套接字accept()调用进行IP匹配,因此我将掩码和网络预先计算为整数:

SNS_SOURCES = [
  # US-EAST-1
  '207.171.167.101',
  '207.171.167.25',
  '207.171.167.26',
  '207.171.172.6',
  '54.239.98.0/24',
  '54.240.217.16/29',
  '54.240.217.8/29',
  '54.240.217.64/28',
  '54.240.217.80/29',
  '72.21.196.64/29',
  '72.21.198.64/29',
  '72.21.198.72',
  '72.21.217.0/24',
  ]

def build_masks():
  masks = [ ]
  for cidr in SNS_SOURCES:
    if '/' in cidr:
      netstr, bits = cidr.split('/')
      mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
      net = ip_to_u32(netstr) & mask
    else:
      mask = 0xffffffff
      net = ip_to_u32(cidr)
    masks.append((mask, net))
  return masks

然后,我可以快速查看给定的IP是否在这些网络之一内:

ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
  if ip & mask == net:
    # matched!
    break
else:
  raise BadClientIP(ipstr)

无需导入模块,并且代码匹配非常快。


这个cached_masks是指什么?
ajin

2

从netaddr import all_matching_cidrs

>>> from netaddr import all_matching_cidrs
>>> all_matching_cidrs("212.11.70.34", ["192.168.0.0/24","212.11.64.0/19"] )
[IPNetwork('212.11.64.0/19')]

这是此方法的用法:

>>> help(all_matching_cidrs)

Help on function all_matching_cidrs in module netaddr.ip:

all_matching_cidrs(ip, cidrs)
    Matches an IP address or subnet against a given sequence of IP addresses and subnets.

    @param ip: a single IP address or subnet.

    @param cidrs: a sequence of IP addresses and/or subnets.

    @return: all matching IPAddress and/or IPNetwork objects from the provided
    sequence, an empty list if there was no match.

基本上,您提供一个ip地址作为第一个参数,并提供一个cidrs列表作为第二个参数。返回命中列表。


2
#这可以正常工作,而不会处理逐字节的怪异
def addressInNetwork(ip,net):
    '''是网络中的地址'''
    #将地址转换为主机顺序,因此转移实际上很有意义
    ip = struct.unpack('> L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netaddr = struct.unpack('> L',socket.inet_aton(netaddr))[0]
    #必须向左移一个全数值,/ 32 =零移,/ 0 =向左移32
    网络掩码=(0xffffffff <<(32-int(bits)))&0xffffffff
    #无需屏蔽网络地址,只要它是正确的网络地址即可
    return(ip&netmask)== netaddr 

由于netmask值不正确,该代码在64位OS上无法正常工作。我已经采取了修复措施。
drdaeman 2012年

2

先前的解决方案在ip&net == net中存在错误。正确的ip查找是ip&netmask = net

错误修正的代码:

import socket
import 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 addressInNetwork(ip,net,netmask):
   "Is an address in a network"
   print "IP "+str(ip) + " NET "+str(net) + " MASK "+str(netmask)+" AND "+str(ip & netmask)
   return ip & netmask == net

def humannetcheck(ip,net):
        address=dottedQuadToNum(ip)
        netaddr=dottedQuadToNum(net.split("/")[0])
        netmask=makeMask(long(net.split("/")[1]))
        return addressInNetwork(address,netaddr,netmask)


print humannetcheck("192.168.0.1","192.168.0.0/24");
print humannetcheck("192.169.0.1","192.168.0.0/24");

2

选择的答案有错误。

以下是正确的代码:

def addressInNetwork(ip, net_n_bits):
   ipaddr = struct.unpack('<L', socket.inet_aton(ip))[0]
   net, bits = net_n_bits.split('/')
   netaddr = struct.unpack('<L', socket.inet_aton(net))[0]
   netmask = ((1L << int(bits)) - 1)
   return ipaddr & netmask == netaddr & netmask

注意:ipaddr & netmask == netaddr & netmask代替ipaddr & netmask == netmask

我也替换((2L<<int(bits)-1) - 1)((1L << int(bits)) - 1),因为后者似乎更容易理解。


我认为掩码转换((2L<<int(bits)-1) - 1)是正确的。例如,如果掩码为16,则应为“ 255.255.0.0”或65535L,但((1L << int(bits)) - 1)将得到32767L,这是不正确的。
Chris.Q 2015年

@ Chris.Q,((1L << int(bits)) - 1)在我的系统上给出65535L,bits设置为16!
Debanshu Kundu 2015年

另外,对于bits设置为0((2L<<int(bits)-1) - 1)会引发错误。
Debanshu Kundu 2015年

是的,除/ 0,/ 8,/ 16,/ 32以外的其他值均不能正常工作。
Debanshu Kundu

2

这是我为最长的前缀匹配编写的一个类:

#!/usr/bin/env python

class Node:
def __init__(self):
    self.left_child = None
    self.right_child = None
    self.data = "-"

def setData(self, data): self.data = data
def setLeft(self, pointer): self.left_child = pointer
def setRight(self, pointer): self.right_child = pointer
def getData(self): return self.data
def getLeft(self): return self.left_child
def getRight(self): return self.right_child

def __str__(self):
        return "LC: %s RC: %s data: %s" % (self.left_child, self.right_child, self.data)


class LPMTrie:      

def __init__(self):
    self.nodes = [Node()]
    self.curr_node_ind = 0

def addPrefix(self, prefix):
    self.curr_node_ind = 0
    prefix_bits = ''.join([bin(int(x)+256)[3:] for x in prefix.split('/')[0].split('.')])
    prefix_length = int(prefix.split('/')[1])
    for i in xrange(0, prefix_length):
        if (prefix_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setRight(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setLeft(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)

        if i == prefix_length - 1 :
            self.nodes[self.curr_node_ind].setData(prefix)

def searchPrefix(self, ip):
    self.curr_node_ind = 0
    ip_bits = ''.join([bin(int(x)+256)[3:] for x in ip.split('.')])
    for i in xrange(0, 32):
        if (ip_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                return self.nodes[self.curr_node_ind].getData()
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                return self.nodes[self.curr_node_ind].getData()

    return None

def triePrint(self):
    n = 1
    for i in self.nodes:
        print n, ':'
        print i
        n += 1

这是一个测试程序:

n=LPMTrie()
n.addPrefix('10.25.63.0/24')
n.addPrefix('10.25.63.0/16')
n.addPrefix('100.25.63.2/8')
n.addPrefix('100.25.0.3/16')
print n.searchPrefix('10.25.63.152')
print n.searchPrefix('100.25.63.200')
#10.25.63.0/24
#100.25.0.3/16

1

谢谢您的脚本!
为了使所有功能正常工作,我做了很长的工作...所以我在这里分享

  • 使用netaddr类比使用二进制转换要慢10倍,因此,如果要在大量IP上使用它,则应考虑不使用netaddr类
  • makeMask函数不起作用!仅适用于/ 8,/ 16,/ 24
    Ex:

    位=“ 21”;socket.inet_ntoa(struct.pack('= L',(2L << int(bits)-1)-1))
    '255.255.31.0'而应为255.255.248.0

    所以我从http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/ 使用了另一个函数calcDottedNetmask(mask)


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • 另一个问题是IP是否属于网络的匹配过程!基本操作应该是比较(ipaddr&netmask)和(network&netmask)。
    例如:暂时,该功能有误

#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
>>>True which is completely WRONG!!

所以我的新addressInNetwork函数看起来像:


#!/usr/bin/python
import socket,struct
def addressInNetwork(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(bits)))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-int(mask),32):
        bits |= (1 > 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

现在,答案是正确的!


#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
False

我希望它可以帮助其他人,为他们节省时间!


1
上面代码的当前版本在最后一行提供了回溯,您可以“ | =”一个int和一个元组。
肖恩·赖夫施奈德

1

关于以上所有内容,我认为socket.inet_aton()以网络顺序返回字节,因此解压缩它们的正确方法可能是

struct.unpack('!L', ... )

1
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('/')
    netaddr = struct.unpack('!L',socket.inet_aton(netaddr))[0]
    netmask = ((1<<(32-int(bits))) - 1)^0xffffffff
    return ipaddr & netmask == netaddr & netmask
print addressInNetwork('10.10.10.110','10.10.10.128/25')
print addressInNetwork('10.10.10.110','10.10.10.0/25')
print addressInNetwork('10.10.10.110','10.20.10.128/25')

$ python check-subnet.py
False

False


您能解释一下您在已经给出的答案中添加了什么吗?
David Guyon

给定的答案存在一些问题,无法解决CIDR。我只是更改了IP地址的字节顺序。就像这样:>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
约翰逊

1
感谢你的回答。我想这是您应该添加到答案中以进行澄清的内容。解释“什么”,“为什么”,最后是“如何”是StackOverflow的精神。您的答案仅包含“如何” :( ..我让您通过编辑来完成您的答案;)。
David Guyon


0

从上面的各种来源以及我自己的研究,这就是我使子网和地址计算工作的方式。这些片段足以解决问题和其他相关问题。

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

    @staticmethod
    def numToDottedQuad(n):
        "convert long int to dotted quad string"
        return socket.inet_ntoa(struct.pack('>L', n))

    @staticmethod
    def makeNetmask(mask):
        bits = 0
        for i in xrange(32-int(mask), 32):
            bits |= (1 << i)
        return bits

    @staticmethod
    def ipToNetAndHost(ip, maskbits):
        "returns tuple (network, host) dotted-quad addresses given"
        " IP and mask size"
        # (by Greg Jorgensen)
        n = iptools.dottedQuadToNum(ip)
        m = iptools.makeMask(maskbits)
        net = n & m
        host = n - mask
        return iptools.numToDottedQuad(net), iptools.numToDottedQuad(host)

0

在python中有一个称为SubnetTree的API可以很好地完成这项工作。这是一个简单的例子:

import SubnetTree
t = SubnetTree.SubnetTree()
t.insert("10.0.1.3/32")
print("10.0.1.3" in t)

这是链接


0

这是我的代码

# -*- coding: utf-8 -*-
import socket


class SubnetTest(object):
    def __init__(self, network):
        self.network, self.netmask = network.split('/')
        self._network_int = int(socket.inet_aton(self.network).encode('hex'), 16)
        self._mask = ((1L << int(self.netmask)) - 1) << (32 - int(self.netmask))
        self._net_prefix = self._network_int & self._mask

    def match(self, ip):
        '''
        判断传入的 IP 是不是本 Network 内的 IP
        '''
        ip_int = int(socket.inet_aton(ip).encode('hex'), 16)
        return (ip_int & self._mask) == self._net_prefix

st = SubnetTest('100.98.21.0/24')
print st.match('100.98.23.32')

0

如果您不想导入其他模块,可以使用:

def ip_matches_network(self, network, ip):
    """
    '{:08b}'.format(254): Converts 254 in a string of its binary representation

    ip_bits[:net_mask] == net_ip_bits[:net_mask]: compare the ip bit streams

    :param network: string like '192.168.33.0/24'
    :param ip: string like '192.168.33.1'
    :return: if ip matches network
    """
    net_ip, net_mask = network.split('/')
    net_mask = int(net_mask)
    ip_bits = ''.join('{:08b}'.format(int(x)) for x in ip.split('.'))
    net_ip_bits = ''.join('{:08b}'.format(int(x)) for x in net_ip.split('.'))
    # example: net_mask=24 -> compare strings at position 0 to 23
    return ip_bits[:net_mask] == net_ip_bits[:net_mask]

0

我在这些答案中尝试了一个提议的解决方案的子集..没有成功,我终于修改并修复了提议的代码并编写了我的固定函数。

我对其进行了测试,并且至少在小型字节序体系结构(egx86)上工作,如果有人喜欢尝试大型字节序体系结构,请给我反馈。

IP2Int代码来自此帖子,另一种方法是此问题中先前提议的完全(对于我的测试用例)可行的修复方法。

代码:

def IP2Int(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res


def addressInNetwork(ip, net_n_bits):
    ipaddr = IP2Int(ip)
    net, bits = net_n_bits.split('/')
    netaddr = IP2Int(net)
    bits_num = int(bits)
    netmask = ((1L << bits_num) - 1) << (32 - bits_num)
    return ipaddr & netmask == netaddr & netmask

希望有用,


0

这是使用netaddr软件包的解决方案

from netaddr import IPNetwork, IPAddress


def network_has_ip(network, ip):

    if not isinstance(network, IPNetwork):
        raise Exception("network parameter must be {0} instance".format(IPNetwork.__name__))

    if not isinstance(ip, IPAddress):
        raise Exception("ip parameter must be {0} instance".format(IPAddress.__name__))

    return (network.cidr.ip.value & network.netmask.value) == (ip.value & network.netmask.value)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.