قدمنا في الجزء الأول من هذا الدليل الخطة التي نعمل على إعدادها من أجل ضبط آلية للطرق على المنافذ تعتمد حصرا على جدار iptables الناري. نستكمل في هذا الجزء ما بدأناه بتنفذ الآلية المشروحة في الجزء السابق.
إعداد إطار عمل نظامي للجدار الناري
نبدأ بوضع إطار أساسي للاتصالات في الخادوم. ستتولى سلسلة INPUT
التعامل مع جميع الاتصالات القادمة. سنزيل جميع قواعد الجدار الناري المطبقة حاليا من أجل بدء الإعداد من الصفر. لكن قبل ذلك يجب أن نتأكد من أن السياسات الافتراضية مضبوطة على ACCEPT
للاستمرار في الاتصال الجاري:
sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -F
بهذه الطريقة نبدأ مع جدار ناري مفتوح تماما. قبل تقييد الاتصالات ننفذ أوامر إضافة السلاسل الجديدة:
sudo iptables -N KNOCKING sudo iptables -N GATE1 sudo iptables -N GATE2 sudo iptables -N GATE3 sudo iptables -N PASSED
نتوفر الآن على ثماني سلاسل. سنستخدمها كلَّها ما عدا سلسلتيْ OUTPUT
وFORWARD
اللتان لا تعنياننا هنا.
نبدأ بالتعامل مع الاتصالات التي لا تحتاج للطرق على المنافذ لفتحها، فنضيف قاعدة إلى سلسلة INPUT
للسماح للاتصالات الجارية كافةً بالاستمرار:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
وأخرى لقبول جميع الاتصالات من الجهاز المحلي:
sudo iptables -A INPUT -i lo -j ACCEPT
إذا كانت لديك خدمات موجَّهة للعموم، مثل خادوم ويب، فأضف قاعدة على النحو التالي حتى يمكن الاتصال بها:
sudo iptables -A INPUT -p protocol --dport port -j ACCEPT
مثال لقاعدة تتيح الوصول إلى خادوم الويب:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
أنهينا الآن إعداد قواعد الاتصالات المسموح بها. نمرّر جميع الاتصالات التي لا تنطبق عليها إحدى القواعد السابقة إلى سلسلة KNOCKING
من أجل التنفيذ الفعلي لآلية الطرْق:
sudo iptables -A INPUT -j KNOCKING
إعداد البوابة الأولى
سنُلحِق “البوابات” بعد اكتمال إعدادها بسلسلة KNOCKING
لتمرير حركة البيانات عبر الاختبارات المشروحة في الجزء الأول من هذا الدليل. لكن قبل ذلك يجب وضع أساس كل اختبار على انفراد.
نبدأ بتعريف أول اختبار طرْق.
عندما يحاول عميل الاتصال فإننا ننظر في المنفذ الذي يرسل إليه الطلب؛ إن كان يوافق المنفذ الأول لدينا في متتالية الطرْق نشير إلى أن العميل تجاوز الاختبار الأول بنجاح؛ وإلا نتجاهل الطلب.
نضع علامة على العميل عند محاولة الاتصال بالمنفذ الصحيح:
sudo iptables -A GATE1 -p tcp --dport 1111 -m recent --name AUTH1 --set -j DROP
يؤدي السطر أعلاه مهام عدة؛ يضيف قاعدة جديدة إلى سلسلة GATE1
. شروط تنفيذ القاعدة هي أن يكون البروتوكول المستخدَم هو tcp
والمنفذ المطلوب هو1111
، أي المنفذ اﻷول في سلسلة الطرق. عند تحقق الشروط نستدعي وِحدة recent
(باستخدام خيار m-
) ونضع علامة AUTH1
(باستخدام name AUTH1 --set--
). ستُستعمَل هذه العلامة عند اختبار إصابة المنفذ الثاني. أخيرا، وبعد تعيين العلامة، نتجاهل الحزمة لكي لا يعرف العميل مالذي يحدث.
ثم نتجاهل جميع حزم البيانات الأخرى، لأن أي معلومة تُرسَل إلى هذه السلسلة تبحث فقط عن موافقة أول حزمة:
sudo iptables -A GATE1 -j DROP
أنجزنا الآن ما يتعلق بالمنفذ الأول من متتالية الطرْق: إما أن توافق الحزمة المنفذ المطلوب أو تُتَجاهَل. إذا وافقت المنفذ توضع عليها علامة AUTH1
.
إعداد البوابة الثانية
تُضبط البوابة الثانية بطريقة مشابهة إلا أنها أكثر تعقيدا.
أول ما يجب الانتباه إليه هو أن قرار توجيه محاولات الاتصال إلى هذه السلسلة سيكون ضمن السلسلة الأم KNOCKING
. لن تحتاج سلسلة GATE2
إلى التأكد من مطابقة محاولة الاتصال للبوابة الأولى، لأن هذا الاختبار جرى سلفا.
مع ذلك يجب أن تحذف أي علامات قد تكون وُضعت على العميل قبل البدء في التعامل مع محاولة الاتصال. عدم إزالة العلامات السابقة قد ينتج عنه وضع علامات عدة على عنوان العميل ممّا قد يؤدي إلى نجاح الطرق على المنفذ بمجرد فحص المنافذ ثلاث مرات. طبعا هذا أمر لا نرغب فيه.
نستخدم وحدة recent
مرة أخرى لحذف الاسم (العلامة):
sudo iptables -A GATE2 -m recent --name AUTH1 --remove
لا تتخذ القاعدة أعلاه أي قرارات أو إعادة توجيه؛ كل ما تفعله هو حذف العلامة الحالية (وهي تلك التي سمحت بتوجيه الاتصال إلى هذه السلسلة) وتوجيه البيانات إلى القاعدة الموالية.
يصبح العنوان - بعد تجاوز القاعدة الأولى من السلسلة - خاليا من أي علامات. نتحقق من المنفذ الذي يطلبه العنوان ومن مطابقته للمنفذ الثاني في متتالية الطرْق (2222
):
sudo iptables -A GATE2 -p tcp --dport 2222 -m recent --name AUTH2 --set -j DROP
نفس ما فعلناه مع البوابة الأولى. نضع علامة AUTH2
للإشارة إلى أن عنوان الطلب تجاوز الاختبار الثاني إذا كان العميل يحاول الاتصال عبر المنفذ المطلوب، ثم نتجاهل الحزمة لكي لا يعرف العميل مالذي نفعله.
قد تبدو القاعدة التالية غريبة لأول وهلة:
sudo iptables -A GATE2 -j GATE1
قد تظن أن تجاهل الحزمة بعد وضع علامة AUTH2
هو - منطقيا - الخطوة التالية. إلا أن فعل ذلك سيجعلنا في وضع حرج أثناء حالة خاصة.
لو كانت لدينا قاعدة drop all
هنا وكانت الحزمة المرسلة في هذه الأثناء توافق المنفذ الأول في سلسلة الطرْق، فلن تسجَّل على أنها بداية لمتتالية الطرق. نفرض على سبيل المثال أن العميل أرسل - عن طريق الخطأ - محاولتي اتصال إلى المنفذ الأول. في هذه الحالة لن يعُدّ الجدار الناري محاولة الاتصال الثانية صحيحة لأنه سيرى المتتالية كما يلي:
- محاولة اتصال عبر المنفذ الأول. سيحسب الجدار الناري أن الاختبار الأول تُجووِز بنجاح.
- محاولة الاتصال عبر المنفذ الأول. فشل في الاختبار الثاني. يُعاد تعيين المتتالية.
- محاولة الاتصال عبر المنفذ الثاني. فشل في الاختبار الأول (يطبَّق الاختبار الأول لأن المتتالية أعيد تعيينها في الخطوة السابقة). يُعاد تعيين المتتالية.
- محاولة الاتصال عبر المنفذ الثالث. فشل في الاختبار الأول (يُطبق الاختبار الأول لأن المتتالية أعيد تعيينها في الخطوة السابقة). يُعاد تعيين المتتالية.
نجد أن العميل في الافتراض السابق أرسل المتتالية الصحيحة، إلا أن الجدار الناري لم يعتمدها لأنه حصل تشويش لديه في أي قاعدة يجب عليه أن يطبق. يجب إذن على العميل، إذا أخطأ، إرسال طلب وهمي من أجل إعادة تعيين السلسلة، قبل البدء في إرسال المتتالية.
لتجنب الوقوع في هذه الحالة لن نتجاهل الحزمة بل سنوجّهها - بدلا من ذلك - إلى سلسلة GATE1
التي أعددناها سابقا. نرسل جميع حزم البيانات التي لم تُصِب المنفذ الثاني إلى البوابة الأولى من جديد:
sudo iptables -A GATE2 -j GATE1
نكون هنا أمام خيارين: إما أن يكون الطلب موجَّها إلى المنفذ الأول، هنا نبدأ من جديد في المتتالية؛ وإلا فإن الجدار الناري سيتجاهل الطلب حسب العادة. أي أننا تجنبنا الوقوع في الحالة المعروضة آنفا.
إعداد البوابة الثالثة
ننفذ البوابة الثالثة بنفس طريقة تنفيذ البوابة الثانية تماما.
نمسح أولا جميع العلامات التي وُضعت على العنوان مثل ما فعلنا في إعداد البوابة الثانية ولنفس الأسباب:
sudo iptables -A GATE3 -m recent --name AUTH2 --remove
ثم نختبر هل أصابت محاولة الاتصال المنفذ الثالث في متتالية الطرق، فإن فعلت نضع علامة AUTH3
التي تشير إلى أن العميل نجح في طرق المنافذ المطلوبة حسب المرجو؛ ثم نتجاهل - مثل ما هي العادة - الحزمة:
sudo iptables -A GATE3 -p tcp --dport 3333 -m recent --name AUTH3 --set -j DROP
إن لم تفلح محاولة الاتصال في إصابة المنفذ المطلوب نعيد توجيهها إلى البوابة الأولى لترى هل أصابت المنفذ الأول في المتتالية لبدء المسار من جديد:
sudo iptables -A GATE3 -j GATE1
بالوصول إلى هذه النقطة يكون العملاء الذي نجحوا في طرق المنافذ المطلوبة حسب الترتيب المفروض قد حصلوا على علامة AUTH3
التي تمكننا من فتح خدمة SSH لهم ضمن سلسلة PASSED
.
إعداد سلسلة PASSED
تُستخدَم هذه السلسلة لفتح منفذ SSH لمدة ثلاثين ثانية للعميل الذي نجح في طرق المتتالية الصحيحة.
لن يُفتَح منفذ SSH إلا إذا كانت محاولة الاتصال الموالية من العميل تطلب السماح لها بعبوره. تفرض هذه القاعدة على من يحاول عشوائيا طرق المنافذ تجربة الاتصال بSSH بعد كل محاولة، الأمر الذي يصعِّب من معرفة متتالية الطرق.
نبدأ - حسب العادة - بإعادة تعيين العلامات:
sudo iptables -A PASSED -m recent --name AUTH3 --remove
نقبل الاتصال عبر SSH من المستخدمين الذين وصلوا إلى هذه السلسلة:
sudo iptables -A PASSED -p tcp --dport 22 -j ACCEPT
بالنسبة للمستخدمين الذي لم يحاولوا الاتصال عبر SSH فإننا نعيدهم إلى البوابة الأولى:
sudo iptables -A PASSED -j GATE1
أكملنا الآن إعداد جميع السلاسل المتفرعة عن سلسلة KNOCKING
. بقي إعداد السلسلة العامة التي ستمرر حركة البيانات إلى السلاسل الفرعية.
إعداد سلسلة KNOCKING
يمكننا الآن بعد إعداد السلاسل الفرعية منفردةً إلحاقها بالسلسلة العامة KNOCKING
وبالتالي تنفيذ خطة عملنا.
نبدأ أولا بتوجيه اتصالات العملاء الذين نجحوا في اختبارات الطرْق مباشرة إلى سلسلة PASSED
. تمكننا إضافة خيارات هنا. سنقيد الفترة الزمنية التي يمكن للعميل الاتصال فيها بخدمة SSH بعد تجاوزه لاختبارات الطرق، ولتكن ثلاثين ثانية. بعد هذه المهلة لن يكون بمقدوره الاتصال ويجب عليه إرسال متتالية الطرق مرة أخرى.
sudo iptables -A KNOCKING -m recent --rcheck --seconds 30 --name AUTH3 -j PASSED
ثم نختبر العلامات الأخرى بدءا بالأكثر تقييدا. تمكننا إضافة عشر ثوان لتحديد مهلة لانتهاء صلاحية الطَّرْقات؛ يعني هذا أنه يتوجب على العملاء ألايفصلوا بين كل طرْقتين بأكثر من عشر ثوان.
sudo iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH2 -j GATE3 sudo iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH1 -j GATE2
نعيد توجيه جميع محاولات الاتصال التي لم توافق أيا من القواعد السابقة إلى البوابة الأولى:
sudo iptables -A KNOCKING -j GATE1
بهذا تأخذ جميع سلاسل الجدار الناري مكانها. تُلحَق سلسلة KNOCKING
كاملة مع السلاسل التابعة لها بسلسلة INPUT
الاعتيادية.
أعددنا لآن آلية الطرق. حان الوقت لاختبارها.
اختبار الطرق على المنافذ
توجد الكثير من الأدوات التي يمكن استخدامها لإنشاء حزم بيانات تستخدم بروتوكول TCP
المطلوبة في إعدادات الطرْق على المنافذ. سنستخدم أداة nmap
نظرا لوجودها افتراضيا على أغلب توزيعات لينكس.
يستخدم nmap
افتراضيا حزم بيانات TCP
. لذا يجب أن نطلب منه تجاهل استكشاف المستضيف الموجود في سلوكه الابتدائي لكي لا يتداخل مع الطرْقات. إضافة لذلك نريد أن تنتهي مهلة محاولة الاتصال بعد ثانية واحدة فقط لنتابع مع الطرقة الموالية.
ستبدو كل طرْقة، من هذا المنطلق، على النحو التالي. في المثال أول منفذ نريد طرْقه:
nmap -Pn --host_timeout 201 --max-retries 0 -p 1111 your_server
أي أن متتالية الطرق ستصبح على النحو التالي:
nmap -Pn --host_timeout 201 --max-retries 0 -p 1111 your_server nmap -Pn --host_timeout 201 --max-retries 0 -p 2222 your_server nmap -Pn --host_timeout 201 --max-retries 0 -p 3333 your_server
ستكون لدينا بعدها ثلاثون ثانية للاتصال بخدمة SSH.
يمكننا الاستفادة من أساسيات في برمجة Bash لجعل الأمور آليةً أكثر. سنستخدم حلقة for
لتنفيذ الأوامر السابقة ضمن حلقة تكرارية ثم تشغيل عميل SSH للاتصال بالخادوم:
for x in 1111 2222 3333; do nmap -Pn --host_timeout 201 --max-retries 0 -p $x your_server && sleep 1; done && ssh user@your_server
ما نفعله هنا هو الطرْق على المنفذ الأول، انتظار ثانية واحدة، الطرْق على الثاني، وهكذا إلى أن تكتمل المتتالية. ثم نحاول بعدها الاتصال بخدمة SSH على الخادوم.
ننشئ ملفا للسكربت لجعل الأمر أكثر أناقة وأيسر للاستخدام. نسمي الملف knock_client
:
nano knock_client
ونضع فيه المحتوى التالي:
#!/bin/bah ports="1111# 2222 3333" host="your_server" for x in $ports do nmap -Pn --host_timeout 201 --max-retries 0 -p $x $host sleep 1 done ssh user@${host}
احفظ الملف (CTRL + O) ثم أغلقه (CTRL + X).
نجعل الملف قابلا للتنفيذ:
chmod 755 knock_client
نحاول الاتصال بالخادوم بتنفيذ الأمر:
./knock_client
يمكن الآن، إذا جرى كل شيء على ما يرام، الاتصال بالخادوم عن طريق SSH.
بقيت خطوة أخيرة بعد التحقق من عمل الخطة التي نفذناها حسب المُراد. نجعل قواعد الجدار الناري دائمة (لا يُعاد تعيينها بعد إعادة تشغيل الخادوم) بتنزيل وتثبيت حزمة iptables-persistent
على الخادوم:
sudo apt-get install iptables-persistent
وتشغيل خدمة iptables-persistent
:
sudo service iptables-persistent start
خاتمة
يكون لديك باكتمال هذا الدليل نظام عملي للطرق على المنافذ يعتمد فقط على الوظائف الموجودة في جدار iptables
الناري.
توجد مزايا لاعتماد iptables
حصرا في هذا الإطار. أولا، ينتشر استخدام iptables
ويشيع خضوعه لفحوص بحثا عن ثغرات أمنية قد تمثل خطرا على مستخدميه. يعني هذا أنه ما دامت القواعد التي أنشأتها تؤدي العمل الذي تظن أنها تؤديه فأنت في مأمن.
ميزة أخرى لهذا الإعداد في مقابل خدمة منفصلة للطرق على المنافذ هي أنه لا مجال أن تفشل خدمة تنفيذ الطرق في تغيير قواعد الجدار الناري وتدع المنفذ مفتوحا.
ترجمة - بتصرف - لمقال How To Configure Port Knocking Using Only IPTables on an Ubuntu VPS.
حقوق الصورة البارزة: Shield vector designed by Freepik.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.