web-dev-qa-db-fra.com

Comment puis-je vérifier si une adresse IP est dans un réseau en Python?

Étant donné une adresse IP (par exemple 192.168.0.1), comment puis-je vérifier si elle est dans un réseau (par exemple 192.168.0.0/24) en Python?

Existe-t-il des outils généraux en Python pour la manipulation des adresses IP? Des trucs comme des recherches d’hôte, une adresse IP à int, une adresse réseau avec un masque de réseau à int, etc.? Espérons que dans la bibliothèque standard Python pour 2.5.

80
Staale

Cet article montre que vous pouvez le faire avec socket et struct modules sans effort supplémentaire. J'ai ajouté un peu à l'article comme suit:

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)

Cela génère:

False
True

Si vous voulez juste une seule fonction qui prend des chaînes, cela ressemblerait à ceci:

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
31
Dave Webb

J'aime utiliser netaddr pour cela:

from netaddr import CIDR, IP

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

Comme arno_v l'a souligné dans les commentaires, la nouvelle version de netaddr le fait comme ceci:

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

Utilisation de ipaddress ( dans la bibliothèque stdlib depuis 3.3 , sous PyPi pour 2.6/2.7 ):

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

Si vous voulez évaluer un lot d'adresses IP de cette façon, vous voudrez probablement calculer le masque de réseau à l'avance, comme

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

Puis, pour chaque adresse, calcule la représentation binaire avec l’un des suivants:

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

Enfin, vous pouvez simplement vérifier:

in_network = (a & mask) == netw
101
phihag

Ce code fonctionne pour moi sur Linux x86. Je n'ai pas vraiment réfléchi aux problèmes de finalité, mais je l'ai testé avec le module "ipaddr" en utilisant plus de 200K adresses IP testées avec 8 chaînes de réseau différentes, et les résultats de ipaddr sont identiques à ce code.

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)

Exemple:

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

Pour python3

In [64]: ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/24')
Out[64]: False
6
okwap

Je ne suis pas fan de l'utilisation de modules quand ils ne sont pas nécessaires. Ce travail nécessite seulement des calculs simples, voici donc ma fonction simple pour faire le travail:

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

Puis l'utiliser:

>>> 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) 

Ça y est, c'est beaucoup plus rapide que les solutions ci-dessus avec les modules inclus.

6
Landon

J'ai essayé la solution de Dave Webb mais j'ai rencontré quelques problèmes:

Fondamentalement, une correspondance doit être vérifiée en effectuant une opération ET entre l'adresse IP et le masque, puis en vérifiant que le résultat correspond exactement à l'adresse réseau. Pas ANDing l'adresse IP avec l'adresse réseau comme cela a été fait.

J'ai aussi remarqué que le fait d'ignorer le comportement Endian en supposant que la cohérence vous évitera ne fonctionnera que pour les masques situés sur les limites des octets (/ 24,/16). Pour que d’autres masques (/ 23,/21) fonctionnent correctement, j’ai ajouté un "supérieur à" aux commandes de struct, puis modifié le code permettant de créer le masque binaire de manière à ce que tous les "1" soient décalés à gauche (32-mask). ). 

Enfin, j'ai ajouté une simple vérification de la validité de l'adresse réseau pour le masque et simplement imprimer un avertissement si ce n'est pas le cas.

Voici le résultat:

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
6
Paul McDonnell

La réponse acceptée ne fonctionne pas ... ce qui me met en colère. Le masque est à l'envers et ne fonctionne avec aucun bit qui ne soit pas un simple bloc de 8 bits (par exemple/24) J'ai adapté la réponse et cela fonctionne bien.

    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

voici une fonction qui retourne une chaîne binaire en pointillés pour aider à visualiser le masquage .. un peu comme la sortie ipcalc.

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

par exemple:

screen shot of python

5
jorb

Le code de Marc est presque correct. Une version complète du code est -

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))

Évidemment, à partir des mêmes sources que ci-dessus ...

Une remarque très importante est que le premier code a un petit problème - L'adresse IP 255.255.255.255 apparaît également comme adresse IP valide pour tout sous-réseau. J'ai passé énormément de temps à faire fonctionner ce code et merci à Marc pour la bonne réponse.

4
Nitin Khanna

Pas dans la bibliothèque Standard pour 2.5, mais ipaddr rend cela très facile. Je crois que c'est en 3.3 sous le nom 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)
4
James Robinson

S'appuyer sur le module "struct" peut poser des problèmes d'endurance et de tailles de caractères, ce qui n'est pas nécessaire. Socket.inet_aton () non plus. Python fonctionne très bien avec les adresses IP en pointillés:

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

Je dois effectuer une correspondance IP sur chaque appel accept () du socket, par rapport à tout un ensemble de réseaux sources autorisés. Par conséquent, je pré-calcule les masques et les réseaux en tant qu'entiers:

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

