لا شيء في fail2ban يُسقط حزمة بمفرده: فهو يستدعي إجراءً، وهذا الإجراء هو ما يحدد البروتوكول والمنفذ. عندما يبلّغ السجن عن حظر بينما يواصل الخدمة قبول عمليات الدخول، يكون الحظر عادةً حقيقيًا وأضيق مما توحي به السجلات. العميل الذي يعيد الاتصال عبر النقل الآخر لا يصادف القاعدة التي ثُبّتت. قارن ما ثبّته الإجراء بما تستمع إليه الخدمة قبل أن تغيّر أي شيء، لأن الدليل موجود في سلسلة الجدار الناري التي كتبها الإجراء، لا في قائمة السجن.

اقرأ السلسلة، لا ملخص السجن

يُدخل fail2ban سلسلته الخاصة قبل سلسلة الخدمة، لذا تُظهر قائمة العدّادات ما هو موجود بالضبط. سلسلة مسماة على اسم السجن، تحمل قاعدة واحدة يقرأ عمود البروتوكول فيها udp، تفسّر تفسيرًا كاملًا عمليات دخول TCP التي تستمر في الوصول. لا تُرفض إلا حزم UDP القادمة من المصدر المحظور. الخدمة لديها مستمع TCP، ولا شيء في تلك السلسلة يمسّه.

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

الإجراء يسمّي بروتوكولًا واحدًا، وهنا ينكسر

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

عمليات نشر SoftEther و OpenVPN تستمع عادةً إلى UDP و TCP في آن واحد، ولأن سطر السجل يبدو نفسه في الحالتين يراقب الفلتر كليهما. لا يظهر عدم التماثل أبدًا في تقرير السجن نفسه. عدّ fail2ban الإخفاقات بشكل صحيح ثم ثبّت قاعدة تنطبق على نصف الحركة التي وصلت عليها تلك الإخفاقات.

اجعل الحظر يغطي النقلين

أصلح ذلك في تعريف السجن بدلًا من ذلك؛ ستُعاد خلط القواعد المكتوبة يدويًا عند إعادة التحميل التالية. اكتب إجراءين صريحين، واحدًا لكل بروتوكول:

action = %(banaction)s[name=%(__name__)s-tcp, actionname=%(__name__)s-tcp, protocol="tcp", port="%(port)s", chain="%(chain)s"]
         %(banaction)s[name=%(__name__)s-udp, actionname=%(__name__)s-udp, protocol="udp", port="%(port)s", chain="%(chain)s"]

لا تحاول اختصار ذلك باستخدام protocol = all. إجراء الحظر الافتراضي هو إجراء متعدد المنافذ، ويتوسّع إلى -p <protocol> -m multiport --dports <port>؛ دون بروتوكول L4 لا يوجد شيء لاختبار مطابقة المنفذ، لذا يرفض iptables القاعدة بينما يبلّغ السجن عن حظر ناجح. إجراء يشمل كل المنافذ مثل iptables-allports أو nftables-allports يقبل مدخلًا واحدًا فعلًا، لكنه يحظر كل المنافذ على ذلك المصدر، وهذا قرار مختلف يحتاج تبريره الخاص. اترك protocol على tcp أو udp واقبل المدخلين.

أثبت وجود القاعدة بدلًا من الثقة بالإعداد، لأن الإعداد يصف نية حتى تحمله سلسلة:

iptables -S f2b-vpn-tcp
iptables -S f2b-vpn-udp

ينبغي أن تسرد كل سلسلة قاعدة واحدة، مع -p tcp في الأولى و -p udp في الثانية، وكلتاهما تذكر العنوان المحظور. ثم تأكد من رفض العنوان نفسه على النقلين. الحظر الذي لم تره في السلسلة أمل، وسيكلّف التقرير التالي عن العَرَض نفسه الساعة نفسها مرة أخرى.

ما لا يزال الحظر يفوته، والحالة التالية

ما يفعله الإجراء هو رفض مصدر واحد، وفقط على المنافذ المذكورة فيه. لا يفعل شيئًا تجاه مهاجم يبدّل العناوين، ولا يستطيع فصل جهاز معادٍ عن مخرج NAT من فئة الناقل يتشاركه مئات المستخدمين، حيث يحظر حظر واحد أشخاصًا لم يفعلوا شيئًا. تأكد من أن الفلتر يقرأ العنوان الذي يملكه العميل فعلًا، وليس ترويسة مُمرَّرة أو عنوان وكيل. أبقِ النافذة قصيرة بما يكفي لينتهي الخطأ وحده.

لا شيء من ذلك يبرّر تجاوز إصلاح البروتوكول؛ بل يبرّر حمل الفكرتين معًا. الحظر أضيق مما يوحي به ملخص السجن، وحتى الحظر الكامل أضيق من التهديد. ضع سلسلة الجدار الناري بجانب قائمة مستمعات البرنامج الخفي وقارن بروتوكولًا ببروتوكول، لأن هاتين القائمتين تحددان ما إذا كان الحظر يستطيع الوصول إلى الخدمة أصلًا.

احتفظ بأمر إعادة التحميل وقائمة السلسلة في دليل التشغيل بجانب السجن. سيحتاج الشخص التالي كليهما، ولن يخبره ملخص السجن بأي منهما.

مقالات ذات صلة