IP 목록을 최소 CIDR 표현으로 변환

IP 목록을 최소 CIDR 표현으로 변환

다음과 같은 IP 주소 목록이 있습니다.

10.10.0.0
10.10.0.1
10.10.0.2
...
10.10.0.255
172.171.0.5
...
172.171.0.67

이러한 목록을 가져와 해당 IP 주소의 최소 CIDR 표현을 계산할 수 있는 도구가 있습니까?

예를 들어 위의 예에서는 다음과 같은 출력을 얻고 싶습니다.

10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30

편집: 명확히 하기 위해 "최소 CIDR 표현"은 내 입력 파일의 모든 IP 주소를 포함하는 가장 작은 CIDR IP 주소 집합입니다.

답변1

내장된 Python 모듈 사용IP 주소@AB가 제안함논평이것을 제안하다우편 엽서.

누구나주소 범위 요약(시작과 끝이 있음) 또는주소 접기(목록 포함)을 사용할 수 있습니다.

이 경우에는 후자가 더 편리합니다.

import sys
import ipaddress

data = open(sys.argv[1],'r').read().splitlines()
ips = [ipaddress.IPv4Address(line) for line in data]
print('\n'.join([ip.with_prefixlen for ip in ipaddress.collapse_addresses(ips)]))

사용법 및 출력:

$ python3 cidr.py file
10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30

답변2

이것은 실제로 제가 한동안 해결하고 싶은 문제입니다. 이 ipaddress모듈을 사용하여 해결할 수 있지만 제 구현은 아마도 불필요하게 복잡할 수 있지만 작동합니다.

from ipaddress import IPv4Address, IPv6Address, IPv4Network, IPv6Network
addrs = ["10.10.0.0", "10.10.0.1", "10.10.0.2", "10.10.0.255", "172.171.0.5", "172.171.0.67"]
out = []
while True:
    if len(addrs) == 0:
        break
    found = False
    for index in out:
        if IPv4Network(addrs[0], 32).subnet_of(index.supernet(new_prefix=8)):
            cur = index
            while True:
                if cur.supernet_of(IPv4Network(addrs[0], 32)):
                    break
                else:
                    cur = cur.supernet()
            out[out.index(index)] = cur
            addrs.pop(0)
            found = True
            break
    if not found:
        out.append(IPv4Network(addrs.pop(0), 32).supernet())

그러면 다음과 같은 결과가 나타납니다.

In [81]: out
Out[81]: [IPv4Network('10.10.0.0/24'), IPv4Network('172.171.0.0/25')]

내 구현에 대해 100% 확신할 수는 없지만 이것이 더 잘 수행될 수 있다고 생각하며 이는 /8. 그것으로 하세요.

관련 정보