الاثنين، 20 سبتمبر 2021

بايثون للشبكات : برنامج يستخدم برتوكول ARP لعرض جميع الأجهزة المتصلة على الشبكة المحلية

 بسم الله الرحمن الرحيم

الحصول على عنوان الأنترنت الخاص بالإجهزة على الشبكة هو الخطوة الأولى لكي تبدأ عملية اكتشاف نقاط الضعف في هذه الأجهزة , و في هذه التدوينة سوف نبني برنامج بايثون يقوم بهذه المهمة , و هنا يأتي السؤال لماذا ؟ , ألا يوجد برامج تقوم بهذا العمل و تغني عن هذا المجهود , الأجابة نعم  لكن افضل طريقة للتعلم هو التطبيق, سنبدأ أولا بشرح نظري للطريقة التي سنستخدمها مع نظرة لبرتوكول ARP , ثم تثبيت مكتبة Scapy في ويندوز و لينكس و أخيرا سوف نقوم بكتابة سكريبت يقوم باستخدام بروتوكول ARP لكشف الأجهزة المتصلة .


  • نظرة لبرتوكول ARP :

Address Resolution Protocol أو أختصاراً (ARP) , هو برتوكول يهدف لعرض العنوانين الفزيائية أو ما يسمى بعنوان MAC المرتبط بعنوان الأنترنت ( IP Address ) و العكس صحيح .

لنفترض بأنك تريد الاتصال بكمبيوتر يوجد على الشبكة المحلية و لديك عنوان الأنترنت (IP) فتحصل الخطوات التالية :
  1. سيبحث جهازك عن العنوان الفزيائي في جدول العناوين الموجود على النظام  والمسمى ARP Caching Table .
  2. في حالة وجود هذا العنوان في الجدول سوف يتم الأعتماد عليه بدون ارسال طلب ARP .
  3. في حالة عدم وجود العنوان سوف يرسل الجهاز طلب ARP Request لجميع الأجهزة المتصلة (Broadcast message).
  4. جهاز الــ"switch" سيقوم بأرسال هذه الرسالة لجميع المنافذ النشطة ما عدا المنفذ الذي تم منه الأرسال .
  5. عند وصول الرسالة إلى الجهاز الذي يحمل عنوان الأنترنت المطابق سوف يرد برسالة تحمل عنوانه الفيزيائي .
  6. في حالة عدم وجود جهاز يحمل عنوان الأنترنت على الشبكة المحلية سوف ينتهي وقت انتظار الرد و يفترض الجهاز المرسل بأنه لا وجود لهذا الجهاز .

هذه صورة لطلب ARP Request من برنامج wireshark , تلاحظ بساطة البروتوكول :


 الرد في برتوكول يكون العنوان البديل لعنوان البث (Broadcast ) و سوف تكون الرسالة موجهة بشكل  مباشر للمرسل (Unicast) ونوع الرسالة Opcode هو Reply .


هذا شرح مبسط جدا لهذا البرتوكول , و السبب لوجوده بأن الرسائل داخل الشبكة المحلية يتم تبدلها بواسطة برتوكول Ethernet  الذي يعمل في طبقة ربط البيانات (Data Link) والذي يستخدم العنوان الفيزيائي للاتصال  , كما يظهر لك نموذج OSI .


هنا قد تتساءل لماذا لا نستخدم برتوكول ICMP و اشهر تطبيقاته و هو الأمر Ping في انظمة ويندوز و لينكس , السبب هو أن الكثير من الأجهزة مثل الهواتف الذكية و جدران النار تحظر هذا البرتوكول و تقوم بمنع الرد على رسائله, أما في حالة برتوكول ARP فمن الصعب تعطيله لأنه اساسي لعملية الأتصال كما رأيت .


  • تثبيت مكتبة Scapy 

مكتبة Scapy هي مكتبة متخصصة في بناء و ارسال حزم شبكات معدلة و ارسالها عبر الشبكة , امكانيات هذه المكتبة كبيرة جداٌ و تعطي المبرمج امكانيات رائعة .

