0%
Extraer las direcciones de una subred con Python

Extraer las direcciones de una subred con Python

Aprende a extraer y analizar todas las direcciones IP de una subred con Python. Técnicas optimizadas para la monitorización de redes y la auditoría de seguridad.

I

InSkillCoach

· min

Extraer las direcciones de una subred con Python

La extracción y el análisis de las direcciones IP de una subred son tareas esenciales para los administradores de red, los especialistas en seguridad y los desarrolladores de herramientas de monitorización. En esta guía vamos a explorar cómo utilizar Python para extraer de forma eficiente todas las direcciones de una subred, filtrarlas según distintos criterios y analizarlas para diversas aplicaciones prácticas.

¿Por qué extraer las direcciones de una subred?

La extracción de las direcciones IP de una subred es útil para:

  • Inventario de red: catalogar todas las direcciones disponibles
  • Auditoría de seguridad: comprobar qué direcciones están activas o en uso
  • Planificación de capacidad: evaluar la utilización de la subred
  • Monitorización de red: vigilar sistemáticamente todas las direcciones
  • Configuración de equipos: preparar scripts de configuración para equipos de red

El módulo ipaddress al rescate

Python ofrece un potente módulo llamado ipaddress que simplifica enormemente la manipulación de direcciones IP y subredes. Importémoslo para empezar:

import ipaddress

Extraer todas las direcciones de una subred

Técnica básica

El método más sencillo para extraer todas las direcciones de una subred es iterar sobre el objeto de red:

def extract_all_addresses(cidr):
    """Extrait toutes les adresses IP d'un sous-réseau donné en notation CIDR."""
    network = ipaddress.ip_network(cidr)
    return list(network.hosts())

# Exemple pour un petit sous-réseau
subnet = "192.168.1.0/29"
addresses = extract_all_addresses(subnet)
print(f"Le sous-réseau {subnet} contient {len(addresses)} adresses utilisables:")
for addr in addresses:
    print(f"  - {addr}")

Resultado:

Le sous-réseau 192.168.1.0/29 contient 6 adresses utilisables:
  - 192.168.1.1
  - 192.168.1.2
  - 192.168.1.3
  - 192.168.1.4
  - 192.168.1.5
  - 192.168.1.6

Optimización para subredes grandes

Para las subredes grandes, es preferible evitar almacenar todas las direcciones en memoria de una sola vez. Utilicemos generadores:

def address_generator(cidr):
    """Générateur qui produit les adresses IP d'un sous-réseau sans les charger toutes en mémoire."""
    network = ipaddress.ip_network(cidr)
    for host in network.hosts():
        yield host

# Utilisation pour un sous-réseau plus grand
subnet = "10.0.0.0/24"  # 254 adresses utilisables
for i, addr in enumerate(address_generator(subnet)):
    if i < 5:  # Afficher seulement les 5 premières
        print(f"Adresse {i+1}: {addr}")
    elif i == 5:
        print("...")

Extraer subconjuntos de direcciones

Direcciones al principio y al final de la subred

def get_subnet_boundaries(cidr, count=5):
    """Retourne les premières et dernières adresses d'un sous-réseau."""
    network = ipaddress.ip_network(cidr)
    hosts = list(network.hosts())
    
    if len(hosts) <= count * 2:
        return hosts
        
    return hosts[:count] + hosts[-count:]

# Exemple
subnet = "172.16.0.0/20"
boundaries = get_subnet_boundaries(subnet)
print(f"Premières adresses de {subnet}:")
for addr in boundaries[:5]:
    print(f"  - {addr}")
print(f"Dernières adresses de {subnet}:")
for addr in boundaries[-5:]:
    print(f"  - {addr}")

Extraer direcciones por rango

def extract_address_range(cidr, start_idx, end_idx):
    """Extrait une plage spécifique d'adresses d'un sous-réseau."""
    network = ipaddress.ip_network(cidr)
    hosts = list(network.hosts())
    
    if start_idx >= len(hosts) or end_idx > len(hosts):
        raise ValueError("Indices hors limites")
        
    return hosts[start_idx:end_idx]