Ensuite, je peux rapidement voir si une adresse IP donnée se trouve dans l'un de ces réseaux:

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

Aucune importation de module requise et le code est très rapide à la correspondance.

3
gstein

La réponse choisie a un bug.

Voici le code correct:

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

Remarque: ipaddr & netmask == netaddr & netmask au lieu de ipaddr & netmask == netmask

Je remplace également ((2L<<int(bits)-1) - 1) par ((1L << int(bits)) - 1), car ce dernier semble plus compréhensible.

2
Debanshu Kundu

Voici une classe que j'ai écrite pour la correspondance du préfixe le plus long:

#!/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

Et voici un programme de test:

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
2
Amir
 # Ceci fonctionne correctement sans la gestion bizarre octet par octet 
 Def addressInNetwork (ip, net): 
 '' 'Est-ce une adresse dans un réseau' ''. # Convertir les adresses en ordre d'hôte, les changements ont donc du sens 
 ip = struct.unpack ('> L', socket.inet_aton (ip)) [0] 
 netaddr, bits = net.split ('/')
 netaddr = struct.unpack ('> L', socket.inet_aton (netaddr)) [0] 
 # Doit décaler à gauche toutes les valeurs,/32 = décalage à zéro,/0 = 32 décalage à gauche 
 masque de réseau = (0xffffffff & lt & lt (32-int (bits))) & 0xffffffff 
 # Il n’est pas nécessaire de masquer l’adresse réseau tant que cette adresse est correcte 
 return (ip & netmask) == netaddr 
2
Marcelo Pacheco

depuis 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')]

Voici l'utilisation de cette méthode:

>>> 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.

Fondamentalement, vous fournissez une adresse IP comme premier argument et une liste de cidrs comme second argument. Une liste des hits sont retournés.

2
user221014

Merci pour votre script!
J'ai beaucoup travaillé dessus pour que tout fonctionne ... Alors je le partage ici

  • L'utilisation de netaddr Class est 10 fois plus lente que celle de la conversion binaire. Si vous souhaitez l'utiliser sur une grande liste d'adresses IP, vous devriez envisager de ne pas utiliser la classe netaddr.
  • la fonction makeMask ne fonctionne pas! Ne travaille que pour/8,/16,/24 
    Ex:

    bits = "21"; socket.inet_ntoa (struct.pack ('= L', (2L << int (bits) -1) - 1))
    '255.255.31.0' alors qu'il devrait être 255.255.248.0

    J'ai donc utilisé une autre fonction calcDottedNetmask (masque) de http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
    Ex:


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • Un autre problème est le processus de mise en correspondance si une IP appartient à un réseau! Les opérations de base doivent consister à comparer (ipaddr & netmask) et (network & netmask).
    Ex: pour le moment, la fonction est fausse

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

Donc, ma nouvelle fonction addressInNetwork ressemble à ceci:


#!/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))


Et maintenant, la réponse est juste !!


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

J'espère que cela aidera d'autres personnes en leur faisant gagner du temps!

1
Marc Leurent
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
Faux
Vrai
Faux

1
Johnson

Je ne connais rien dans la bibliothèque standard, mais PySubnetTree est une bibliothèque Python qui fera la correspondance de sous-réseau.

1
RichieHindle

Il existe une API appelée SubnetTree disponible en python qui fait très bien ce travail. Voici un exemple simple: 

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

Voici le lien

1
salaheddine

la solution précédente a un bug dans ip & net == net. La recherche ip correcte est ip & netmask = net

code corrigé:

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");
1
user3265849

En ce qui concerne tout ce qui précède, je pense que socket.inet_aton () renvoie les octets dans l’ordre du réseau;

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

Voici mon code

# -*- 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
ruohanc

J'ai essayé un sous-ensemble de solutions proposées dans ces réponses .. sans succès, j'ai finalement adapté et corrigé le code proposé et écrit ma fonction fixe. 

Je l'ai testé et fonctionne au moins sur les architectures Endian peu développées - par exemple, x86 - si quelqu'un aime essayer une architecture big endian, donnez-moi s'il vous plaît des informations.

IP2Int code provient de this post , l’autre méthode est un correctif de travail complet (pour mes cas de test) des propositions précédentes de cette question. 

Le code:

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

J'espère utile,

0
Fabiano Tarlao

De différentes sources ci-dessus et de mes propres recherches, voici comment j'ai obtenu le calcul de sous-réseau et d'adresse. Ces pièces sont suffisantes pour résoudre la question et d’autres questions connexes.

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
Nathan Garabedian

Si vous ne souhaitez pas importer d'autres modules, vous pouvez utiliser:

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
Benny93