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
ipaddresses 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.
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+
Comentarios
Los comentarios funcionan con GitHub Discussions
Inicia sesión con GitHub para participar en la discusión