it-swarm.com.de

Wie kann ich überprüfen, ob sich eine IP in einem Netzwerk in Python befindet?

Wie kann ich bei einer IP-Adresse (z. B. 192.168.0.1) überprüfen, ob sie sich in einem Netzwerk (z. B. 192.168.0.0/24) in Python befindet?

Gibt es in Python allgemeine Werkzeuge zur Manipulation von IP-Adressen? Sachen wie Host-Lookups, IP-Adresse an Int, Netzwerkadresse mit Netzmaske an Int und so weiter? Hoffentlich in der Standard-Python-Bibliothek für 2.5.

80
Staale

Dieser Artikel zeigt, dass Sie dies mit socket und struct Modulen ohne viel zusätzlichen Aufwand tun können. Ich habe dem Artikel ein wenig hinzugefügt:

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)

Dies gibt aus:

False
True

Wenn Sie nur eine einzige Funktion wünschen, die Zeichenfolgen benötigt, würde dies folgendermaßen aussehen:

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

Ich benutze gerne netaddr dafür:

from netaddr import CIDR, IP

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

Wie arno_v in den Kommentaren darauf hingewiesen hat, macht es die neue Version von netaddr folgendermaßen:

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

Verwendung von ipaddress ( in der stdlib seit 3.3 , am PyPi für 2.6/2.7 ):

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

Wenn Sie ein lot von IP-Adressen auf diese Weise auswerten möchten, möchten Sie wahrscheinlich die Netzmaske vorab berechnen, z

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

Berechnen Sie dann für jede Adresse die binäre Darstellung mit einer von

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

Zum Schluss können Sie einfach überprüfen:

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

Dieser Code funktioniert für mich unter Linux x86. Ich habe nicht wirklich über Endianess-Probleme nachgedacht, aber ich habe es gegen das "ipaddr" -Modul getestet, bei dem über 200K-IP-Adressen mit 8 verschiedenen Netzwerkstrings getestet wurden.

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)

Beispiel:

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

Für Python3

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

Ich bin kein Fan von Modulen, wenn sie nicht benötigt werden. Dieser Job erfordert nur einfache Berechnungen, daher ist hier meine einfache Funktion:

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

Dann verwenden Sie es:

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

Das ist es, das ist viel schneller als die oben genannten Lösungen mit den enthaltenen Modulen.

6
Landon

Ich habe die Lösung von Dave Webb ausprobiert, aber einige Probleme festgestellt:

Grundsätzlich gilt: Eine Übereinstimmung sollte durch UND-Verknüpfung der IP-Adresse mit der Maske und anschließender Überprüfung des Ergebnisses mit der Netzwerkadresse überprüft werden. Die IP-Adresse wurde NICHT mit der Netzwerkadresse AND-verknüpft, wie dies geschehen ist.

Ich habe auch bemerkt, dass das Ignorieren des Endian-Verhaltens unter der Annahme, dass Konsistenz sparen wird, 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 nach links verschoben wird (32-Maske) ). 

Schließlich fügte ich eine einfache Überprüfung hinzu, dass die Netzwerkadresse für die Maske gültig ist, und drucke nur eine Warnung, falls dies nicht der Fall ist.

Hier ist das Ergebnis:

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

Die akzeptierte Antwort funktioniert nicht ... was mich wütend macht. Die Maske ist rückwärts und funktioniert nicht mit Bits, die keine einfachen 8-Bit-Blöcke sind (z. B./24). Ich habe die Antwort angepasst und es funktioniert gut.

    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

hier ist eine Funktion, die eine gepunktete binäre Zeichenfolge zurückgibt, um die Maskierung zu erleichtern. Art von ipcalc-Ausgabe.

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

z.B:

screen shot of python

5
jorb

Marc's Code ist fast korrekt. Eine vollständige Version des Codes ist -

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

Offensichtlich aus den gleichen Quellen wie oben ...

Ein sehr wichtiger Hinweis ist, dass der erste Code eine kleine Störung aufweist. Die IP-Adresse 255.255.255.255 wird auch als gültige IP-Adresse für jedes Subnetz angezeigt. Ich hatte eine Menge Zeit, diesen Code zum Laufen zu bringen und danke Marc für die richtige Antwort.

4
Nitin Khanna

Nicht in der Standard-Bibliothek für 2.5, aber ipaddr macht dies sehr einfach. Ich glaube es ist in 3.3 unter dem Namen 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

Wenn Sie sich auf das "struct" -Modul verlassen, kann dies zu Problemen mit der Endianität und der Schriftgröße führen und wird nicht benötigt. Noch ist socket.inet_aton (). Python funktioniert sehr gut mit gepunkteten Quad-IP-Adressen:

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

Ich muss den IP-Abgleich für jeden Socket-Accept () - Aufruf gegen eine ganze Reihe zulässiger Quellennetzwerke durchführen, sodass ich Masken und Netzwerke als Ganzzahlen vorberechne:

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

Dann kann ich schnell sehen, ob sich eine bestimmte IP in einem dieser Netzwerke befindet:

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

Es sind keine Modulimporte erforderlich, und der Code ist sehr schnell beim Abgleichen.

3
gstein

Die gewählte Antwort hat einen Fehler.

Folgendes ist der korrekte Code:

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

Hinweis: ipaddr & netmask == netaddr & netmask statt ipaddr & netmask == netmask

Ich ersetze auch ((2L<<int(bits)-1) - 1) durch ((1L << int(bits)) - 1), da letzteres verständlicher erscheint.

2
Debanshu Kundu

Hier ist eine Klasse, die ich für den längsten Präfixvergleich geschrieben habe:

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

Und hier ist ein Testprogramm:

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
 # Dies funktioniert einwandfrei ohne die seltsame byteweise Behandlung von 
 Def addressInNetwork (ip, net): 
 '' 'Ist eine Adresse in einem Netzwerk' '' 
 # Adressen in Host-Reihenfolge konvertieren, so dass Verschiebungen tatsächlich sinnvoll sind 
 ip = struct.unpack ('> L', socket.inet_aton (ip)) [0] 
 netaddr, bits = net.split ('/')
 netaddr = struct.unpack ('> L', socket.inet_aton (netaddr)) [0] 
 # Muss einen Alle-Wert nach links verschieben,/32 = Nullpunktverschiebung,/0 = 32 nach links verschieben 
 Netzmaske = (0xffffffff & lt (32-int (Bits))) & 0xffffffff 
 # Es ist nicht erforderlich, die Netzwerkadresse zu maskieren, sofern es sich um eine korrekte Netzwerkadresse handelt 
 return (ip & netmask) == netaddr 
2
Marcelo Pacheco

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

Hier ist die Verwendung für diese Methode:

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

Grundsätzlich geben Sie eine IP-Adresse als erstes Argument und eine Liste von cidrs als zweites Argument an. Eine Trefferliste wird zurückgegeben.

2
user221014

Danke für dein Skript!
Ich habe ziemlich lange daran gearbeitet, um alles zum Laufen zu bringen ... Also teile ich es hier

  • Die Verwendung der netaddr-Klasse ist zehnmal langsamer als die binäre Konvertierung. Wenn Sie also eine große Liste von IP-Adressen verwenden möchten, sollten Sie die netaddr-Klasse nicht verwenden
  • die makeMask-Funktion funktioniert nicht! Nur für/8,/16,/24 arbeiten 
    Ex:

    bits = "21"; socket.inet_ntoa (struct.pack ('= L', (2L << int (bits) -1) - 1))
    '255.255.31.0', wobei es 255.255.248.0 sein sollte

    Also habe ich eine andere Funktion verwendet, die calcDottedNetmask (mask) von http://code.activestate.com/recipes/576483-convert-subnetmask-von-cidr-notation-to-dotdecima/ verwendet. 
    Ex:


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • Ein weiteres Problem ist der Abgleich, ob eine IP zu einem Netzwerk gehört! Grundlegende Vorgänge sollten die Vergleiche (ipaddr & netmask) und (network & netmask) sein.
    Bsp .: die Funktion ist vorerst falsch

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

So sieht meine neue addressInNetwork-Funktion so aus:


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


Und jetzt ist die Antwort richtig !!


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

Ich hoffe, es hilft anderen Menschen und spart ihnen Zeit!

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
Falsch
Wahr
Falsch

1
Johnson

Ich kenne nichts in der Standardbibliothek, aber PySubnetTree ist eine Python-Bibliothek, die Subnetzabgleich durchführen wird.

1
RichieHindle

Es gibt eine API mit dem Namen SubnetTree, die in Python verfügbar ist und diese Aufgabe sehr gut erfüllt. Dies ist ein einfaches Beispiel: 

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

Das ist die Verbindung

1
salaheddine

vorherige Lösung hat einen Fehler in ip & net == net. Richtige IP-Suche ist ip & netmask = net

bugfixed Code:

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

In Bezug auf all das denke ich, dass socket.inet_aton () Bytes in der Reihenfolge des Netzwerks zurückgibt, also ist der korrekte Weg, sie zu entpacken, wahrscheinlich

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

Hier ist mein 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

Ich habe einen Teil der vorgeschlagenen Lösungen in diesen Antworten ausprobiert. Ohne Erfolg habe ich schließlich den vorgeschlagenen Code angepasst und repariert und meine feste Funktion geschrieben. 

Ich habe es getestet und arbeitet zumindest mit kleinen Endian-Architekturen - z. B. x86 -. Wenn jemand eine Big-Endian-Architektur ausprobieren möchte, geben Sie mir bitte ein Feedback.

IP2Int-Code stammt aus diesem Beitrag , die andere Methode ist eine vollständige (für meine Testfälle) funktionierende Korrektur früherer Vorschläge in dieser Frage. 

Der 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

Hoffe nützlich,

0
Fabiano Tarlao

Aus verschiedenen Quellen oben und aus meiner eigenen Recherche habe ich so das Subnetz und die Adressberechnung zum Laufen gebracht. Diese Stücke reichen aus, um die Frage und andere verwandte Fragen zu lösen.

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

Wenn Sie keine anderen Module importieren möchten, können Sie Folgendes tun:

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