خادم DHCP الأصلي باستخدام باش

أحب أتمتة العملية وأكتب دراجاتي الخاصة لدراسة هذه المادة أو تلك. كان هدفي الجديد هو خادم DHCP الذي سيصدر عنوانًا في الشبكات الصغيرة بحيث يمكن إجراء التكوين الأولي للمعدات.

في هذه المقالة سأتحدث قليلا عن بروتوكول DHCP وبعض التفاصيل الدقيقة من باش.



النتيجة النهائية


لنبدأ من النهاية ، بحيث يكون من الواضح ما نحارب من أجله.

مظاهرة العمل:



مستودع مع البرنامج النصي: firemoon777 / باش خادم DHCP

المشكلة الأولية


تتم التهيئة التي أحتاجها بهذه الطريقة: نقوم بالاتصال مباشرة عبر زوج ملتوي إلى الجهاز ، وإصدار عنوان مؤقت عبر DHCP ، وتهيئته باستخدام برنامج نصي تم إنشاؤه بالفعل. وحتى عشرة إلى عشرين مرة على التوالي.

بالنسبة للكثيرين ، يقوم isc-dhcp-server المعروف بعمله على أكمل وجه ، ولكن ، للأسف ، لا يخطر البرنامج النصي الخاص بي أن العنوان قد صدر ، لذلك تحتاج إلى حظر التنفيذ بطريقة ما حتى يتم إصدار العنوان.

يبدو أن الحل موجود على السطح: ping حتى اللون الأزرق في الوجه ، حتى يستجيب الجهاز:

while ! ping -c1 -W1 "$DHCP" | grep -q "time=" do echo "Waiting for $DHCP..." done 

لكن هذا القرار يفتقر بالتأكيد إلى المغامرة.

الجزء النظري


الحصول على عنوان مع خادم DHCP واحد



يعمل بروتوكول DHCP عبر UDP على المنفذين 67 و 68. يعمل الخادم دائمًا فقط عند 67 ، والعميل فقط عند 68. نظرًا لأن العميل ليس لديه عنوان (لديه عنوان 0.0.0.0) ، يتم بث حزم DHCP. أي يرسل العميل دائمًا الحزم إلى العنوان 255.255.255.255:67 من العنوان 0.0.0.0:68 ، ويرسل الخادم من عنوانه: 67 إلى العنوان 255.255.255.255:68.

يتلقى العميل العنوان في أربع حزم ( DORA ):

  1. يكتشف العميل مكان خادم DHCP ( D iscover)
  2. يستجيب الخادم ويقدم عنوانه ( O ffer)
  3. يطلب العميل العنوان المقترح من خادم معين ( R equest)
  4. يوافق الخادم ويصدر العنوان ( A ck)

بصريا ، يمكن تمثيل المخطط على النحو التالي:



الحصول على عنوان مع خوادم DHCP متعددة



عندما يرسل العميل اكتشاف ، ترسل جميع الخوادم التي يمكنها سماع عرضها إلى العميل. ولكن يجب على العميل اختيار واحد. يتم الإعلان عن اختيار العميل في رسالة الطلب مع الخيار 54 (خادم DHCP) ، والذي يحتوي على عنوان IP لخادم DHCP المفضل. على الرغم من أن الطلب يتم إرساله أيضًا إلى كل شخص على الشبكة ، إلا أن خادم DHCP الذي تم تحديد عنوان IP الخاص به في الخيار 54 سوف يستجيب.



محتويات حزمة DHCP


تتكون حزمة DHCP من جزأين: ثابت ، 236 بايت ، متغير يحمل خيارات (خيار DHCP).

الجدول مع جميع الحقول من حزمة DHCP من ويكيبيديا
المجالالوصفالطول (بالبايت)
المرجع السابق
نوع الرسالة. على سبيل المثال ، يمكن أن يستغرق القيم: BOOTREQUEST (0x01 ، طلب من عميل إلى خادم) و BOOTREPLY (0x02 ، استجابة من خادم إلى عميل).
1
htype
نوع عنوان الجهاز. يتم تعريف القيم الصالحة لهذا الحقل في أرقام RFC 1700 المخصصة. على سبيل المثال ، بالنسبة لعنوان MAC Ethernet ، يتم تعيين هذا الحقل على 0x01.
1
hlen
طول عنوان الجهاز بالبايت. عنوان Ethernet MAC هو 0x06.
1
القفزات
عدد أجهزة التوجيه الوسيطة (ما يسمى عوامل ترحيل DHCP ) التي مرت الرسالة من خلالها. يعين العميل هذا الحقل إلى 0x00.
1
xid
معرف معاملة فريد من 4 بايت تم إنشاؤه بواسطة العميل في بداية عملية الحصول على العنوان.
4
ثوانى
الوقت بالثواني منذ بدء عملية الحصول على العنوان. لا يمكن استخدامها (في هذه الحالة يتم ضبطه على 0x0000).
2
أعلام
مجال الأعلام هو معلمات خاصة لبروتوكول DHCP.
2
كادر
عنوان IP للعميل. يتم ملؤه فقط إذا كان لدى العميل بالفعل عنوان IP خاص به وكان قادرًا على الاستجابة لطلبات ARP (هذا ممكن إذا نفذ العميل الإجراء الخاص بتحديث العنوان بعد انتهاء مدة عقد الإيجار).
4
yiaddr
عنوان IP للعميل الجديد المقترح من قبل الخادم.
4
siaddr
خادم عنوان IP. عاد في بند DHCP (انظر أدناه).
4
giaddr
عنوان IP الخاص بعامل الترحيل ، إذا كان أحد المشاركين في عملية توصيل رسالة DHCP إلى الخادم.
4
شادر
عنوان الجهاز (عادة ما يكون عنوان MAC) للعميل.
16
اسم
اسم الخادم الاختياري كسلسلة منتهية فارغة.
64
ملف
اسم ملف خادم اختياري تستخدمه محطات العمل الخالية من الأقراص عند التنزيل عن بُعد. مثل sname ، يتم تمثيله كسلسلة منتهية بقيمة خالية.
128
خيارات
مجال خيارات DHCP . يشار إلى خيارات التكوين الإضافية المختلفة هنا. في بداية هذا الحقل ، تتم الإشارة إلى أربع بايتات خاصة بقيم 99 و 130 و 83 و 99 ("أرقام سحرية") ، مما يسمح للخادم بتحديد وجود هذا الحقل. يحتوي الحقل على طول متغير ، لكن يجب أن يكون عميل DHCP جاهزًا لتلقي رسالة DHCP سعة 576 بايت (في هذه الرسالة ، يبلغ طول حقل الخيارات 340 بايت).
متغير


قائمة بجميع خيارات DHCP في RFC 2132

يتم ترميز خيارات DHCP كما يلي:
رقمطولالبيانات

على سبيل المثال ، المعلمة 3 (البوابة المقترحة) بقيمة 10.0.0.1:
3410001

في حال احتجت إلى تمرير العديد من المعلمات ، يزداد طول المعلمة.
على سبيل المثال ، في المعلمة 6 (خادم DNS) ، سننقل عنوانين (1.1.1.1 و 8.8.4.4):
6811118844

علامة نهاية حقل الخيار هي معلمة برقم 255 (0xFF) وطول 0.

في أغلب الأحيان ، يضع العميل المعلمة 55 (قائمة المعلمات التي يريد تلقيها استجابة) في DHCP Discover ، ومع ذلك ، يحق لنا أن نمنحه ليس كل ما طلبه.

الجزء العملي


تم التخطيط أصلاً لكتابة الخادم بلغة أكثر ملائمة (C) لهذا ، ومع ذلك ، سيكون الأمر بسيطًا وبسيطًا. إنها إما مسألة كتابة نصوص تتولى مهام خادم dhcp.

التبسيط


نظرًا لأنه كان من المفترض أن يتم استخدام الخادم الذي يتم تطويره في شبكات من عقدتين متصلتين برقع ، فقد تم اعتماد التبسيط التالي:

  • يضمن أن عميل واحد على الشبكة ؛
  • يتم ضمان عدم وجود المزيد من خوادم dhcp في الشبكة
  • البادئ يقرر أي عنوان لإصداره
  • يتم تجاهل إصدار DHCP ورفض DHCP

