Gerar todos os Endereços IP de uma Rede em Python
Explore vários métodos para gerar e enumerar os endereços IP de uma rede usando ipaddress, com otimização de memória e exemplos práticos de uso.
InSkillCoach
Gerar todos os Endereços IP de uma Rede em Python
Gerar ou enumerar todos os endereços IP de uma rede é uma tarefa comum em administração de sistemas, em reconhecimento de rede e em testes de aplicações. O módulo ipaddress do Python fornece ferramentas eficientes para isso. A chave é entender a diferença entre subnets() para as sub-redes, hosts() para os endereços utilizáveis e a rede completa, além de usar geradores para evitar problemas de memória em redes grandes.
1. Enumerar os Endereços Utilizáveis com hosts()
O método hosts() retorna um gerador contendo todos os endereços IP utilizáveis de uma rede, excluindo o endereço de rede e o endereço de broadcast.
import ipaddress
reseau = ipaddress.ip_network("192.168.1.0/24")
# hosts() retourne un générateur (pas une liste)
print(type(reseau.hosts())) # <class 'generator'>
# Itérer sur tous les hôtes
for ip in reseau.hosts():
print(ip)
# Affiche : 192.168.1.1, 192.168.1.2, ..., 192.168.1.254
# (254 adresses pour un /24)
Converter em lista (atenção à memória!)
import ipaddress
reseau = ipaddress.ip_network("192.168.1.0/24")
# Convertir le générateur en liste
liste_ips = list(reseau.hosts())
print(f"Nombre d'adresses : {len(liste_ips)}") # 254
# Accès direct à un élément
print(liste_ips[0]) # 192.168.1.1
print(liste_ips[10]) # 192.168.1.11
# ⚠️ WARNING : Ne pas faire cela sur un grand réseau !
# reseau_enorme = ipaddress.ip_network("10.0.0.0/8") # 16 millions d'IPs
# liste_enorme = list(reseau_enorme.hosts()) # Consomme plusieurs Go de RAM
2. Enumerar a Rede Completa com Iteração
Para incluir o endereço de rede e o endereço de broadcast, itere diretamente sobre a rede.
import ipaddress
reseau = ipaddress.ip_network("192.168.1.0/24")
# Itérer sur toutes les adresses (réseau + hôtes + broadcast)
for ip in reseau:
print(ip)
# Affiche : 192.168.1.0, 192.168.1.1, ..., 192.168.1.255
# (256 adresses pour un /24)
# Nombre total d'adresses
print(f"Nombre total : {reseau.num_addresses}") # 256
3. Diferença: hosts() vs Rede Completa
import ipaddress
reseau = ipaddress.ip_network("10.0.0.0/30")
# hosts() : exclut l'adresse réseau et le broadcast
print("hosts():")
for ip in reseau.hosts():
print(f" {ip}")
# Affiche : 10.0.0.1, 10.0.0.2
# (2 adresses utilisables)
# Itération complète
print("Réseau complet:")
for ip in reseau:
print(f" {ip}")
# Affiche : 10.0.0.0, 10.0.0.1, 10.0.0.2, 10.0.0.3
# (4 adresses totales : réseau 0, hôtes 1-2, broadcast 3)
4. Otimização de Memória com Geradores
Para redes grandes, use geradores e itertools.islice para limitar o número de endereços processados.
import ipaddress
import itertools
reseau_enorme = ipaddress.ip_network("10.0.0.0/8") # 16 millions d'IPs
# ✗ NE PAS FAIRE : cela consomme 100+ GB de RAM
# toutes_les_ips = list(reseau_enorme.hosts())
# ✓ FAIRE : utiliser un générateur et islice
print("Afficher les 10 premières adresses :")
for ip in itertools.islice(reseau_enorme.hosts(), 10):
print(ip)
# Affiche : 10.0.0.1, 10.0.0.2, ..., 10.0.0.10
# Traiter les adresses par lots
print("\nTraiter par lots de 100 :")
for lot in iter(lambda: list(itertools.islice(reseau_enorme.hosts(), 100)), []):
print(f"Lot de {len(lot)} adresses : {lot[0]} à {lot[-1]}")
# Traiter chaque lot (scanner, ping, etc.)
5. Dividir uma Rede em Sub-redes
O método subnets() divide uma rede em sub-redes menores.
import ipaddress
# Réseau initial
reseau = ipaddress.ip_network("192.168.0.0/22")
# Diviser en /24 (4 sous-réseaux)
print("Sous-réseaux /24 :")
for subnet in reseau.subnets(new_prefix=24):
print(f" {subnet}")
# Affiche :
# 192.168.0.0/24
# 192.168.1.0/24
# 192.168.2.0/24
# 192.168.3.0/24
# Diviser en /25 (8 sous-réseaux)
print("\nSous-réseaux /25 :")
for subnet in reseau.subnets(new_prefix=25):
print(f" {subnet}")
6. Contar os Endereços
import ipaddress
reseau = ipaddress.ip_network("172.16.0.0/12")
# Nombre total
print(f"Total : {reseau.num_addresses}") # 1048576
# Nombre d'hôtes utilisables (excluant réseau et broadcast)
print(f"Hôtes utilisables : {len(list(reseau.hosts()))}") # 1048574
# Adresses réservées
print(f"Réservées : 2 (réseau + broadcast)")
7. Exportar para Arquivo
Para processar milhões de IPs, escreva em um arquivo em vez de carregar tudo em memória.
import ipaddress
reseau = ipaddress.ip_network("10.0.0.0/16")
# Exporter en fichier texte
with open("ips.txt", "w") as f:
for ip in reseau.hosts():
f.write(f"{ip}\n")
# Vérifier le fichier
with open("ips.txt", "r") as f:
nb_lignes = sum(1 for _ in f)
print(f"Fichier contient {nb_lignes} adresses")
# Fichier contient 65534 adresses
8. Exemplo: Scanner de Rede Simples
Escaneie os endereços ativos em uma rede (observe que isso exige as permissões apropriadas).
import ipaddress
import socket
from concurrent.futures import ThreadPoolExecutor, as_completed
def ping_ip(ip, timeout=1):
"""Vérifier si une IP répond."""
try:
socket.create_connection((str(ip), 22), timeout=timeout)
return True
except (socket.timeout, socket.error):
return False
def scanner_reseau(reseau_cidr, num_workers=10):
"""Scanner un réseau et lister les IPs actives."""
reseau = ipaddress.ip_network(reseau_cidr, strict=False)
actives = []
with ThreadPoolExecutor(max_workers=num_workers) as executor:
futures = {
executor.submit(ping_ip, ip): ip
for ip in reseau.hosts()
}
for future in as_completed(futures):
ip = futures[future]
if future.result():
actives.append(ip)
print(f"✓ {ip} actif")
return actives
# Scanner le réseau 192.168.1.0/24
# ips_actives = scanner_reseau("192.168.1.0/24")
# print(f"\nTotal actifs : {len(ips_actives)}")
# Note : remplacer socket.create_connection par un vrai ping
# pour une reconnaissance plus réaliste (ICMP)
9. Caso de Uso: Listar os Endereços por Faixa
import ipaddress
def generer_adresses_par_plages(plages):
"""
Génère des adresses IP à partir de multiples plages CIDR.
Args:
plages (list): Liste de strings CIDR (ex: ["192.168.1.0/24", "10.0.0.0/16"])
Yields:
ipaddress.IPv4Address : adresse IP
"""
for plage in plages:
reseau = ipaddress.ip_network(plage, strict=False)
for ip in reseau.hosts():
yield ip
# Utilisation
plages_internes = [
"192.168.0.0/16",
"10.0.0.0/8",
"172.16.0.0/12",
]
print("Afficher les 20 premières adresses internes :")
for i, ip in enumerate(generer_adresses_par_plages(plages_internes)):
if i >= 20:
break
print(ip)
10. Boas Práticas
- Use geradores: não carregue milhões de IPs na memória de uma só vez.
hosts()vs iteração direta: usehosts()para excluir a rede e o broadcast (caso comum).- Atenção aos /30 e menores: um
/32tem apenas um endereço, um/31tem dois, ehosts()retorna zero. - Teste primeiro em redes pequenas: antes de escanear redes /8 ou /16.
- Respeite as leis: escaneie apenas as redes que você controla.
Conclusão
Gerar ou enumerar endereços IP de uma rede em Python é simples com ipaddress, mas é preciso ficar atento ao desempenho em redes grandes. Os geradores, subnets() e islice são seus melhores aliados para processar blocos CIDR com eficiência, sem estourar a memória. Essas técnicas são indispensáveis para a administração de sistemas, o reconhecimento de rede e os testes de infraestrutura.
Sobre InSkillCoach
Especialista em treinamento e tecnologias
Coach especializado em tecnologias avançadas e IA, apoiado pela GNeurone Inc.
Certificações:
- AWS Certified Solutions Architect – Professional
- Certificações Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão