أتمتة Nmap: دمج Nmap مع Python لكتابة أداة فحص منافذ مخصصة


أتمتة Nmap: دمج Nmap مع Python لكتابة أداة فحص منافذ مخصصة

أتمتة Nmap: دمج Nmap مع Python لكتابة أداة فحص منافذ مخصصة

مرحباً أيها المطورون! اليوم سنتعلم كيفية بناء أداة فحص منافذ مخصصة وفعالة باستخدام قوة Nmap ومكتبة python-nmap، مما يتيح لنا أتمتة مهام الفحص بطريقة برمجية مرنة.

1. التحضير الأولي وتثبيت المكتبات

قبل أن نبدأ، نحتاج إلى التأكد من تثبيت Nmap على نظامنا ومكتبة python-nmap التي ستكون الجسر بين Python و Nmap. إذا لم يكن Nmap مثبتاً، يمكنك تثبيته باستخدام مدير الحزم الخاص بنظام التشغيل لديك (مثل sudo apt install nmap لأوبونتو).

ملاحظة تقنية: مكتبة python-nmap هي مجرد غلاف (wrapper) لأداة Nmap الأصلية. هذا يعني أن Nmap يجب أن يكون مثبتاً وقابلاً للتشغيل من سطر الأوامر حتى تعمل المكتبة بشكل صحيح.

لتثبيت مكتبة python-nmap، استخدم الأمر التالي:

pip install python-nmap

لنبدأ باستيراد المكتبة وإنشاء كائن PortScanner:

import nmap # استيراد مكتبة nmap في بايثون
import argparse # لاستقبال وسائط سطر الأوامر

# إنشاء كائن PortScanner
nm = nmap.PortScanner()

2. بناء وظيفة فحص المنافذ الأساسية

الآن سنقوم بإنشاء دالة تقوم بإجراء عملية الفحص الفعلية. ستأخذ هذه الدالة عنوان IP أو اسم المضيف ونطاق المنافذ كمدخلات، ثم تستخدم Nmap لإجراء الفحص واستخراج المعلومات ذات الصلة.

def custom_port_scan(target_host, port_range):
    print(f"[*] بدء فحص المنافذ لـ: {target_host} على النطاق: {port_range}")
    try:
        # تنفيذ فحص Nmap
        # -sS: فحص SYN (افتراضي، سريع ومخفي نسبياً)
        # -sV: اكتشاف إصدار الخدمة
        # -O: اكتشاف نظام التشغيل
        # -p: تحديد نطاق المنافذ
        nm.scan(hosts=target_host, ports=port_range, arguments='-sS -sV -O')

        # التحقق مما إذا كان المضيف نشطاً
        if target_host not in nm.all_hosts():
            print(f"[-] المضيف {target_host} غير مستجيب أو غير موجود.")
            return

        # طباعة حالة المضيف
        host_status = nm[target_host].state()
        print(f"[*] حالة المضيف {target_host}: {host_status}")

        # التكرار عبر البروتوكولات (TCP، UDP)
        for proto in nm[target_host].all_protocols():
            print(f"[*] البروتوكول: {proto.upper()}")
            lport = nm[target_host][proto].keys() # الحصول على قائمة المنافذ
            sorted_ports = sorted(lport) # ترتيب المنافذ

            if not sorted_ports:
                print(f"    لا توجد منافذ مفتوحة للبروتوكول {proto.upper()}.")
                continue

            for port in sorted_ports:
                port_info = nm[target_host][proto][port]
                state = port_info['state'] # حالة المنفذ (open, closed, filtered)
                service = port_info.get('name', 'N/A') # اسم الخدمة
                product = port_info.get('product', 'N/A') # المنتج
                version = port_info.get('version', 'N/A') # الإصدار

                print(f"    [+] المنفذ: {port}/{proto} \tالحالة: {state} \tالخدمة: {service} \tالمنتج: {product} \tالإصدار: {version}")

    except nmap.PortScannerError as e:
        print(f"[-] خطأ في Nmap: {e}")
    except Exception as e:
        print(f"[-] حدث خطأ غير متوقع: {e}")
    finally:
        print(f"[*] انتهى فحص المنافذ لـ: {target_host}")

3. إضافة دعم لوسائط سطر الأوامر (CLI Arguments)

لجعل أداتنا أكثر مرونة وسهولة في الاستخدام، سنضيف دعمًا لوسائط سطر الأوامر باستخدام مكتبة argparse. هذا سيسمح للمستخدمين بتحديد المضيف ونطاق المنافذ مباشرة عند تشغيل السكربت.

if __name__ == "__main__":
    # إعداد محلل الوسائط
    parser = argparse.ArgumentParser(description="أداة فحص منافذ مخصصة باستخدام Nmap و Python.")
    parser.add_argument("-t", "--target", dest="target_host", help="عنوان IP أو اسم المضيف الهدف.", required=True)
    parser.add_argument("-p", "--ports", dest="port_range", help="نطاق المنافذ للفحص (مثال: '1-1024' أو '80,443').", default="1-1024")

    args = parser.parse_args() # تحليل الوسائط المدخلة

    # استدعاء دالة الفحص
    custom_port_scan(args.target_host, args.port_range)
