Python — ipaddress — Как эффективно перебирать ipv6-адреса, отфильтрованные по частичному суффиксу?

#python #ip-address #python-ipaddress

Вопрос:

Я ищу способ зацикливания на определенных хостах, отфильтрованных по частичному суффиксу. Поскольку сети ipv6 огромны, моя фактическая реализация требует много времени и поиска наилучшего решения для достижения того же результата.

Это пример моего реального теста для достижения того, что мне нужно :

 
import ipaddress
from itertools import islice

for address, suffix in zip(['10.10.0.0/16','2A00:7E40:F020::/64'],['.1',':00FF:FE00:0003']):

    print('===============')
    network = ipaddress.ip_network(address)

    print(str(network.num_addresses)   ' addresses available')

    print('suffix '   suffix)
    print('===============')

    for ip in islice(filter(lambda x: str(x.exploded).endswith(suffix),network.hosts()),0,2):
        print(ip)
 

Фактический объем производства :

 ===============
65536 addresses available
suffix .1
===============
10.10.0.1
10.10.1.1
===============
18446744073709551616 addresses available
suffix :00FF:FE00:0003
===============
^C
 

С уважением,

Комментарии:

1. В чем здесь проблема? Несмотря на то, что пространство поиска огромно, я сомневаюсь, что вы затрудняете фильтрацию итерации. Вы ищете более быстрый итератор, или более быстрый способ что-то сделать с этими ip-адресами, когда они у вас есть, или что-то совсем другое?

2. Проблема заключается во времени, которое требуется, поскольку ip-адрес не обеспечивает «оптимизированный» способ сделать это. Не уверен, что более быстрый итератор будет достаточно быстрым. Может быть, есть лучший способ найти все IP-адреса из cidr с определенным суффиксом без ретрансляции на итераторе .hosts ()?

Ответ №1:

Пытаясь понять, как ускорить фильтрацию и нарезку, я пришел к этому решению, которое, похоже, справляется с этой задачей довольно быстро, даже если мы начнем с середины огромного блока IPV6

 #!/usr/bin/env python3

import ipaddress
from itertools import islice

def newv6hosts(self,start=None,limit=None,suffix=None):

    # - start is the index of the ip from where we should start
    # - limit is the number of ip we want
    # - if suffix is specified, only ips respecting this suffix will be
    #   generated. start / limit will be updated to corresponding to the index
    #   of thoses ip.
    range_start = int(self.network_address)   1
    range_end = int(self.broadcast_address)
    range_step = 1

    if suffix:
        if suffix.find('::') != -1:
            raise ValueError('Suffix should not contain "::"')
        suffix_address = ipaddress.ip_address(''.join([str(self.network_address),suffix]))
        if int(suffix_address) < int(self.network_address):
            raise ValueError('Suffix index is lower than Network adress')
        suffix_len = len(suffix.replace(':',''))
        range_start = int(suffix_address)
        range_step = 16 ** suffix_len

    if start:
        new_start = range_start   (start * int(range_step or 1))
        if new_start < range_end:
            range_start = new_start
        else:
            range_start = range_end

    if limit:
        new_end = range_start   (limit * int(range_step or 1))
        if new_end < range_end:
            range_end = new_end

    for x in range(range_start, range_end, range_step):
        yield self._address_class(x)

# Replace default method to :
#  - have a start / limit without relaying on islice (faster)
#  - filter ips generated based on a suffix
ipaddress.IPv6Network.hosts = newv6hosts

for address, suffix in zip(['10.10.0.0/16','2A00:7E40:F020::/64'],['.1','00FF:FE00:0003']):

    print('===============')
    network = ipaddress.ip_network(address)

    print(str(network.num_addresses)   ' addresses available')

    print('suffix '   suffix)
    print('===============')

    if network.version == 4:
        for ip in islice(filter(lambda x: str(x.exploded).endswith(suffix),network.hosts()),0,2):
            print(ip)
    else:
        for ip in network.hosts(start=500,limit=2,suffix=suffix):
            print(ip)
 

Выход :

 ===============
65536 addresses available
suffix .1
===============
10.10.0.1
10.10.1.1
===============
18446744073709551616 addresses available
suffix 00FF:FE00:0003
===============
2a00:7e40:f020:0:1f4:ff:fe00:3
2a00:7e40:f020:0:1f5:ff:fe00:3