التثبيت في نظام لينكس :

لمستخدمي توزيعة Ubuntu أو اي توزيعة تستخدم مدير الحزم Apt فقط اكتب الأمر في موجه الأوامر :

sudo apt-get install scapy


التثبيت في نظام ويندوز :

لتثبيت في ويندوز سوف نستخدم توزيعة البايثون Anaconda , هذه التوزيعة من الأشهر في مجال علم البيانات ( Data sciences ) و ما يميزها هو سهولة تثبيت المكتبات و وجود محرر ممتاز لذا سوف نستخدمها في حالتنا .

  1. قم بتنزيل التوزيعة من الموقع الرسمي ( https://www.anaconda.com/products/individual-d ) .
     
    2. اتبع خطوات التثبيت 
     



    3. تأكد من تفعيل خيار أضافة مجلد التثبيت إلى متغير مسار البرامج ( PATH )


 4. بعد أنتهاء التثبيت قم بتشغيل برنامج Anconda من القائمة Start 




5. عندما ينتهي تحميل البرنامج ستظر لم نافذة كالتالي :



6. أختر من القائمة على اليمين Enviroments :





7. و لتحديث قائمة المكتبات أضغط "Update Index" و غير العرض إلى جميع المكتبات ثم أبحث عن المكتبة scapy و اضغط في اسفل المكتبة على الخيار Apply :

 
للتأكد من نجاح التثبيت قم بتشغيل موجه الأوامر الخاص بالمكتبة Scapy في نظام ويندوز من القائمة Start أكتب في مربع البحث أكتب "Cmd" و أختر "Run as Administrator" :
 

 اكتب في موجه الأوامر Scapy أذا ظهر لك موجه الأوامر كالتالي فيعني أننا نجحنا في التثبيت :


في نظام ليكنس فقط أكتب الأمر كالتالي , يجب أن يظهر لك موجه الأوامر مشابه لما في ويندوز :

sudo scapy


  • الموجه التفاعلي لمكتبة Scapy

    قبل أن نكتب السكريبت في بايثون سوف نستغل خاصية الموجه الأوامر في Scapy و الذي هو عبارة عن موجه python مع تفعيل المكتبة Scapy.
     
    هذه الخاصية اعتبرها من الأمكانيات الممتازة حيث يمكن تجريب و التعديل بشكل مباشر و سريع لكي تتأكد من نجاح برنامجك.

    لنبدأ أولا بأنشاء الاساس في أطار الشبكة الخاصة ببرتوكول ARP , البرتوكول مبنى و مضمن في أطار ايثرنت (Ethernet Frame) .
    * يجب أن أنوه بأن برتوكول ARP مستخدم في أكثر من أطار للشبكات , ولكن للشبكات المحلية الأطار المستخدم هو ايثرنت .
     
    و لكن قبل أن ننشىء هنا عرض مبسط لمكونات الإطار و شرح لها :

    المصدر :https://commons.wikimedia.org/wiki/File:Ethernet_II_Frame_Structure.png


    هذه الصورة لإطار ايثرنت ( اقصد بالإطار Frame و هي الكلمة المستخدمة للحزم في الطبقة الثانية من OSI للشبكات ) و الشرح ببساطة :

    1. Preamble : هو مجموعة 56 بايت تستخدم لمزامنة ساعة المستقبل على نفس ساعة المرسل ( Clock Sync )  و هنا لا نعني التوقيت كالوقت و التاريخ , هذا المصطلح يخص الإلكترونيات , و هذا النطاق يخص الطبقة الأولى من من OSI وسوف اتجنب شرحها لكي لا أعقد الموضوع .
    2. SFD : اختصار لــ  Start Frame Delimiter بداية البيانات الخاص بالإطار أيضا يقع في الطبقة الأولى من OSI .
    3. Destination Address : العنوان الفيزيائي للبطاقة الشبكة (Mac Address ) المرسل لها البيانات يتكون من 6 بايتات يتم عرضه بتمثيل Hexadecimal و فصل بين كل بايت بـ ":" .
    4.  Source Address : العنوان الفيزيائي للبطاقة الشبكة (Mac Address ) المرسل منها البيانات يتكون من 6 بايتات ايضا و يتبع نفس التمثيل كما في العنوان المرسل له .
    5. النوع : بحسب البرتوكول المستخدم في حالتنا سيكون ARP و سيحمل القيمة 0x0806.
    6.  البيانات : البيانات الفعلية
    7. FCS : هذه القيمة تمثل ناتج معادلة تأكد للمرسل أذا حدث خطأ في نقل البيانات , حيث يتم تنفيذ نفس المعادلة في المرسل و المستقبل و في حالة أختلاف القيمة في المرسل يتم أفتراض حصول خطأ .


    في Scapy يمكن الوصول إلى العنوان المرسل و المستقبل و البيانات و النوع , و FCS متروكين للنظام أما Preamble و SFD فهما متروكين لبطاقة الشبكة .
     
    لإنشاء أطار Ethernet في Scapy فقط استخدم الأمر التالي الذي سوف ينشأ أطار Ethernet و يسنده إلى المتغير الخاص بنا:
myFrame = Ether()

لعرض مجتويات هذا الأطار فقط أستخدم الدالة show كالتالي :

myFrame.show()

سيعرض لك القيم التي تستطيع تغيرها في الإطار كالتالي :
###[ Ethernet ]###
dst= ff:ff:ff:ff:ff:ff
src= 11:36:12:54:14:49
type= 0x9000


العنوان الذي في خانة dst و الخاص بإطار Ethernet هو عنوان broadcast و معناه أرسال هذه الرسالة لجميع المنافذ ما عدا المنفذ المرسل , في نظام ويندوز لن يكون هذا العنوان للمرسل , للتغيير فقط قم بدخل للمتغير dst في كائن (Object) الإيثرنت الذي إنشائنا :


myFrame.dst = "ff:ff:ff:ff:ff:ff"

أما عنوان المرسل فالمكتبة تستخدم عنوانك الفيزيائي للبطاقة المستخدمة , في حالة برنامجنا فهذا هو المطلوب .

و الأن قد تتساءل لماذا لم نغير نوع الاطار (Frame) لنوع أطار برتوكول ARP , لكي تعرف السبب سوف نضيف طبق برتوكول ARP للإطار الذي تم إنشائه :

myFrame = myFrame / ARP()

الأن قم بعرض الإطار بأستخدام الدالة show و لاحظ التغير :

>>> myFrame.show()
###[ Ethernet ]###
dst= ff:ff:ff:ff:ff:ff
src=
11:36:12:54:14:49 
  type= ARP
###[ ARP ]###
hwtype= 0x1
ptype= IPv4
hwlen= None
plen= None
op= who-has
hwsrc=
11:36:12:54:14:49 
     psrc= 192.168.1.148
hwdst= 00:00:00:00:00:00
pdst= 0.0.0.0

>>


هل لاحظت نوع إطار الإيثرنت , لقد تغير إلى ARP , بدون أي داعي من قبلك لتغيير أي شيء , كما أن طريقة العرض و الأضافة كطبقات تسهل عملية الأضافة و البرمجة .
نوع ARP هنا تجده في القيمة op هو who-has هو طلب استفسار عن العنوان الفيزيائي لعنوان أنترنت و هو المطلوب لبرنامجنا لذا لن نغير أي شيء , العنوان الفيزيائي للجهة المرسل إليها في الطبقة الخاصة ببرتوكول ARP هي 00:00:00:00:00:00 و هو ايضا عنوان خاص بالإرسال إلى الكل (broadcast) .

نحتاج فقط لوضع عنوان الأنترنت الذي نريد التأكد من وجوده في الشبكة المحلية , نستطيع أن نكتب عنوان واحد كالتالي :

myFrame.pdst = "192.168.1.114"

و لكن تذكر نريد أن نعرض جميع الأجهزة المتصلة , قد تقترح أن تقوم بعمل حلقة تكرارية (Loop) كالتالي :

for i in range(1,254):
    myFrame.pdst = "192.168.1." + str(i) 
    #الإرسال هنا و الاستقبال - سنضيف ذلك  
 
 هذا حل جيد و لكن هنالك طريقة أفضل فمكتبة Scapy توفر أمكانية استخدام المدى لعنوانين الأنترنت فنكتب كالتالي :


myFrame.pdst = "192.168.1.0/24"

 و الأن إلى الأرسال و عرض النتائج باستخدام الدالة srp التي تقوم لنا بعملية الأرسال و الأستقبال حرف p في نهاية اسم الدالة يدل على أنها ترسل و تستقبل في الطبقة الثانية ( Data Link ) من نموذج OSI , هذه الدالة ترجع Tuple يحتوي على الطلبات التي تم الأستجابة لها و التي تم رفضها , لكي تقوم بتجاهل الطلبات التي تم تجاهلها فقط أستبدل اسم المتغيرunanswered بـ _ :

answered , unanswered = srp(myFrame,timeout2)

وهنا الأمر بعد التعديل لتجاهل الطلبات التي لم يتم الرد عليها :
 


answered , _ = srp(myFrame,timeout2)
 
 لعرض النتائج تستطيع استخدام الدالة summary الموجودة في المكتبة كالتالي :

answered.summary()

لتقليل البيانات المعروضة استخدم هذا الحلقة التكرارية , سوف نقوم بدوران في القائمة التي لدينا و التي تحتوي على tuple يحتوي على البيانات المرسلة و المستقبلة   و سوف نقوم بتجاهل ما تم ارسالها و عرض فقط الردود :

for _ , recv in answered :
    print(recv.summary())
 

 
هذا الخطوات هي ببساطة ما سوف يقوم به السكريبت , الأن سوف نضع هذه الأوامر في سكريبت .
 
 
  • السكريبت النهائي :

 
#!/usr/bin/env python
import sys
from scapy.all import srp,Ether,ARP,conf

#الحصول على مدى عنوانين الشبكة او في حالة وجود عنوان واحد

if len(sys.argv) != 2:
    print("Usage:arping.py <Net or IP> Ex. 192.168.1.0/24 or 192.168.1.10")
    exit(1)
#ايقاف  عرض البيانات الأضافية الخاصة بعملية الأرسال 
conf.verb = 0

target = sys.argv[1]
pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=target)

