قد يصبح التعامل مع عناوين IP والشبكات والشبكات الفرعية في بايثون أمرًا معقدًا، خاصةً عند التعامل مع إعدادات واقعية. تعمل وحدة ipaddress المدمجة في بايثون على تبسيط هذه العملية، مما يجعل الكود الخاص بك أكثر وضوحًا وموثوقية وأسهل في الصيانة.
لقد أمضيت سنوات في أتمتة مهام الشبكة في العمل، بدءًا من تحليل نطاقات IP في ملفات XML وحتى التحقق من تكوينات جدار الحماية. الأمثلة أدناه هي إصدارات مبسطة مستوحاة من هذه المهام الواقعية.
تعمل وحدة ipaddress المدمجة في Python على تسهيل التحقق من صحة عناوين IP والشبكات وتكرارها ومعالجتها بشكل موثوق. على الرغم من أنها جزء من المكتبة القياسية، إلا أنها قوية بشكل مدهش وغير معروفة على نطاق واسع خارج دوائر الشبكات.
في هذه المقالة، سنركز على IPv4 (IPv6 مشابه) ونستكشف الاستخدام العملي لـ Python دون التعمق في نظرية الشبكات.
لنبدأ بالأساسيات:
تمثيل عناوين IP الفردية
توفر وحدة Python ipaddress فئة عنوان IPv4 لتمثيل عناوين IP ككائنات بدلاً من سلاسل عادية. يتجنب هذا الأسلوب الأخطاء الدقيقة ويجعل التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة.
الطريقة الأكثر طبيعية لإنشاء كائن IP هي من خلال سلسلة عشرية منقطية:
import ipaddress
ip = ipaddress.IPv4Address("192.168.1.10")
print(ip)
# 192.168.1.10
نصيحة: إذا كنت لا تريد ترميز IPv4 مقابل IPv6، فاستخدم وظيفة المصنع ()ip_address، التي تكتشف ذلك تلقائيًا:
from ipaddress import ip_address
print(type(ip_address("192.168.1.10")))
# <class 'ipaddress.IPv4Address'>
print(type(ip_address("2001:db8::1")))
# <class 'ipaddress.IPv6Address'>
في هذه المرحلة، يعد ip1 وip2 كائنين حقيقيين لعنوان IPv4Address. على عكس السلاسل البسيطة، فهي تدعم المقارنات والعمليات الحسابية والتحويل إلى أعداد صحيحة:
import ipaddress
ip1 = ipaddress.IPv4Address("192.168.1.10")
ip2 = ipaddress.IPv4Address("192.168.1.20")
# Comparisons
print(ip1 < ip2) # True
print(ip2 > ip1) # True
# Arithmetic with IP addresses
print(ip1 + 1) # 192.168.1.11
# Conversion to integer
print(int(ip1)) # 3232235786
يمكنك أيضًا إنشاء كائنات IP من الأعداد الصحيحة أو البايتات:
ip_from_int = ipaddress.IPv4Address(3232235786)
ip_from_bytes = ipaddress.IPv4Address(b'\xc0\xa8\x01\x0a')
ومع ذلك، بالنسبة لمعظم المهام اليومية، يظل تنسيق السلسلة العشرية المنقطة هو الطريقة الأسهل والأكثر بديهية للعمل مع عناوين IP.
العمل مع الشبكات
بمجرد أن تعتاد على عناوين IP الفردية، فإن الخطوة التالية الطبيعية هي التعامل مع مجموعات العناوين، والمعروفة أيضًا بالشبكات. تُسهّل فئة IPv4Network في بايثون هذه العملية:
import ipaddress
net = ipaddress.IPv4Network("192.168.1.0/24")
print(net.netmask) # 255.255.255.0
print(net.broadcast_address) # 192.168.1.255
# Show the first few usable hosts
hosts = list(net.hosts())[:5]
print(hosts)
# [IPv4Address('192.168.1.1'), IPv4Address('192.168.1.2'), ...]
يمكنك إنشاء كائن IPv4Network باستخدام تدوين CIDR، وسيقوم تلقائيًا بحساب نطاقات الشبكة والمضيف. توفر خاصيتا .netmask و .broadcast_address معلومات أساسية عن الشبكة بشكل فوري.
حيلة أخرى مفيدة: يمكنك التحقق مما إذا كان عنوان IP ينتمي إلى شبكة باستخدام عامل التشغيل in:
ip = ipaddress.IPv4Address("192.168.1.10")
net = ipaddress.IPv4Network("192.168.1.0/24")
print(ip in net) # True
بمجرد حصولك على كائن الشبكة، يصبح المرور عبر جميع عناوين IP القابلة للاستخدام أمرًا بسيطًا:
for host in net.hosts():
print(host)
هنا، تُنشئ الدالة .hosts() جميع عناوين IP القابلة للاستخدام، متجاوزةً عناوين الشبكة والبث. يُسهّل هذا النهج الكائني التوجه عملية التكرار على الشبكات الفرعية أو الأجهزة المضيفة، لمهام مثل تحديثات جدار الحماية، ومسح نطاقات عناوين IP، والتحقق من صحة الأجهزة المضيفة. يمكنك الانتقال بسلاسة من العمل مع عناوين IP فردية إلى شبكات كاملة دون الحاجة إلى حساب النطاقات يدويًا أو القلق بشأن أخطاء تحديد النطاق.
الشبكات الفرعية والشبكات الكبرى
كما تسهل وحدة ipaddress استكشاف علاقات الشبكة وتقسيم الشبكات:
import ipaddress
net1 = ipaddress.IPv4Network("192.168.1.0/24")
net2 = ipaddress.IPv4Network("192.168.1.0/25")
print(net2.subnet_of(net1)) # True
print(net1.supernet_of(net2)) # True
هنا، تقوم الحلقة بعملٍ بالغ الأهمية: فهي تقسم تلقائيًا شبكة net1 إلى شبكات فرعية أصغر متساوية الحجم بناءً على new_prefix التي تُحددها. هذا يُسهّل تقسيم الشبكات، وإنشاء شبكات فرعية للاختبار، أو أتمتة إنشاء التكوين دون الحاجة إلى حساب النطاقات يدويًا.
العمل مع منافذ المضيف
أحيانًا يكون من الأنسب أو العملي التعامل مع كل من عنوان IP ومعلومات الشبكة معًا. تقوم فئة IPv4Interface في بايثون بذلك تحديدًا. على سبيل المثال، بدلًا من إدارة عنوان IP والشبكة بشكل منفصل، يمكنك ربطهما معًا في كائن واحد.
import ipaddress
iface = ipaddress.IPv4Interface("192.168.1.10/24")
print(iface.ip) # 192.168.1.10
print(iface.network) # 192.168.1.0/24
print(iface.netmask) # 255.255.255.0
يحتفظ عنصر المنفذ بمعلومات عنوان IP والشبكة معًا، مما يتيح لك استخراج معلومات الشبكة أو قناع الشبكة أو قناع المضيف بسهولة لاستخدامها في قواعد جدار الحماية أو البرامج النصية للأتمتة أو مهام الشبكة الأخرى. وهذا مفيدٌ عندما تحتاج إلى معلومات المضيف والشبكة في آنٍ واحد.
خصائص بروتوكول الإنترنت: فحص العناوين بسرعة
تأتي كائنات IPv4Address مزودة بخصائص مفيدة للتحقق من طبيعة العنوان:
- is_private. : صحيح للشبكات الخاصة (على سبيل المثال، 192.168.x.x)
- is_reserved. : صحيح للعناوين المحجوزة من قبل IANA
- is_global. : صحيح للعناوين القابلة للتوجيه عالميًا
مثال:
ip = ipaddress.IPv4Address("192.168.1.10")
print(ip.is_private) # True
print(ip.is_reserved) # False
print(ip.is_global) # False
هذه الخصائص تجعل برامج التصفية والتحقق والأتمتة بسيطة وأقل عرضة للأخطاء.
أنماط عملية للاستخدام اليومي
هذه هي أنواع المكاسب السريعة التي ستجد نفسك تستخدمها كثيراً:
- تصفية عناوين IP الخاصة: مفيد إذا كنت تريد فقط عناوين عامة لتسجيل البيانات أو المراقبة.
ips = ["192.168.1.1", "8.8.8.8", "10.0.0.1"]
private_ips = [ip for ip in ips if ipaddress.IPv4Address(ip).is_private]
print(private_ips)
# ['192.168.1.1', '10.0.0.1']
- التكرار عبر شبكات متعددة: مثالي للعمليات الجماعية مثل المسح الضوئي أو إنشاء تكوينات جدار الحماية.
nets = ["192.168.1.0/24", "10.0.0.0/24"]
for n in nets:
net = ipaddress.IPv4Network(n)
for host in net.hosts():
print(host)
تتوسع هذه الأنماط الصغيرة بشكل جيد عند أتمتة عمليات سير العمل الأكبر.
التلخيص المتقدم باستخدام netaddr
للحصول على تجميع شبكات أكثر تقدماً، تُكمل مكتبة netaddr التابعة لجهة خارجية عنوان IP من خلال توفير أدوات لدمج شبكات متعددة وتلخيصها بكفاءة.
pip install netaddr
from netaddr import cidr_merge, IPNetwork
nets = [IPNetwork('192.168.0.0/24'), IPNetwork('192.168.1.0/24'), IPNetwork('10.0.0.0/24')]
summarized = cidr_merge(nets)
print(summarized)
# [IPNetwork('10.0.0.0/24'), IPNetwork('192.168.0.0/23')]
يدمج تلقائيًا الشبكات المتداخلة أو المتجاورة، مما يقلل من التعقيد عند إدارة قوائم الشبكات الكبيرة. استخدم عنوان IP للشبكات/المضيفين الفردية، وعنوان الشبكة للتجميع.
قد لا تكون وحدة ipaddress في بايثون معروفة على نطاق واسع لجميع المطورين، لكنها أداة قوية وفعالة وشاملة ضمن المكتبة القياسية. سواءً أكان الأمر يتعلق بالتحقق من صحة العناوين، أو استعراض المضيفين، أو تقسيم الشبكات أو دمجها، أو أتمتة المهام المتعلقة ببروتوكول الإنترنت، فإنها تُبسط التعليمات البرمجية، وتقلل الأخطاء، وتوفر الوقت.
حتى لو كنت قد استخدمته من قبل، فإن الأمثلة هنا ستساعدك على كتابة برامج نصية أكثر وضوحًا وكفاءة، وستضفي على مشاريعك موثوقية احترافية. ابدأ بالتجربة، وسترى كيف سيصبح أداة أساسية في مجموعة أدوات الشبكات الخاصة بك في بايثون.
اكتشاف المزيد من بايثون العربي
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.