# Exemple: obtenir les adresses 10 à 20 d'un sous-réseau
subnet = "192.168.2.0/24"
middle_range = extract_address_range(subnet, 10, 20)
print(f"Adresses 10 à 20 de {subnet}:")
for addr in middle_range:
    print(f"  - {addr}")

Análisis y filtrado de direcciones

Filtrar por patrón de dirección

def filter_by_pattern(cidr, pattern):
    """Filtre les adresses d'un sous-réseau selon un motif."""
    network = ipaddress.ip_network(cidr)
    pattern_str = str(pattern)
    
    result = []
    for addr in network.hosts():
        if pattern_str in str(addr):
            result.append(addr)
    
    return result

# Exemple: trouver toutes les adresses contenant "100"
subnet = "192.168.0.0/22"
matching_addrs = filter_by_pattern(subnet, "100")
print(f"Adresses contenant '100' dans {subnet}:")
for addr in matching_addrs:
    print(f"  - {addr}")

Determinar las direcciones pares e impares

def categorize_addresses(cidr):
    """Catégorise les adresses en paires et impaires."""
    network = ipaddress.ip_network(cidr)
    even = []
    odd = []
    
    for host in network.hosts():
        if int(host) % 2 == 0:
            even.append(host)
        else:
            odd.append(host)
    
    return {
        'even': even,
        'odd': odd
    }

# Exemple
subnet = "192.168.1.16/28"
categories = categorize_addresses(subnet)
print(f"Adresses paires de {subnet}: {len(categories['even'])}")
print(f"Adresses impaires de {subnet}: {len(categories['odd'])}")

Aplicaciones prácticas

Escanear una subred en busca de hosts activos

import subprocess
import concurrent.futures
import platform

def ping(ip):
    """Vérifie si une adresse IP répond au ping."""
    param = "-n" if platform.system().lower() == "windows" else "-c"
    command = ["ping", param, "1", str(ip)]
    return subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0

def scan_subnet(cidr, max_workers=10):
    """Scanne un sous-réseau pour trouver les hôtes actifs."""
    network = ipaddress.ip_network(cidr)
    active_hosts = []
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        # Créer un dictionnaire de futures
        future_to_ip = {executor.submit(ping, ip): ip for ip in network.hosts()}
        
        for future in concurrent.futures.as_completed(future_to_ip):
            ip = future_to_ip[future]
            try:
                if future.result():
                    active_hosts.append(ip)
                    print(f"Hôte actif trouvé: {ip}")
            except Exception as exc:
                print(f"{ip} a généré une exception: {exc}")
    
    return active_hosts

# Exemple d'utilisation (attention: peut prendre du temps selon la taille du sous-réseau)
# active_hosts = scan_subnet("192.168.1.0/24")
# print(f"Total des hôtes actifs: {len(active_hosts)}")

Generar archivos de configuración para equipos de red

def generate_dhcp_config(cidr, domain="example.com"):
    """Génère une configuration DHCP pour un sous-réseau."""
    network = ipaddress.ip_network(cidr)
    
    config = [
        f"subnet {network.network_address} netmask {network.netmask} {{",
        f"  option domain-name \"{domain}\";",
        f"  option domain-name-servers 8.8.8.8, 8.8.4.4;",
        f"  option routers {next(network.hosts())};",
        f"  option broadcast-address {network.broadcast_address};",
        f"  default-lease-time 600;",
        f"  max-lease-time 7200;",
        "}",
        "",
        "# Réservations statiques"
    ]
    
    # Ajouter quelques réservations d'exemple
    for i, host in enumerate(list(network.hosts())[:5]):
        config.append(f"host device{i+1} {{")
        config.append(f"  hardware ethernet 00:11:22:33:44:{i+1:02x};")
        config.append(f"  fixed-address {host};")
        config.append("}")
    
    return "\n".join(config)

