Comment puis-je vérifier si une adresse ip est un réseau en Python?
Donné une adresse ip (dire 192.168.0.1), comment puis-je vérifier si il est dans un réseau (dire 192.168.0.0/24) en Python?
Sont là des outils généraux en Python pour l'adresse ip de la manipulation? Des trucs comme hôte de recherches d'adresse ip int, adresse réseau masque réseau d'int et ainsi de suite? Espérons que dans la bibliothèque standard de Python 2.5.
- Cette question semble être un bon canonique pour les très vieux 2.x les réponses, mais est obsolète pour 3.x Voir Comment organiser et d'attribuer canonicals pour “Python/pandas comparer adresse IP/CIDR”?
- Je ne vois pas pourquoi; phihag de répondre à stackoverflow.com/a/1004527/1709587 est une très bonne réponse pour Python 3 et a été ici depuis 2014. J'ai roulé en arrière votre travail d'édition qui a invalidé cette réponse.
Vous devez vous connecter pour publier un commentaire.
Cet article montre que vous pouvez le faire avec
socket
etstruct
modules sans trop d'effort supplémentaire. J'ai ajouté un peu de l'article comme suit:Ce sorties:
Si vous voulez juste une seule fonction qui prend des chaînes, il devrait ressembler à ceci:
return struct.unpack('<L',socket.inet_aton(ip))[0]
addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
(je les ai converti en " L " à "<L' dans mes os 64 bits)addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
ip & net == net
, qui renvoie true lorsque ip='11.0.1.1' et net='10.0.0.0/8'; 2. il ne fonctionne que sur little-endian lavable en même fixer le premier bug. C'est incompatible sur big-endian de la machine. La résolution est de toujours utiliser la fonctionntohl()
(en python, c'estsocket.ntohl()
) pour convertir l'entier retourné parinet_aton()
. Et après l'utilisationntohl()
, nous avons besoin de comparer le n bits au début plutôt qu'à la n bits à la fin.J'aime utiliser netaddr pour que:
Comme arno_v souligné dans les commentaires, la nouvelle version de netaddr elle a fait comme ceci:
À l'aide de ipaddress (dans la stdlib depuis 3.3, au PyPi pour 2.6/2.7):
Si vous souhaitez évaluer un beaucoup d'adresses IP de cette façon, vous aurez probablement envie de calculer le masque de réseau d'avance, comme
Ensuite, pour chaque adresse, calculer la représentation binaire avec l'un de
Enfin, vous pouvez simplement cocher:
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 le nombre entier des représentations du réseau et les adresses de diffusion, donc rassurez-vous si c'était votre inquiétude.Ce code fonctionne pour moi sur Linux x86. Je n'ai pas vraiment pensé à l'endianess questions, mais je l'ai testé contre les "ipaddr" module à l'aide de plus de 200 adresses IP testé contre 8 différentes réseau de chaînes, et les résultats de l'adresse ip sont les mêmes que le présent code.
Exemple:
Pour python3
J'ai essayé Dave Webb solution mais frapper quelques problèmes:
Plus fondamentalement, un match doit être vérifiée par ANDing l'adresse IP et le masque, puis de vérifier que le résultat correspond à l'adresse de Réseau exactement. Pas ANDing l'adresse IP avec l'adresse de Réseau comme cela a été fait.
J'ai aussi remarqué que juste ignorant la Endian comportement en supposant que la consistance vous permettra d'économiser en ne fonctionnera que pour les masques sur octet limites (/24, /16). Pour obtenir d'autres masques (/23, /21) fonctionne correctement, j'ai ajouté un "supérieur" à la structure des commandes et changé le code pour créer le masque binaire de commencer avec tous les "1" et décale à gauche par (32-masque).
Enfin, j'ai ajouté une façon simple de vérifier que l'adresse réseau est valable pour le masque et il vous suffit d'imprimer un avertissement si elle ne l'est pas.
Voici le résultat:
Je ne suis pas un fan de l'utilisation de modules lorsqu'ils ne sont pas nécessaires. Ce travail ne nécessite mathématiques simples, alors voici ma fonction simple pour faire le travail:
Puis de l'utiliser:
C'est ça, c'est beaucoup plus rapide que les solutions ci-dessus avec les modules inclus.
{TypeError}'map' object is not subscriptable
. Vous avez besoin d'uno = list(o)
aprèso = map(int, ip.split('.'))
La accepté de répondre ne fonctionne pas ... ce qui me rend en colère. Le masque est en arrière et ne fonctionne pas avec tous les bits ne sont pas un simple 8 bloc de bits (par exemple /24). J'ai adapté la réponse, et il fonctionne très bien.
ici est une fonction qui retourne un pointillé chaîne binaire pour aider à visualiser le masquage.. un peu comme
ipcalc
de sortie.par exemple:
Pas dans la bibliothèque Standard de 2.5, mais ipaddr très facile. Je crois que c'est en 3.3 sous le nom de ipaddress.
De Marc, le code est presque correct. Une version complète du code, c'est -
Évidemment de la même source que ci-dessus...
Une remarque très Importante, c'est que le premier code a un petit glitch - L'adresse IP 255.255.255.255 également présente comme une IP Valide pour n'importe quel sous-réseau. J'ai eu un diable de temps à obtenir ce code fonctionne, et merci à Marc pour la réponse correcte.
En s'appuyant sur le "struct" module peut causer des problèmes avec endian-ness et des formats, et n'est tout simplement pas nécessaire. Ni est prise.inet_aton(). Python fonctionne très bien avec les pointillés en quad adresses IP:
J'ai besoin de faire IP correspondant à chaque socket accept() de l'appel, à l'encontre de tout un ensemble de source permise réseaux, donc je précalculer les masques et les réseaux, comme les entiers:
Alors je peut voir rapidement si une IP est dans un de ces réseaux:
Pas de module d'importation requis, et le code est très rapide de la correspondance.
de netaddr importation all_matching_cidrs
Ici est l'utilisation de cette méthode:
En gros vous fournir une adresse ip comme premier argument et une liste de cidm comme deuxième argument. Une liste de hits sont retournés.
netmask
valeurs. J'ai pris la liberté de corriger cela.Choisi la réponse a un bug.
Suivant est le bon code:
Remarque:
ipaddr & netmask == netaddr & netmask
au lieu deipaddr & netmask == netmask
.J'ai aussi remplacer
((2L<<int(bits)-1) - 1)
avec((1L << int(bits)) - 1)
, comme ce dernier semble plus compréhensible.((2L<<int(bits)-1) - 1)
est correct. par exemple, si le masque est de 16 ans, il doit être "255.255.0.0" ou 65535L, mais((1L << int(bits)) - 1)
obtiendrez 32767L, ce qui n'est pas droit.bits
16!!bits
ensemble de0
,((2L<<int(bits)-1) - 1)
est la collecte d'erreur.Ici est une classe que j'ai écrit pour le plus long préfixe correspondant:
Et ici est un programme de test:
Merci pour ton script!
J'ai un travail assez long sur elle pour faire tout ce travail... Donc je partage ici
makeMask ne fonctionne pas! Seulement pour /8,/16,/24
Ex:
J'ai donc utilisé une autre fonction calcDottedNetmask(masque) de http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
Ex:
Ex: pour le moment, la fonction est mal
Donc mon nouveau addressInNetwork fonction ressemble comme:
Et maintenant, la réponse est juste!!
J'espère que ça aidera d'autres personnes, le gain de temps pour eux!!!
Relatives à l'ensemble des ci-dessus, je pense que socket.inet_aton() renvoie octets en réseau, donc la bonne façon de décompresser entre eux est probablement
solution précédente ont un bug dans ip & net == net. Correcte de recherche de l'ip est l'ip & netmask = net
erreurs de code:
Il y a une API qui est appelé SubnetTree disponible en python qui fait ce travail très bien.
C'est un exemple simple :
C'est le lien
$ python check-subnet.py
Faux
Vrai
Faux
>>> 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 pas de quoi que ce soit dans la bibliothèque standard, mais PySubnetTree est une bibliothèque Python qui permettra de faire de sous-réseau correspondant.
À partir de diverses sources ci-dessus, et de ma propre recherche, c'est comment j'ai obtenu de sous-réseau et l'adresse de calcul de travail. Ces pièces sont assez pour résoudre la question et d'autres questions connexes.
Voici mon code
Si vous ne souhaitez pas importer d'autres modules que vous pourriez aller avec:
J'en 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 little endian architectures--e.g.x86-- si quelqu'un aime essayer sur un big endian architecture, veuillez me donner vos commentaires.
IP2Int
du code vient de ce post, l'autre est une méthode entièrement (pour mon cas de test) de travail correctif de propositions dans cette question.Le code:
Espère utile,