Comment vérifier si une adresse IP fait partie d'un réseau en Python?

Étant donné une adresse IP (disons 192.168.0.1), comment puis-je vérifier si elle fait partie d’un réseau (disons 192.168.0.0/24) en Python ?

En utilisant ipaddress

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

Si vous souhaitez évaluer un grand nombre d’adresses IP de cette manière, vous devrez probablement calculer le masque de réseau à l’avance, comme suit

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

Ensuite, pour chaque adresse, calculez la représentation binaire à l’aide de l’une des méthodes suivantes

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]  # Seulement IPv4

Enfin, il suffit de vérifier :

in_network = (a & mask) == netw

J’aime bien utiliser netaddr pour cela :

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "192.168.0.1 se trouve bien dans 192.168.0.0/24"

La nouvelle version de netaddr fonctionne comme suit:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "192.168.0.1 se trouve bien dans 192.168.0.0/24"

Pour les utilisateur de Python3

import ipaddress
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/24')
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/16')

Sortie :

False
True

En utilisant Python >= 3.7 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}")))

Vérifier si 192.168.0.1 se trouve dans 192.168.0.0/16 est la même chose que de vérifier si 192.168.0.1/32 est un sous-réseau de 192.168.0.0/16