# Exemple
subnet = "192.168.5.0/24"
dhcp_config = generate_dhcp_config(subnet)
print("Configuration DHCP générée:")
print(dhcp_config)

Gestión de IPv6

El módulo ipaddress funciona igual de bien con IPv6 que con IPv4:

def compare_ipv4_ipv6_extraction(ipv4_cidr, ipv6_cidr, count=5):
    """Compare l'extraction d'adresses IPv4 et IPv6."""
    ipv4_net = ipaddress.ip_network(ipv4_cidr)
    ipv6_net = ipaddress.ip_network(ipv6_cidr)
    
    ipv4_hosts = list(ipv4_net.hosts())[:count]
    ipv6_hosts = list(ipv6_net.hosts())[:count]
    
    print(f"Premiers {count} hôtes IPv4 dans {ipv4_cidr}:")
    for host in ipv4_hosts:
        print(f"  - {host}")
    
    print(f"\nPremiers {count} hôtes IPv6 dans {ipv6_cidr}:")
    for host in ipv6_hosts:
        print(f"  - {host}")
    
    print(f"\nTaille totale IPv4: {ipv4_net.num_addresses} adresses")
    print(f"Taille totale IPv6: {ipv6_net.num_addresses} adresses")

# Exemple
compare_ipv4_ipv6_extraction("192.168.1.0/24", "2001:db8::/120")

Optimización del rendimiento

Para las subredes muy grandes (como /16 o mayores en IPv4, o la mayoría de las subredes IPv6), la enumeración completa puede resultar ineficiente o imposible. Estos son algunos enfoques optimizados:

def sample_large_subnet(cidr, sample_size=1000):
    """Échantillonne un grand sous-réseau de manière statistique."""
    network = ipaddress.ip_network(cidr)
    total_addresses = network.num_addresses
    
    # Si le réseau a des adresses de broadcast/réseau, les exclure du calcul
    if network.version == 4:
        host_addresses = total_addresses - 2
    else:  # IPv6 n'a pas ces restrictions
        host_addresses = total_addresses
    
    if host_addresses <= sample_size:
        return list(network.hosts())
    
    # Calculer des points d'échantillonnage statistiques
    step = host_addresses // sample_size
    
    result = []
    current = int(network.network_address) + (1 if network.version == 4 else 0)
    
    for _ in range(sample_size):
        addr = ipaddress.ip_address(current)
        if addr in network:
            result.append(addr)
        current += step
    
    return result

# Exemple avec un grand sous-réseau
large_subnet = "10.0.0.0/16"  # 65,534 adresses utilisables
samples = sample_large_subnet(large_subnet, 10)
print(f"Échantillon de 10 adresses du sous-réseau {large_subnet}:")
for addr in samples:
    print(f"  - {addr}")

Puntos clave

  • El módulo ipaddress es esencial para manipular de forma eficiente las direcciones IP en Python
  • Para las subredes pequeñas, la enumeración completa es sencilla y eficiente
  • Para las subredes grandes, da preferencia a los generadores y al muestreo
  • Las técnicas de extracción pueden adaptarse tanto a IPv4 como a IPv6
  • Las aplicaciones prácticas incluyen el escaneo de red, la configuración de equipos y el inventario de direcciones

Conclusión

La extracción de direcciones IP de una subred es una competencia fundamental para cualquier administrador de red o desarrollador que trabaje con aplicaciones de red. Python, con su módulo ipaddress, ofrece herramientas potentes para automatizar estas tareas e integrarlas en sistemas más amplios de gestión de red, monitorización o seguridad.

Dominando estas técnicas, puedes construir soluciones robustas para la gestión de tus infraestructuras de red, ya se trate de pequeñas redes locales o de grandes despliegues empresariales.

InSkillCoach

Acerca de InSkillCoach

Experto en formación y tecnologías

Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.

Certificaciones:

  • AWS Certified Solutions Architect – Professional
  • Certificaciones de Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.1k
104

Comentarios

Los comentarios funcionan con GitHub Discussions

Inicia sesión con GitHub para participar en la discusión

¡Enlace copiado!