0%
Generate All IP Addresses in a Network with Python

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.

I

InSkillCoach

· min

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: use hosts() to exclude the network and broadcast addresses (the common case).
  • Watch out for /31 and /32 networks: a /32 has only one address, a /31 has two, and hosts() 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.

InSkillCoach

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+
1.2k
348

Comments

Comments are powered by GitHub Discussions

Sign in with GitHub to join the discussion

Link copied!