0%
Extraire les adresses d'un sous-réseau avec Python

Extraire les adresses d'un sous-réseau avec Python

Apprenez à extraire et analyser toutes les adresses IP d'un sous-réseau avec Python. Techniques optimisées pour le monitoring réseau et l'audit de sécurité.

I

InSkillCoach

· min

import EmailSubscribe from ’../../../components/EmailSubscribe.astro’;

Extraire les adresses d’un sous-réseau avec Python

L’extraction et l’analyse des adresses IP d’un sous-réseau sont des tâches essentielles pour les administrateurs réseau, les spécialistes en sécurité et les développeurs d’outils de monitoring. Dans ce guide, nous allons explorer comment utiliser Python pour extraire efficacement toutes les adresses d’un sous-réseau, les filtrer selon différents critères, et les analyser pour diverses applications pratiques.

Pourquoi extraire les adresses d’un sous-réseau?

L’extraction des adresses IP d’un sous-réseau est utile pour:

  • Inventaire réseau: Cataloguer toutes les adresses disponibles
  • Audit de sécurité: Vérifier quelles adresses sont actives ou utilisées
  • Planification de capacité: Évaluer l’utilisation du sous-réseau
  • Monitoring réseau: Surveiller systématiquement toutes les adresses
  • Configuration d’équipements: Préparer des scripts de configuration pour des équipements réseau

Le module ipaddress à la rescousse

Python offre un puissant module nommé ipaddress qui simplifie grandement la manipulation des adresses IP et des sous-réseaux. Importons-le pour commencer:

import ipaddress

Extraire toutes les adresses d’un sous-réseau

Technique de base

La méthode la plus simple pour extraire toutes les adresses d’un sous-réseau est d’itérer sur l’objet réseau:

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}")

Résultat:

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

Optimisation pour grands sous-réseaux

Pour les grands sous-réseaux, il est préférable d’éviter de stocker toutes les adresses en mémoire d’un coup. Utilisons des générateurs:

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("...")

Extraire des sous-ensembles d’adresses

Adresses au début et à la fin du sous-réseau

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}")

Extraire des adresses par plage

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}")

Analyse et filtrage d’adresses

Filtrer par motif d’adresse

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}")

Déterminer les adresses paires et impaires

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'])}")

Applications pratiques

Scanner un sous-réseau pour les hôtes actifs

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)}")

Générer des fichiers de configuration pour équipements réseau

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)

Gestion d’IPv6

Le module ipaddress fonctionne aussi bien avec IPv6 qu’avec 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")

Optimisation des performances

Pour les très grands sous-réseaux (comme /16 ou plus grand en IPv4, ou la plupart des sous-réseaux IPv6), l’énumération complète peut être inefficace ou impossible. Voici quelques approches optimisées:

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}")

Points clés à retenir

  • Le module ipaddress est essentiel pour manipuler efficacement les adresses IP en Python
  • Pour les petits sous-réseaux, l’énumération complète est simple et efficace
  • Pour les grands sous-réseaux, privilégiez les générateurs et l’échantillonnage
  • Les techniques d’extraction peuvent être adaptées pour IPv4 et IPv6
  • Les applications pratiques incluent le scanning réseau, la configuration d’équipements, et l’inventaire d’adresses

Conclusion

L’extraction d’adresses IP d’un sous-réseau est une compétence fondamentale pour tout administrateur réseau ou développeur travaillant avec des applications réseau. Python, avec son module ipaddress, offre des outils puissants pour automatiser ces tâches et les intégrer dans des systèmes plus larges de gestion réseau, de monitoring ou de sécurité.

En maîtrisant ces techniques, vous pouvez construire des solutions robustes pour la gestion de vos infrastructures réseau, qu’il s’agisse de petits réseaux locaux ou de vastes déploiements en entreprise.

InSkillCoach

À propos de InSkillCoach

Expert en formation et technologies

Coach spécialisé dans les technologies avancées et l'IA, porté par GNeurone Inc.

Certifications:

  • AWS Certified Solutions Architect – Professional
  • Certifications Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
724
59

Commentaires

Les commentaires sont alimentés par GitHub Discussions

Connectez-vous avec GitHub pour participer à la discussion

Lien copié !