#في حالة وجود خطأ في عنوان الأنترنت أو المدى
try:
    answerd, _ = srp(pkt,timeout=4)
except Exception as e:
    print("Error: " + e.__class__, " occurred.")
    exit(2)



for _ , recv in answerd :
    #عرض فقط عنوان الانترنت الخاص بالمرسل
    #أذا اردت معلومات أكثر استخدم summary 
    print("IP:" + recv.psrc) 
 
 
 
 
 لتشغيل السكريبت في ويندوز , افنح موجه أوامر خاص بمدير النظام ثم أكتب python متبوعا بمسار الملف الذي حفظته :

python C:\Users\abgoor\Desktop\arping.py 192.168.1.0/24

 أما في نظام لينكس فيجب أن تحول الملف لملف تنفيذي باستخدام الأمر chmod ثم لتنفيذ الأمر استخدم النقطة "." ثم مسار الملف :
 
 
chmod +x /home/abgoor/script/arping.py

. /home/abgoor/script/arping.py 192.168.1.0/24
 
 
  • الخاتمة

    احساس الإنجاز شعور جميل , رغم بساطة برنامجنا إلا أنه يعمل و بشكل جيد , طبعا أريد منك أنك تحاول تطور البرنامج و في الأخير هذا لن يكون الموضوع الأخير عن مكتبة Scapy , هذه المكتبة تعطيك اختيارات غير محدودة في برمجة الشبكات, و أن شاء الله سوف نحاول نغطي هذه الإمكانيات في أكثر من موضوع .
    أذا اعجبك الموضوع طلب بسيط دعوة طيبة منك تكفي :-) .
     

ليست هناك تعليقات:

إرسال تعليق