ملاحظة تقنية: if __name__ == "__main__": يضمن أن الكود الموجود داخل هذه الكتلة سيتم تنفيذه فقط عندما يتم تشغيل السكربت مباشرة، وليس عند استيراده كوحدة نمطية.

الكود النهائي الكامل

إليك الكود المجمع لأداتنا القابلة للتشغيل:

import nmap # استيراد مكتبة nmap في بايثون
import argparse # لاستقبال وسائط سطر الأوامر

# إنشاء كائن PortScanner
nm = nmap.PortScanner()

def custom_port_scan(target_host, port_range):
    print(f"[*] بدء فحص المنافذ لـ: {target_host} على النطاق: {port_range}")
    try:
        # تنفيذ فحص Nmap
        # -sS: فحص SYN (افتراضي، سريع ومخفي نسبياً)
        # -sV: اكتشاف إصدار الخدمة
        # -O: اكتشاف نظام التشغيل
        # -p: تحديد نطاق المنافذ
        nm.scan(hosts=target_host, ports=port_range, arguments='-sS -sV -O')

        # التحقق مما إذا كان المضيف نشطاً
        if target_host not in nm.all_hosts():
            print(f"[-] المضيف {target_host} غير مستجيب أو غير موجود.")
            return

        # طباعة حالة المضيف
        host_status = nm[target_host].state()
        print(f"[*] حالة المضيف {target_host}: {host_status}")

        # التكرار عبر البروتوكولات (TCP، UDP)
        for proto in nm[target_host].all_protocols():
            print(f"[*] البروتوكول: {proto.upper()}")
            lport = nm[target_host][proto].keys() # الحصول على قائمة المنافذ
            sorted_ports = sorted(lport) # ترتيب المنافذ

            if not sorted_ports:
                print(f"    لا توجد منافذ مفتوحة للبروتوكول {proto.upper()}.")
                continue

            for port in sorted_ports:
                port_info = nm[target_host][proto][port]
                state = port_info['state'] # حالة المنفذ (open, closed, filtered)
                service = port_info.get('name', 'N/A') # اسم الخدمة
                product = port_info.get('product', 'N/A') # المنتج
                version = port_info.get('version', 'N/A') # الإصدار

                print(f"    [+] المنفذ: {port}/{proto} \tالحالة: {state} \tالخدمة: {service} \tالمنتج: {product} \tالإصدار: {version}")

    except nmap.PortScannerError as e:
        print(f"[-] خطأ في Nmap: {e}")
    except Exception as e:
        print(f"[-] حدث خطأ غير متوقع: {e}")
    finally:
        print(f"[*] انتهى فحص المنافذ لـ: {target_host}")

if __name__ == "__main__":
    # إعداد محلل الوسائط
    parser = argparse.ArgumentParser(description="أداة فحص منافذ مخصصة باستخدام Nmap و Python.")
    parser.add_argument("-t", "--target", dest="target_host", help="عنوان IP أو اسم المضيف الهدف.", required=True)
    parser.add_argument("-p", "--ports", dest="port_range", help="نطاق المنافذ للفحص (مثال: '1-1024' أو '80,443').", default="1-1024")

    args = parser.parse_args() # تحليل الوسائط المدخلة

    # استدعاء دالة الفحص
    custom_port_scan(args.target_host, args.port_range)

النتيجة المتوقعة

عند تشغيل السكربت من سطر الأوامر، ستقوم الأداة بإجراء فحص للمضيف ونطاق المنافذ المحددين، وستطبع النتائج إلى الشاشة بتنسيق منظم. على سبيل المثال، لتشغيل فحص على scanme.nmap.org للمنافذ 80 و 443 و 22، يمكنك استخدام الأمر التالي:

python your_scanner.py -t scanme.nmap.org -p 22,80,443

ستكون النتيجة مشابهة لما يلي (قد تختلف تفاصيل الإصدار والخدمة):

[*] بدء فحص المنافذ لـ: scanme.nmap.org على النطاق: 22,80,443
[*] حالة المضيف scanme.nmap.org: up
[*] البروتوكول: TCP
    [+] المنفذ: 22/tcp \tالحالة: open \tالخدمة: ssh \tالمنتج: OpenSSH \tالإصدار: 7.7 (protocol 2.0)
    [+] المنفذ: 80/tcp \tالحالة: open \tالخدمة: http \tالمنتج: Nginx \tالإصدار: 1.14.0
    [+] المنفذ: 443/tcp \tالحالة: open \tالخدمة: https \tالمنتج: Nginx \tالإصدار: 1.14.0
[*] انتهى فحص المنافذ لـ: scanme.nmap.org

بهذا، تكون قد بنيت أداة فحص منافذ مخصصة وقوية باستخدام Python و Nmap، مما يفتح لك الباب لأتمتة العديد من مهام الأمن السيبراني.