Generate All IP Addresses in a Network with Python
Explore several methods for generating and enumerating the IP addresses of a network using ipaddress, with memory optimization and practical usage examples.
InSkillCoach
Generate All IP Addresses in a Network with Python
Generating or enumerating all the IP addresses in a network is a common task in system administration, network reconnaissance, and application testing. Python’s ipaddress module provides efficient tools for this. The key is to understand the difference between subnets() for subnets, hosts() for usable addresses, and the full network, and to use generators to avoid memory problems on large networks.
1. Enumerate Usable Addresses with hosts()
The hosts() method returns a generator containing all the usable IP addresses in a network, excluding the network address and the broadcast address.
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)
Convert to a list (watch out for memory!)
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. Enumerate the Full Network by Iterating
To include the network address and the broadcast address, iterate directly over the network.
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. Difference: hosts() vs. the Full Network
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. Memory Optimization with Generators
For large networks, use generators and itertools.islice to limit the number of addresses processed.
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. Split a Network into Subnets
The subnets() method splits a network into smaller subnets.
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. Count Addresses
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. Export to a File
To process millions of IPs, write to a file rather than loading everything into memory.
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. Example: Simple Network Scanner
Scan for active addresses in a network (note that this requires the appropriate permissions).
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. Use Case: List Addresses by Range
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. Best Practices
- Use generators: don’t load millions of IPs into memory at once.
hosts()vs. direct iteration: usehosts()to exclude the network and broadcast addresses (the common case).- Watch out for /31 and /32 networks: a
/32has only one address, a/31has two, andhosts()returns zero. - Test on small networks first: before scanning /8 or /16 networks.
- Follow the law: only scan networks that you control.
Conclusion
Generating or enumerating the IP addresses of a network in Python is simple with ipaddress, but you need to stay aware of performance on large networks. Generators, subnets(), and islice are your best allies for efficiently processing CIDR blocks without blowing up your memory. These techniques are essential for system administration, network reconnaissance, and infrastructure testing.
About InSkillCoach
Training and technology expert
Coach specializing in advanced technologies and AI, backed by GNeurone Inc.
Certifications:
- AWS Certified Solutions Architect – Professional
- Google Cloud certifications
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comments
Comments are powered by GitHub Discussions
Sign in with GitHub to join the discussion