PythonのネットワークにIPがあるかどうかを確認するにはどうすればよいですか?


100

IPアドレス(192.168.0.1など)が指定されている場合、Pythonのネットワーク(192.168.0.0/24など)にあるかどうかを確認するにはどうすればよいですか?

PythonにIPアドレス操作のための一般的なツールはありますか?ホストルックアップ、intへのip adddress、intへのネットマスクを使用したネットワークアドレスなどのようなものですか?うまくいけば、2.5の標準Pythonライブラリにあります。


この質問は、非常に古い2.xの回答では大丈夫の正規のように見えますが、3.xでは廃止されています。
smci

@smci理由はわかりません。でphihagの答えstackoverflow.com/a/1004527/1709587は Pythonの3のための完璧な答えであると私はその答えを無効にあなたの編集をロールバックしてきた2014年以来、ここにいました。
Mark Amery

@Staale-ここでの回答を、重大なバグがないものに更新する必要があります。他の答えは、組み込みライブラリを使用して、バグなしで同じことを1/10のコードで達成します。
Addison

回答:


30

この記事では、余計な手間をかけずにsocketstructモジュールでそれを実行できることを示しています。次のように記事に少し追加しました。

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)

これは出力します:

False
True

文字列を取る単一の関数が必要な場合は、次のようになります。

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

8
さらに、struct.unpack( 'L'、socket.inet_aton(ip))[0]は、エンディアンに関係なく、 'L'が4バイト以外の何かにアンパックするアーキテクチャでは失敗します。
ラファウDowgird

5
64ビットのPythonインタプリタ上で動作するようにこれを取得するために、ラファウさんのコメントに引き続き、との質問に行を置き換える:return struct.unpack('<L',socket.inet_aton(ip))[0]
とんちき

11
私はあなたの解決策に深刻なバグがあると思います:(addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True私は64ビットOSで 'L'を '<L'に変換しました)
Taha Jahangir

20
注意:このソリューションには重大なバグがあります:addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
Taha Jahangir 2012

6
この回答にはバグがあります。答えを参照してください。stackoverflow.com/questions/819355/...
Debanshuクンドゥ

156

そのためにnetaddrを使用するのが好きです。

from netaddr import CIDR, IP

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

コメントでarno_vが指摘したように、新しいバージョンのnetaddrは次のようにします。

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

>>> netaddr.all_matching_cidrs( "192.168.0.1"、["192.168.0.0/24","212.11.64.0/19"])[IPNetwork( '192.168.0.0/24')]

22
または、新しいバージョンでは、netaddr import IPNetworkから、IPNetwork( "192.168.0.0/24")のIPAddress IPAddress( "192.168.0.1")
arno_v

140

使用してIPアドレス3.3以降STDLIBでは2.6 / 2.7のためには、PyPIで):

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

この方法で多くのIPアドレスを評価したい場合は、次のようにネットマスクを事前に計算することになるでしょう。

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

次に、アドレスごとに、次のいずれかを使用してバイナリ表現を計算します。

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

最後に、簡単に確認できます。

in_network = (a & mask) == netw

2
python-ipaddrの動作は非常に遅いため、多くの比較が頻繁に必要になる場合には適さない場合があることに注意してください。YMMV、あなた自身のベンチマーク。
drdaeman

一部のバージョンでは、Pythonのstr型ではなく、Unicode文字列を指定する必要がある場合がありますipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
Moondoggy 2017年

1
このメソッドがネットワーク内のアドレスのリストを反復処理しているのではないかと心配していましたが、ipaddressモジュール__contains__は、ネットワークとブロードキャストアドレスの整数表現を比較することによって効率的な方法でそれを行うためのメソッドをオーバーライドします。。
avatarofhope2 2018年

24

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

出力:

False
True

1
標準ライブラリは賢いビット単位のチェックを使用するため、これがここで最も最適なソリューションです。github.com/python/cpython/blob/3.8/Lib/ipaddress.py#L690
rocketspacer

10

このコードはLinux x86で動作します。エンディアンの問題については特に考えていませんが、8つの異なるネットワーク文字列に対して200Kを超えるIPアドレスを使用して「ipaddr」モジュールに対してテストしました。ipaddrの結果はこのコードと同じです。

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)

例:

>>> print addressInNetwork('10.9.8.7', '10.9.1.0/16')
True
>>> print addressInNetwork('10.9.8.7', '10.9.1.0/24')
False

素晴らしくて速い。いくつかの単純な論理演算用のライブラリは必要ありません。
Chris Koston、2018年

7

Python3 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}")))

説明

IPアドレスは、可能な限り最大のネットマスクを持つネットワークと考えることができます(/32IPv4の場合、/128IPv6の場合)

