Wie überprüfe ich bei einer gegebenen IP-Adresse (z. B. 192.168.0.1), ob sie sich in einem Netzwerk (z. B. 192.168.0.0/24) in Python befindet?
Gibt es in Python allgemeine Tools zur Manipulation von IP-Adressen? Sachen wie Host-Lookups, IP-Adresse zu int, Netzwerkadresse mit Netzmaske zu int und so weiter? Hoffentlich in der Standard-Python-Bibliothek für 2.5.
python
networking
ip-address
cidr
Staale
quelle
quelle
Antworten:
Dieser Artikel zeigt, dass Sie dies mit
socket
undstruct
Modulen ohne großen Aufwand tun können . Ich habe dem Artikel wie folgt ein wenig hinzugefügt:Dies gibt aus:
Wenn Sie nur eine einzelne Funktion benötigen, die Zeichenfolgen akzeptiert, sieht dies folgendermaßen aus:
quelle
return struct.unpack('<L',socket.inet_aton(ip))[0]
addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
(Ich habe 'L' in meinem 64-Bit-Betriebssystem in '<L' konvertiert)addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
Ich benutze dafür gerne netaddr :
Wie arno_v in den Kommentaren hervorhob, macht die neue Version von netaddr das so:
quelle
Verwenden der IP-Adresse ( in der stdlib seit 3.3 , bei PyPi für 2.6 / 2.7 ):
Wenn Sie viele IP-Adressen auf diese Weise auswerten möchten, möchten Sie wahrscheinlich die Netzmaske im Voraus berechnen, z
Berechnen Sie dann für jede Adresse die binäre Darstellung mit einer von
Schließlich können Sie einfach überprüfen:
quelle
ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
.__contains__
Methode, um dies auf effiziente Weise zu tun, indem es die ganzzahligen Darstellungen des Netzwerks und die Broadcast-Adressen vergleicht. Seien Sie also versichert, wenn dies Ihre Sorge ist .Für Python3
Ausgabe :
quelle
Dieser Code funktioniert für mich unter Linux x86. Ich habe nicht wirklich über Endianess-Probleme nachgedacht, aber ich habe es mit dem "ipaddr" -Modul unter Verwendung von über 200 KB IP-Adressen getestet, die mit 8 verschiedenen Netzwerkzeichenfolgen getestet wurden. Die Ergebnisse von ipaddr stimmen mit denen dieses Codes überein.
Beispiel:
quelle
Verwenden der Python3- IP-Adresse :
Erläuterung
Sie können sich eine IP-Adresse als ein Netzwerk mit der größtmöglichen Netzmaske vorstellen (
/32
für IPv4,/128
für IPv6).Das Überprüfen, ob
192.168.0.1
in192.168.0.0/16
ist, ist im Wesentlichen dasselbe wie das Überprüfen, ob192.168.0.1/32
es sich um ein Subnetz von handelt192.168.0.0/16
quelle
Ich habe die Lösung von Dave Webb ausprobiert, bin aber auf einige Probleme gestoßen:
Grundsätzlich gilt: Eine Übereinstimmung sollte überprüft werden, indem die IP-Adresse mit der Maske UND-verknüpft wird und anschließend überprüft wird, ob das Ergebnis genau mit der Netzwerkadresse übereinstimmt. Die IP-Adresse wird nicht wie zuvor mit der Netzwerkadresse UND-verknüpft.
Mir ist auch aufgefallen, dass das Ignorieren des Endian-Verhaltens unter der Annahme, dass Konsistenz Sie spart, nur für Masken an Oktettgrenzen (/ 24, / 16) funktioniert. Damit andere Masken (/ 23, / 21) korrekt funktionieren, habe ich den struct-Befehlen ein "Größer als" hinzugefügt und den Code zum Erstellen der Binärmaske so geändert, dass er mit allen "1" beginnt und um (32-Maske) nach links verschoben wird ).
Schließlich habe ich eine einfache Überprüfung hinzugefügt, ob die Netzwerkadresse für die Maske gültig ist, und nur eine Warnung gedruckt, wenn dies nicht der Fall ist.
Hier ist das Ergebnis:
quelle
Ich bin kein Fan von Modulen, wenn sie nicht benötigt werden. Dieser Job erfordert nur einfache Mathematik. Hier ist meine einfache Funktion, um den Job zu erledigen:
Dann, um es zu benutzen:
Das war's, das ist viel schneller als die oben genannten Lösungen mit den enthaltenen Modulen.
quelle
{TypeError}'map' object is not subscriptable
. Sie benötigen eineno = list(o)
nacho = map(int, ip.split('.'))
Nicht in der Standardbibliothek für 2.5, aber ipaddr macht dies sehr einfach. Ich glaube es ist in 3.3 unter dem Namen ipaddress.
quelle
Die akzeptierte Antwort funktioniert nicht ... was mich wütend macht. Die Maske ist rückwärts und funktioniert nicht mit Bits, die kein einfacher 8-Bit-Block sind (z. B. / 24). Ich habe die Antwort angepasst und es funktioniert gut.
Hier ist eine Funktion, die eine gepunktete Binärzeichenfolge zurückgibt, um die Maskierung zu veranschaulichen
ipcalc
.z.B:
quelle
Marc's Code ist fast korrekt. Eine vollständige Version des Codes ist -
Offensichtlich aus den gleichen Quellen wie oben ...
Ein sehr wichtiger Hinweis ist, dass der erste Code einen kleinen Fehler aufweist. Die IP-Adresse 255.255.255.255 wird auch als gültige IP für jedes Subnetz angezeigt. Ich hatte verdammt viel Zeit, um diesen Code zum Laufen zu bringen, und danke Marc für die richtige Antwort.
quelle
Das Verlassen auf das "struct" -Modul kann Probleme mit der Endianität und den Typgrößen verursachen und wird einfach nicht benötigt. Socket.inet_aton () ist auch nicht. Python funktioniert sehr gut mit gepunkteten Quad-IP-Adressen:
Ich muss bei jedem Aufruf des Sockets accept () einen IP-Abgleich für eine ganze Reihe zulässiger Quellnetzwerke durchführen, daher berechne ich Masken und Netzwerke als Ganzzahlen vor:
Dann kann ich schnell sehen, ob sich eine bestimmte IP in einem dieser Netzwerke befindet:
Es sind keine Modulimporte erforderlich, und der Code ist beim Abgleichen sehr schnell.
quelle
aus netaddr importiere all_matching_cidrs
Hier ist die Verwendung für diese Methode:
Grundsätzlich geben Sie als erstes Argument eine IP-Adresse und als zweites Argument eine Liste von cidrs an. Eine Liste der Treffer wird zurückgegeben.
quelle
quelle
netmask
Werte nicht richtig . Ich habe mir erlaubt, das zu beheben.vorherige Lösung haben einen Fehler in ip & net == net. Die korrekte IP-Suche lautet ip & netmask = net
Bugfixed Code:
quelle
Die gewählte Antwort hat einen Fehler.
Es folgt der richtige Code:
Hinweis:
ipaddr & netmask == netaddr & netmask
anstelle vonipaddr & netmask == netmask
.Ich ersetze auch
((2L<<int(bits)-1) - 1)
mit((1L << int(bits)) - 1)
, da diese besser verständlich zu sein scheint.quelle
((2L<<int(bits)-1) - 1)
ist korrekt. Wenn die Maske beispielsweise 16 ist, sollte sie "255.255.0.0" oder 65535L sein,((1L << int(bits)) - 1)
erhält aber 32767L, was nicht richtig ist.((1L << int(bits)) - 1)
gibt 65535L auf meinem System, mitbits
auf 16 gesetzt !!bits
Satz zu0
,((2L<<int(bits)-1) - 1)
hebt Fehler.Hier ist eine Klasse, die ich für die längste Präfixübereinstimmung geschrieben habe:
Und hier ist ein Testprogramm:
quelle
Vielen Dank für Ihr Skript!
Ich habe ziemlich lange daran gearbeitet, damit alles funktioniert ... Also teile ich es hier
Die Funktion makeMask funktioniert nicht! Arbeitet nur für / 8, / 16, / 24 Beispiel
:
Also habe ich eine andere Funktion calcDottedNetmask (Maske) von http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/ verwendet. Beispiel
:
Bsp.: Derzeit ist die Funktion falsch
Meine neue addressInNetwork-Funktion sieht also folgendermaßen aus:
Und jetzt ist die Antwort richtig !!
Ich hoffe, dass es anderen Menschen hilft und ihnen Zeit spart!
quelle
In Bezug auf all das oben Genannte denke ich, dass socket.inet_aton () Bytes in der Netzwerkreihenfolge zurückgibt, daher ist der richtige Weg, sie zu entpacken, wahrscheinlich
quelle
$ python check-subnet.py
False
True
False
quelle
>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
Ich weiß nichts in der Standardbibliothek, aber PySubnetTree ist eine Python-Bibliothek, die Subnetz-Matching durchführt.
quelle
Aus verschiedenen Quellen oben und aus meiner eigenen Forschung habe ich auf diese Weise die Subnetz- und Adressberechnung zum Laufen gebracht. Diese Stücke reichen aus, um die Frage und andere verwandte Fragen zu lösen.
quelle
In Python gibt es eine API namens SubnetTree, die diese Aufgabe sehr gut erfüllt. Dies ist ein einfaches Beispiel:
Das ist die Verbindung
quelle
Hier ist mein Code
quelle
Wenn Sie keine anderen Module importieren möchten, können Sie Folgendes tun:
quelle
Ich habe eine Teilmenge der vorgeschlagenen Lösungen in diesen Antworten ausprobiert. Ohne Erfolg habe ich schließlich den vorgeschlagenen Code angepasst und korrigiert und meine feste Funktion geschrieben.
Ich habe es getestet und arbeite zumindest mit Little-Endian-Architekturen - egx86 -. Wenn jemand eine Big-Endian-Architektur ausprobieren möchte, gib mir bitte Feedback.
IP2Int
Code kommt aus diesem Beitrag , die andere Methode ist eine vollständig (für meine Testfälle) funktionierende Korrektur früherer Vorschläge in dieser Frage.Der Code:
Hoffe nützlich,
quelle
Hier ist die Lösung mit dem netaddr-Paket
quelle