Étant donné une adresse IP (par exemple 192.168.0.1), comment puis-je vérifier si elle se trouve 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 d'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 et ainsi de suite? Espérons que dans la bibliothèque Python standard pour 2.5.
python
networking
ip-address
cidr
Staale
la source
la source
Réponses:
Cet article montre que vous pouvez le faire avec
socket
et desstruct
modules sans trop d'effort supplémentaire. J'ai ajouté un peu à l'article comme suit:Cela produit:
Si vous voulez juste une seule fonction qui prend des chaînes, cela ressemblerait à ceci:
la source
return struct.unpack('<L',socket.inet_aton(ip))[0]
addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
(j'ai converti 'L' en '<L' dans mon système d'exploitation 64 bits)addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
J'aime utiliser netaddr pour cela:
Comme arno_v l'a souligné dans les commentaires, la nouvelle version de netaddr le fait comme ceci:
la source
En utilisant ipaddress ( dans le stdlib depuis 3.3 , chez PyPi pour 2.6 / 2.7 ):
Si vous souhaitez évaluer un grand nombre d'adresses IP de cette façon, vous voudrez probablement calculer le masque de réseau à l'avance, comme
Ensuite, pour chaque adresse, calculez la représentation binaire avec l'un des
Enfin, vous pouvez simplement vérifier:
la source
ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
.__contains__
méthode pour le faire de manière efficace en comparant les représentations entières du réseau et des adresses de diffusion, alors soyez assuré si c'était votre souci .Pour python3
Production :
la source
Ce code fonctionne pour moi sous Linux x86. Je n'ai pas vraiment réfléchi aux problèmes d'endianess, mais je l'ai testé contre le module "ipaddr" en utilisant plus de 200K adresses IP testées sur 8 chaînes réseau différentes, et les résultats d'ipaddr sont les mêmes que ce code.
Exemple:
la source
Utilisation de l'adresse IP Python3 :
Explication
Vous pouvez considérer une adresse IP comme un réseau avec le plus grand masque de réseau possible (
/32
pour IPv4,/128
pour IPv6)Vérifier si
192.168.0.1
est dans192.168.0.0/16
est essentiellement la même que vérifier s'il192.168.0.1/32
s'agit d'un sous-réseau de192.168.0.0/16
la source
J'ai essayé la solution de Dave Webb mais j'ai rencontré des problèmes:
Plus fondamentalement, une correspondance doit être vérifiée en associant l'adresse IP avec le masque, puis en vérifiant que le résultat correspond exactement à l'adresse réseau. Ne pas ANDing l'adresse IP avec l'adresse réseau comme cela a été fait.
J'ai également remarqué que le simple fait d'ignorer le comportement Endian en supposant que la cohérence vous sauvera ne fonctionnera que pour les masques sur les limites d'octets (/ 24, / 16). Afin de faire fonctionner correctement les autres masques (/ 23, / 21), j'ai ajouté un "supérieur à" aux commandes struct et j'ai changé le code de création du masque binaire pour qu'il commence par tout "1" et décale à gauche de (32-mask ).
Enfin, j'ai ajouté une simple vérification que l'adresse réseau est valide pour le masque et j'ai simplement imprimé un avertissement si ce n'est pas le cas.
Voici le résultat:
la source
Je ne suis pas fan de l'utilisation de modules lorsqu'ils ne sont pas nécessaires. Ce travail ne nécessite que de simples calculs, voici donc ma fonction simple pour faire le travail:
Alors pour l'utiliser:
Voilà, c'est beaucoup plus rapide que les solutions ci-dessus avec les modules inclus.
la source
{TypeError}'map' object is not subscriptable
. Vous avez besoin d'uno = list(o)
aprèso = map(int, ip.split('.'))
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.
la source
La réponse acceptée ne fonctionne pas ... ce qui me met en colère. Le masque est à l'envers et ne fonctionne pas avec des bits qui ne sont pas un simple bloc de 8 bits (par exemple / 24). J'ai adapté la réponse et cela fonctionne bien.
voici une fonction qui renvoie une chaîne binaire en pointillé pour aider à visualiser le masquage .. un peu comme une
ipcalc
sortie.par exemple:
la source
Le code de Marc est presque correct. Une version complète du code est -
Evidemment des mêmes sources que ci-dessus ...
Une note très importante est que le premier code a un petit problème - L'adresse IP 255.255.255.255 apparaît également comme une adresse IP valide pour n'importe quel sous-réseau. J'ai eu beaucoup de temps à faire fonctionner ce code et merci à Marc pour la bonne réponse.
la source
Se fier au module "struct" peut causer des problèmes avec les tailles d'endian-ness et de type, et n'est tout simplement pas nécessaire. Socket.inet_aton () non plus. Python fonctionne très bien avec les adresses IP à quatre points:
Je dois faire une correspondance IP sur chaque appel de socket accept (), contre un ensemble complet de réseaux source autorisés, donc je précalcule les masques et les réseaux, sous forme d'entiers:
Ensuite, je peux voir rapidement si une adresse IP donnée se trouve dans l'un de ces réseaux:
Aucune importation de module n'est nécessaire et le code est très rapide à faire correspondre.
la source
depuis netaddr import all_matching_cidrs
Voici l'utilisation de cette méthode:
En gros, vous fournissez une adresse IP comme premier argument et une liste de cidrs comme deuxième argument. Une liste de résultats est renvoyée.
la source
la source
netmask
valeurs incorrectes . J'ai pris la liberté de résoudre ce problème.la solution précédente a un bogue dans ip & net == net. La recherche d'IP correcte est ip & netmask = net
code corrigé:
la source
La réponse choisie a un bug.
Voici le code correct:
Remarque:
ipaddr & netmask == netaddr & netmask
au lieu deipaddr & netmask == netmask
.Je remplace également
((2L<<int(bits)-1) - 1)
par((1L << int(bits)) - 1)
, car ce dernier semble plus compréhensible.la source
((2L<<int(bits)-1) - 1)
est correcte. par exemple, si le masque est 16, il devrait être "255.255.0.0" ou 65535L, mais((1L << int(bits)) - 1)
obtiendra 32767L, ce qui n'est pas correct.((1L << int(bits)) - 1)
donne 65535L sur mon système, avec une valeurbits
de 16 !!bits
définir sur0
,((2L<<int(bits)-1) - 1)
génère une erreur.Voici une classe que j'ai écrite pour la correspondance de préfixe la plus longue:
Et voici un programme de test:
la source
Merci pour votre script!
J'ai beaucoup de travail dessus pour que tout fonctionne ... Donc je le partage ici
La fonction makeMask ne fonctionne pas! Fonctionne uniquement pour / 8, / 16, / 24
Ex:
J'ai donc utilisé une autre fonction calcDottedNetmask (mask) de http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
Ex:
Ex: pour le moment, la fonction est fausse
Donc, ma nouvelle fonction addressInNetwork ressemble à:
Et maintenant, la réponse est juste !!
J'espère que cela aidera d'autres personnes, leur faisant gagner du temps!
la source
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, donc la bonne façon de les décompresser est probablement
la source
$ python check-subnet.py
Faux
Vrai
Faux
la source
>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
Je ne sais rien de la bibliothèque standard, mais PySubnetTree est une bibliothèque Python qui fera la correspondance de sous-réseau.
la source
À partir de diverses sources ci-dessus et de mes propres recherches, c'est ainsi que j'ai fait fonctionner le calcul de sous-réseau et d'adresse. Ces pièces suffisent à résoudre la question et d'autres questions connexes.
la source
Il existe une API appelée SubnetTree disponible en python qui fait très bien ce travail. Voici un exemple simple:
Voici le lien
la source
Voici mon code
la source
Si vous ne souhaitez pas importer d'autres modules, vous pouvez utiliser:
la source
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 des architectures little endian - egx86 - si quelqu'un aime essayer une architecture big endian, merci de me faire part de vos commentaires.
IP2Int
le code vient de cet article , l'autre méthode est un correctif de travail complet (pour mes cas de test) des propositions précédentes dans cette question.Le code:
J'espère utile,
la source
Voici la solution utilisant le package netaddr
la source