であるかどうかの確認192.168.0.1は、192.168.0.0/16本質的に192.168.0.1/32192.168.0.0/16


...なぜこの答えが(まだ)一番上にないのかわかりません。
フィリッポヴィターレ

6

私はDave Webbの解決策を試しましたが、いくつかの問題が発生しました:

最も基本的には、IPアドレスとマスクのANDをとることで一致をチェックし、ネットワークアドレスと正確に一致する結果をチェックする必要があります。IPアドレスとネットワークアドレスのAND演算は行われていません。

また、一貫性によって節約されると想定してエンディアンの動作を無視すると、オクテット境界(/ 24、/ 16)のマスクに対してのみ機能することにも気付きました。他のマスク(/ 23、/ 21)が正しく機能するように、構造体コマンドに「より大きい」を追加し、バイナリマスクを作成するコードを変更して、すべて「1」で開始し、(32-mask )。

最後に、ネットワークアドレスがマスクに対して有効であることを確認する簡単なチェックを追加し、有効でない場合は警告を出力しました。

結果は次のとおりです。

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

これは64ビットで確実に機能するように見え(値が32ビットなので 'L'は失敗します)、適切な順序で値を返します(192.168.0.1の場合、ipaddrは0xC0A80001になります)。また、「192.168.0.1」のネットマスクとして「192.168.0.1/24」にも対応しています(標準ではありませんが、可能で簡単に修正可能)
IBBoard

Python 2.4で完全に動作します
xlash

6

不要なモジュールを使うのは好きではありません。この仕事は単純な数学だけを必要とするので、ここに仕事をするための私の簡単な関数があります:

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

それを使用するには:

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

それだけです。これは、含まれているモジュールを使用する上記のソリューションよりもはるかに高速です。


{TypeError}'map' object is not subscriptable。あなたは必要o = list(o)o = map(int, ip.split('.'))
gies0r

5

2.5の標準ライブラリにはありませんが、ipaddrはこれを非常に簡単にします。名前はipaddressで3.3にあると思います。

import ipaddr

a = ipaddr.IPAddress('192.168.0.1')
n = ipaddr.IPNetwork('192.168.0.0/24')

#This will return True
n.Contains(a)

これは、ここにある無数の選択肢の中で、私のお気に入りです(コメント時、2017年)。ありがとう!
rsaw 2017年

5

受け入れられた答えはうまくいきません...それは私を怒らせています。マスクは逆方向であり、単純な8ビットブロックではないビット(たとえば/ 24)では機能しません。私は答えを採用しました、そしてそれはうまくいきます。

    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

これは、マスキングを視覚化するのに役立つドット付きのバイナリ文字列を返す関数ですipcalc

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

例えば:

pythonのスクリーンショット


4

マークのコードはほぼ正しいです。コードの完全なバージョンは-

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

明らかに上記と同じソースから...

非常に重要な注意事項は、最初のコードに小さな不具合があることです。IPアドレス255.255.255.255も、サブネットの有効なIPとして表示されます。私はこのコードを機能させるのにかなりの時間を費やしました。正しい答えを提供してくれたMarcに感謝します。


試してテストしました。このページのすべてのソケット/構造体の例から、これは唯一の正しいものです
Zabuzzman、2015

4

「struct」モジュールに依存すると、エンディアンのサイズと型のサイズに問題が発生する可能性があるため、必要ありません。また、socket.inet_aton()も同様です。Pythonはドットで区切られたクワッドIPアドレスで非常にうまく機能します。

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

許容されるソースネットワークのセット全体に対して、各ソケットのaccept()呼び出しでIPマッチングを実行する必要があるため、マスクとネットワークを整数として事前計算します。

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

次に、特定のIPがこれらのネットワークの1つにあるかどうかをすばやく確認できます。

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

モジュールのインポートは不要であり、コードはマッチングが非常に高速です。


このcached_masksとは何ですか?
ajin

2

netaddrからインポート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')]

このメソッドの使用法は次のとおりです。

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

基本的に、最初の引数としてIPアドレスを指定し、2番目の引数としてCidrのリストを指定します。ヒットのリストが返されます。


2
#これは奇妙なバイトごとの処理なしで正しく機能します
def addressInNetwork(ip、net):
    '' 'ネットワーク内のアドレスです' ''
    #アドレスをホストの順序に変換するため、シフトは実際に意味があります
    ip = struct.unpack( '> L'、socket.inet_aton(ip))[0]
    netaddr、bits = net.split( '/')
    netaddr = struct.unpack( '> L'、socket.inet_aton(netaddr))[0]
    #すべて1の値を左シフトする必要があります、/ 32 =ゼロシフト、/ 0 = 32左シフト
    ネットマスク=(0xffffffff <<(32-int(bits)))&0xffffffff
    #適切なネットワークアドレスであれば、ネットワークアドレスをマスクする必要はありません。
    return(ip&netmask)== netaddr 

