[python] Python의 네트워크에 IP가 있는지 어떻게 확인할 수 있습니까?

IP 주소 (예 : 192.168.0.1)가 주어지면 Python에서 네트워크 (예 : 192.168.0.0/24)에 있는지 어떻게 확인합니까?

Python에 IP 주소 조작을위한 일반적인 도구가 있습니까? 호스트 조회, int에 대한 ip 주소, int에 대한 넷 마스크가있는 네트워크 주소 등과 같은 것들? 바라건대 2.5 용 표준 Python 라이브러리에 있습니다.



답변

이 기사 에서는 추가 노력없이 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


답변

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


답변

사용 IPADDRESS ( 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


답변

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


답변

이 코드는 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


답변

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/32으로 서브넷 인지 확인하는 것과 같습니다.192.168.0.0/16


답변

Dave Webb의 솔루션을 시도했지만 몇 가지 문제가 발생했습니다.

가장 근본적으로-일치 여부는 IP 주소를 마스크와 AND로 연결 한 다음 결과가 네트워크 주소와 정확히 일치하는지 확인해야합니다. IP 주소와 네트워크 주소를 AND로 처리하지 않았습니다.

또한 일관성이 절약된다는 가정하에 Endian 동작을 무시하는 것만으로도 옥텟 경계 (/ 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