0%
توليد جميع عناوين IP في شبكة باستخدام Python

توليد جميع عناوين IP في شبكة باستخدام Python

اكتشف عدة طرق لتوليد عناوين IP في شبكة ما وتعدادها باستخدام ipaddress، مع تحسين استهلاك الذاكرة وأمثلة عملية للاستخدام.

I

InSkillCoach

· دقيقة

توليد جميع عناوين IP في شبكة باستخدام Python

يُعدّ توليد جميع عناوين IP في شبكة ما أو تعدادها مهمة شائعة في إدارة الأنظمة واستطلاع الشبكات واختبار التطبيقات. توفّر الوحدة ipaddress في Python أدوات فعّالة لهذا الغرض. والمفتاح هو فهم الفرق بين subnets() للشبكات الفرعية، وhosts() للعناوين القابلة للاستخدام، والشبكة الكاملة، إضافةً إلى استخدام المولّدات (generators) لتفادي مشكلات الذاكرة في الشبكات الكبيرة.

1. تعداد العناوين القابلة للاستخدام باستخدام hosts()

تُرجع الدالة hosts() مولّدًا يحتوي على جميع عناوين IP القابلة للاستخدام في الشبكة، مع استثناء عنوان الشبكة وعنوان البث (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)

التحويل إلى قائمة (انتبه إلى الذاكرة!)

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. تعداد الشبكة كاملةً عبر التكرار

لتضمين عنوان الشبكة وعنوان البث، كرِّر مباشرةً على الشبكة نفسها.

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. الفرق بين hosts() والشبكة الكاملة

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. تحسين استهلاك الذاكرة باستخدام المولّدات

بالنسبة إلى الشبكات الكبيرة، استخدم المولّدات وitertools.islice للحدّ من عدد العناوين التي تتم معالجتها.

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. تقسيم شبكة إلى شبكات فرعية

تقسّم الدالة 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. عدّ العناوين

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. التصدير إلى ملف

لمعالجة ملايين عناوين IP، اكتبها في ملف بدلًا من تحميلها في الذاكرة.

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. مثال: ماسح شبكة بسيط

امسح العناوين النشطة في شبكة ما (لاحظ أن ذلك يتطلب الصلاحيات المناسبة).

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. حالة استخدام: سرد العناوين حسب النطاقات

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. أفضل الممارسات

  • استخدم المولّدات: لا تحمّل ملايين عناوين IP في الذاكرة دفعة واحدة.
  • hosts() مقابل التكرار المباشر: استخدم hosts() لاستثناء عنوان الشبكة وعنوان البث (الحالة الأكثر شيوعًا).
  • انتبه إلى الشبكات /30 والأصغر منها: الشبكة /32 لا تحتوي إلا على عنوان واحد، والشبكة /31 تحتوي على عنوانين، وhosts() لا تُرجع أي عنوان في الحالتين.
  • اختبر على شبكات صغيرة أولًا: قبل مسح شبكات /8 أو /16.
  • احترم القوانين: لا تمسح إلا الشبكات التي تتحكم بها.

الخاتمة

إن توليد عناوين IP في شبكة ما أو تعدادها باستخدام Python أمر بسيط بفضل ipaddress، لكن يجب أن تبقى واعيًا بمسألة الأداء في الشبكات الكبيرة. فالمولّدات وsubnets() وislice هي أفضل حلفائك لمعالجة كتل CIDR بكفاءة دون استنزاف الذاكرة. وهذه التقنيات لا غنى عنها في إدارة الأنظمة واستطلاع الشبكات واختبار البنية التحتية.

InSkillCoach

نبذة عن InSkillCoach

خبير في التدريب والتقنيات

مدرّب متخصص في التقنيات المتقدمة والذكاء الاصطناعي، تدعمه شركة GNeurone Inc.

الشهادات:

  • AWS Certified Solutions Architect – Professional
  • شهادات Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.5k
80

التعليقات

التعليقات مدعومة عبر GitHub Discussions

سجّل الدخول باستخدام GitHub للمشاركة في النقاش

تم نسخ الرابط!