netmask値が正しくないため、コードは64ビットOSでは正しく機能しませんでした。私はそれを修正するために自由を取りました。
drdaeman

2

以前のソリューションには、ip&net == netにバグがあります。正しいIPルックアップはip&netmask = netです。

バグ修正されたコード:

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

2

選択した答えにはバグがあります。

以下は正しいコードです:

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

注:のipaddr & netmask == netaddr & netmask代わりにipaddr & netmask == netmask

私はまた、交換する((2L<<int(bits)-1) - 1)((1L << int(bits)) - 1)、後者がより理解しやすいようだと、。


マスク変換((2L<<int(bits)-1) - 1)は正しいと思います。たとえば、マスクが16の場合、「255.255.0.0」または65535Lにする必要があります((1L << int(bits)) - 1)が、32767Lになりますが、これは正しくありません。
Chris.Q、2015

@ Chris.Qは、((1L << int(bits)) - 1)私のシステムでbits16に設定して65535Lを与えます!!
Debanshu Kundu

また、にbits設定すると0((2L<<int(bits)-1) - 1)エラーが発生します。
Debanshu Kundu

はい、実際には/ 0、/ 8、/ 16、/ 32以外の値は正しく機能していません。
Debanshu Kundu 2017

2

これが、最長のプレフィックスマッチング用に作成したクラスです。

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

そしてここにテストプログラムがあります:

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

1

スクリプトをありがとう!
私はすべてを機能させるためにかなり長い間取り組んでいます...だから私はここでそれを共有しています

  • netaddrクラスを使用すると、バイナリ変換を使用するよりも10倍遅くなります。そのため、IPの大きなリストで使用する場合は、netaddrクラスを使用しないことを検討してください。
  • makeMask関数が機能していません。/ 8、/ 16、/ 24でのみ機能する
    例:

    ビット= "21"; socket.inet_ntoa(struct.pack( '= L'、(2L << int(bits)-1)-1))
    '255.255.31.0'ですが、255.255.248.0である必要があります

    だから私はhttp://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/から別の関数calcDottedNetmask(mask)を使用しました
    Ex:


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • もう1つの問題は、IPがネットワークに属しているかどうかを照合するプロセスです。基本的な操作は、(ipaddr&netmask)と(network&netmask)を比較することです。
    例:とりあえず、機能が間違っている

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

したがって、私の新しいaddressInNetwork関数は次のようになります。


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

そして今、答えは正しいです!


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

それが他の人々を助け、彼らのために時間を節約することを願っています!


1
上記のコードの現在のバージョンでは、最後の行にトレースバックがあり、「| = intとタプル」を使用できます。
Sean Reifschneider、2010


1
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
False
True
False


すでに与えられた回答に何を追加するのか説明できますか?
David Guyon、2016

与えられた回答には問題があり、CIDRを処理できませんでした。IPアドレスのバイト順を変更しました。このように:>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
ジョンソン

1
答えてくれてありがとう。これは、明確にするために回答に追加する必要があることだと思います。「何を」「なぜ」そして最後に「どのように」を説明するのはStackOverflowの精神です。回答には「方法」のみが含まれます:(。編集して回答を完成させます;)。
David Guyon、2016


0

上記のさまざまな情報源、および私自身の調査から、これがサブネットとアドレスの計算を機能させる方法です。これらの部分は、質問および他の関連する質問を解決するのに十分です。

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

Pythonで利用可能なSubnetTreeと呼ばれるAPIがあり、この仕事を非常にうまく行っています。これは簡単な例です:

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

これはリンクです


0

これが私のコードです

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

他のモジュールをインポートしたくない場合は、次のようにします。

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

私はこれらの回答で提案されたソリューションの1つのサブセットを試しました..成功せず、最終的に提案されたコードを適応させて修正し、修正した関数を記述しました。

私はそれをテストし、少なくともリトルエンディアンアーキテクチャ(egx86)で動作します。ビッグエンディアンアーキテクチャを試してみたい人がいたら、フィードバックを送ってください。

IP2Intコードはこの投稿からのものです他の方法は、この質問の以前の提案の完全に(私のテストケースでは)機能する修正です。

コード:

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

お役に立てれば幸いです。


0

これはnetaddrパッケージを使用したソリューションです

from netaddr import IPNetwork, IPAddress


def network_has_ip(network, ip):

    if not isinstance(network, IPNetwork):
        raise Exception("network parameter must be {0} instance".format(IPNetwork.__name__))

    if not isinstance(ip, IPAddress):
        raise Exception("ip parameter must be {0} instance".format(IPAddress.__name__))

    return (network.cidr.ip.value & network.netmask.value) == (ip.value & network.netmask.value)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.