שום דבר ב-fail2ban לא מפיל חבילה בעצמו: הוא קורא לפעולה, והפעולה הזו היא שממנה פרוטוקול ופורט. כשה-jail מדווח על ban בזמן שהדמון ממשיך לקבל התחברויות, ה-ban בדרך כלל אמיתי וצר ממה שהלוג מרמז. לקוח שמתחבר מחדש דרך התעבורה השנייה לעולם לא פוגש את הכלל שהותקן. השוו את מה שהפעולה התקינה למה שהדמון מאזין לו לפני שאתם משנים משהו, כי ההוכחה נמצאת בשרשרת חומת האש שהפעולה כתבה, לא ברשימת ה-jail.

קראו את השרשרת, לא את סיכום ה-jail

fail2ban מכניס שרשרת משלו לפני שרשרת השירות, כך שרשימת מונים מראה בדיוק מה קיים. שרשרת הקרויה על שם ה-jail, שמחזיקה כלל אחד שעמודת הפרוטוקול שלו היא udp, היא הסבר מלא להתחברויות TCP שממשיכות להגיע. רק חבילות UDP מהמקור החסום נדחות. לשירות יש מאזין TCP, ושום דבר בשרשרת ההיא לא נוגע בו.

שימו לב גם לאפקט ה-jail השכן. מארח אחד יכול להיראות מוגדר היטב רק מפני ש-jail אחר מספק את החצי החסר, ואותו build לא עושה דבר במקום שבו ה-jail הזה לא מותקן.

הפעולה ממנה פרוטוקול אחד, ושם זה נשבר

כל banaction הוא תבנית פקודה של חומת אש, והפרוטוקול יושב באחד ממחזיקי המקום שלו. הצרות מכוונת, כי ל-jail של אתר ול-jail של DNS אין מה לחפש בחסימת פורטים זהים. זה הופך למלכודת כשהשירות מאזין ליותר מתעבורה אחת, מה שדמונים של VPN עושים בשגרה. המסנן יכול לצפות בהתחברויות כושלות משתי התעבורות בזמן שהפעולה מכסה אחת.

פריסות SoftEther ו-OpenVPN מאזינות בדרך כלל ל-UDP ול-TCP בו-זמנית, ומכיוון ששורת הלוג נראית זהה בשני המקרים המסנן צופה בשניהם. האסימטריה לא מופיעה אף פעם בדוח של ה-jail עצמו. fail2ban ספר את הכשלים נכון ואז התקין כלל שחל על מחצית מהתעבורה שעליה הגיעו אותם כשלים.

גרמו ל-ban לכסות את שתי התעבורות

תקנו זאת בהגדרת ה-jail במקום; כללים שנכתבו ביד יעורבבו בטעינה הבאה. פרטו שתי פעולות, אחת לכל פרוטוקול:

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. ה-banaction המוגדר כברירת מחדל הוא פעולת multiport, והוא מתרחב ל--p <protocol> -m multiport --dports <port>; בלי פרוטוקול L4 אין מה להתאמת הפורט לבדוק, ולכן iptables דוחה את הכלל בעוד ה-jail עדיין מדווח על ban מוצלח. פעולה של כל הפורטים כמו iptables-allports או nftables-allports אכן מקבלת רשומה אחת, אבל היא חוסמת כל פורט באותו מקור, וזו החלטה שונה שדורשת הצדקה משלה. השאירו את protocol על tcp או udp וקבלו את שתי הרשומות.

הוכיחו שהכלל קיים במקום לסמוך על ההגדרה, כי הגדרה מתארת כוונה עד ששרשרת מחזיקה אותה:

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

כל שרשרת אמורה לפרט כלל אחד, עם -p tcp בראשונה ו--p udp בשנייה, ושתיהן ממנות את הכתובת החסומה. אחר כך ודאו שאותה כתובת נדחית בשתי התעבורות. ban שלא ראיתם בשרשרת הוא תקווה, והדוח הבא על אותו סימפטום יעלה שוב את אותה שעה.

מה ban עדיין מחמיץ, והמקרה הבא

מה שהפעולה עושה הוא לדחות מקור אחד, ורק בפורטים המפורטים בה. היא לא עושה דבר נגד תוקף שמחליף כתובות, והיא לא יכולה להפריד מכונה עוינת מיציאת NAT ברמת ספק שמשותפת למאות משתמשים, שם ban אחד נועל אנשים שלא עשו דבר. ודאו שהמסנן קורא את הכתובת שבאמת יש ללקוח, ולא כותרת מועברת או כתובת פרוקסי. החזיקו את החלון קצר מספיק כדי שטעות תפוג מעצמה.

שום דבר מזה לא מצדיק לדלג על תיקון הפרוטוקול; הוא מצדיק להחזיק שני רעיונות בו-זמנית. ה-ban צר ממה שסיכום ה-jail מרמז, ואפילו ban מלא צר מהאיום. שימו את שרשרת חומת האש לצד רשימת המאזינים של הדמון והשוו פרוטוקול אחר פרוטוקול, כי שתי הרשימות האלה קובעות אם ban יכול בכלל להגיע לשירות.

שמרו את פקודת הטעינה מחדש ואת רשימת השרשרות ב-runbook לצד ה-jail. האדם הבא יזדקק לשניהם, וסיכום ה-jail לא יגיד לו אף אחד מהם.

מאמרים קשורים