المستمع


بادئ ذي بدء ، تحتاج إلى معرفة كيفية تلقي الحزم. وهذا يتطلب مستمع متعاطف معتمد ، على سبيل المثال ، nc. ولكن ليس كل nc مناسبة لهذه الأغراض. يعد OpenBSD netcat 1.130 من دبيان مناسبًا ، ولكن رحل 1.105 مع Ubuntu. قم بتشغيل nc للاستماع إلى جميع حزم UDP التي تصل إلى المنفذ 67.

 nc -l 0.0.0.0 -up 67 -w0 

هناك حاجة أيضًا إلى OpencatD netcat بسبب رمز التبديل -w بقيمة 0. بعد تلقي حزمة واحدة (UDP Broadcast) ، لا يتلقى nc التقليدي مزيدًا من الحزم ، لكنه لا ينتهي.

معالجة البايت الخام


في الغلاف ، من الصعب جدًا التعامل مع الأحرف غير القابلة للطباعة ، مثل الأحرف الفارغة: إنه يتجاهلها ببساطة. تحتوي حزمة DHCP على العديد من وحدات البايت 0x00 (على سبيل المثال ، حقل الملف). يأتي حل المشكلة في شكل تفريغ سداسي عشرية:

  nc -l 0.0.0.0 -up 67 -w0 | stdbuf -o0 od -v -w1 -t x1 -An 

بايت واحد لكل سطر ، دون إخراج العنوان ، دون تخطي وحدات البايت المكررة. يمكنك أيضًا توابل stdbuf -o0 بحيث لا يتم تخزين المخزن مؤقتًا.

تلقي وتخزين ومعالجة الحزم


من أمر الأمر od ، يتم أخذ وحدات البايت بواسطة أمر القراءة وإضافتها إلى صفيف.

 msg=() for i in {0..235}; do read -r tmp msg[$i]=$tmp done 

على الرغم من أن جميع القيم يتم إرسالها بترميز سداسي عشري ، إلا أنه من الأفضل عرض رقم خيار DHCP وطول الخيار على الشاشة / في السجلات بالصيغة العشرية المعتادة. للقيام بذلك ، يمكنك استخدام bash'a دخول قصير:

 $ op=AC $ echo $((16#$op)) 172 

يتم تحرير الحزمة المستلمة وفقًا لنوع الطلب (اكتشاف أو طلب) وإرسالها مرة أخرى.

الرد


ومع ذلك ، فإن إرسال حزمة ليست مهمة سهلة. تحتاج أولاً إلى تحويل البايتات من التفريغ إلى البايتات الخام وإرسال كل شيء دفعة واحدة مع حزمة واحدة.

يمكن إجراء التحويل باستخدام الأداة المساعدة printf باستخدام تسلسل هروب. وحتى لا يتم فقد أي شيء ، اكتب البايتات فورًا إلى ملف.

 #   >/tmp/dhcp.payload #     for i in ${msg[*]}; do printf "\x$i" >> /tmp/dhcp.payload done 

يستخدم OpenBSD netcat أيضًا للإرسال. ومع ذلك ، إذا كان الإصدار 1.105 مع Ubuntu مناسبًا كمستمع ، فهو غير مناسب لبث رسائل UDP: لقد حصلنا على خطأ في البروتوكول غير متاح.

 cat /tmp/dhcp.payload | nc -ub 255.255.255.255 68 -s $SERVER -p 67 -w0 

يسمح رمز التبديل -b بإرسال رسائل البث ، وهذا هو السبب الثاني وراء تشغيل الخادم من تحت المستخدم الخارق.

ما هي القيود؟


تم تصميم خادم DHCP هذا مع التبسيط مثل عميل واحد على الشبكة. ومع ذلك ، ستعمل مع العديد من العملاء. مجرد الحصول على أسرع عنوان.



الخاتمة


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

المصادر


  1. DHCP - ويكيبيديا
  2. معلمات DHCP و BOOTP - IANA

Source: https://habr.com/ru/post/ar435148/


All Articles