Fail2ban را نخست نصب می‌کنند و کار معمولاً همان‌جا هم تمام می‌شود: بسته سر جایش است، سرویس کار می‌کند، و sshd ظاهراً پوشش دارد. شش ماه بعد آشکار می‌شود که زندان فایلی را می‌خواند که در این سامانه وجود ندارد، و همه چیز دیگر — ایمیل، پنل مدیریت، فرم ورود سایت — هرگز پوشش نداشته است.

بیایید ببینیم روی یک VPS معمولی که سایتی روی آن است چه چیزی ارزش فعال‌کردن دارد، چه اعدادی آنجا بگذارید، و چگونه مطمئن شوید زندان کار می‌کند نه اینکه صرفاً در پیکربندی حاضر باشد.

نخست بررسی کنید که sshd چیزی می‌گیرد

یک فرمان:

sudo fail2ban-client status sshd

خروجی سطرهای Currently failed، Total failed و Total banned دارد. اگر Total failed روی سروری که دست‌کم یک روز در اینترنت بوده صفر باشد، زندان کار نمی‌کند. آن را با واقعیت بسنجید:

sudo lastb | wc -l

هزاران تلاش ناموفق در lastb در برابر صفرها در Fail2ban دقیقاً یک معنا دارد: فیلتر جای نادرستی را نگاه می‌کند.

رایج‌ترین علت Debian 12 است. این نسخه دیگر rsyslog را به‌صورت پیش‌فرض نصب نمی‌کند، فایل /var/log/auth.log به‌سادگی وجود ندارد، و زندان پیش‌فرض sshd برای خواندن همان فایل تنظیم شده است. و پیامی خطایی هم در کار نیست: سرویس آغاز می‌شود، وضعیت چاپ می‌شود، و شمارنده‌ها روی صفر می‌مانند. راه‌حل گذر به ژورنال systemd است:

[sshd]
enabled = true
backend = systemd

گزینه دیگر بازگرداندن rsyslog به‌عنوان بسته است، اگر یک auth.log متنی ساده برای ابزارهای دیگر اهمیت دارد. Ubuntu 24.04 هم همین‌گونه رفتار می‌کند.

تنظیمات خود را کجا بگذارید

/etc/fail2ban/jail.conf را به حال خود بگذارید: هنگام به‌روزرسانی بسته بازنویسی می‌شود و هر ویرایشی که آنجا انجام دهید روزی بی‌صدا ناپدید خواهد شد. تنظیمات شما به /etc/fail2ban/jail.local می‌رود — این فایل آخر خوانده می‌شود و بر فایل مشترک اولویت دارد.

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.25
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

ignoreip با نشانی خودتان تجمل نیست بلکه بیمه است: قفل‌کردن خود بیرون از سرور با یک غلط تایپی آسان‌تر از آن است که به نظر می‌رسد. و اگر نشانی ثابت ندارید، راه ورود دومی جز SSH نگاه دارید — کنسول ارائه‌دهنده‌تان یا VNC.

زندانی که تصویر را دگرگون می‌کند: recidive

حافظه زندان معمولی کوتاه است: پنج تلاش در ده دقیقه، یک ساعت مسدودسازی، و یک ساعت بعد همه چیز از نو آغاز می‌شود. ربات با این وضع کاملاً کنار می‌آید و فردا و پس‌فردا بازمی‌گردد. recidive دقیقاً همین شکاف را می‌بندد: ژورنال سامانه را نمی‌خواند بلکه ژورنال خود Fail2ban را می‌خواند، یعنی کسی را مسدود می‌کند که Fail2ban پیش‌تر مسدودش کرده است.

[recidive]
enabled  = true
bantime  = 1w
findtime = 1d
maxretry = 5

این را چنین بخوانید: «پنج بار در یک روز مسدود شد، یک هفته ناپدید می‌شود». این زندان به فایل /var/log/fail2ban.log نیاز دارد، پس اگر گزارش‌گیری خود Fail2ban را به syslog برده‌اید، recidive هم به backend = systemd نیاز خواهد داشت.

در عمل اثر این یک زندان معمولاً محسوس‌تر از تنظیم دقیق همه زندان‌های دیگر است: مهمانان همیشگی کنار می‌روند و در گزارش‌ها تنها پس‌زمینه تازه می‌ماند.

وقتی سایتی روی سرور هست دیگر چه فعال کنیم

به ترتیب کاهش سودمندی:

  • nginx-http-auth یا apache-auth — حدس‌زدن علیه احراز هویت پایه. لازم است اگر پنل مدیریت یا سایت آزمایشی پشت گذرواژه وب‌سرور باشد؛
  • nginx-botsearch — پویش مسیرهای شناخته‌شده: /wp-login.php، /phpmyadmin، /.env. این نفوذ نیست بلکه شناسایی است، و همان است که پیش از هر چیز دیگر می‌آید؛
  • nginx-limit-req — تنها در صورتی کار می‌کند که limit_req_zone در خود Nginx تعریف شده باشد؛ بدون آن زندان فعال و بی‌فایده است؛
  • postfix-sasl و dovecot — ضروری‌اند اگر ایمیل خودتان را دارید. حدس‌زدن گذرواژه صندوق‌های پستی پیوسته است و معمولاً کسی پایشش نمی‌کند.
[nginx-botsearch]
enabled = true
logpath = /var/log/nginx/access.log

فرم ورود خود سایت داستان جداگانه‌ای است. برنامه گزارش ویژه‌ای از ورودهای ناموفق ندارد، و در access.log تلاش ناموفق مانند یک POST معمولی با کد 200 یا 302 به نظر می‌رسد — هیچ فیلتر عمومی‌ای آن را از تلاش موفق بازنمی‌شناسد. دو گزینه هست: کاری کنید برنامه شکست‌ها را در syslog بنویسد (بیشتر سامانه‌های مدیریت محتوا افزونه‌ای برای این دارند)، یا نرخ درخواست‌ها به صفحه ورود را محدود کنید. دومی محدودکننده است نه آشکارساز، و بهتر است این را از پیش بدانید.

اعداد

bantime = 10m همان مقدار پیش‌فرضی است که سبب می‌شود مردم Fail2ban را بی‌فایده بشمارند: ده دقیقه برای بازگشت ربات کافی است. یک ساعت برای مسدودسازی نخست به‌علاوه recidive برای یک هفته بسیار بهتر از مسدودسازی همیشگی کار می‌کند، که با گذر زمان به فهرستی بی‌پایان از قواعد بدل می‌شود.

maxretry = 3 برای SSH راهی مطمئن برای قفل‌کردن خودتان بیرون است. پنج تلاش در ده دقیقه حدس‌زدن را به همان خوبی می‌بُرد.

حدس‌زدن کند — یک تلاش هر پنج دقیقه — هرگز درون findtime نخواهد افتاد. این دلیلی برای کش‌دادن پنجره به یک شبانه‌روز نیست: هشدارهای نادرست علیه همکاران خودتان خواهید گرفت. در برابر حدس‌زدن کند نه آستانه بلکه غیرفعال‌کردن احراز هویت با گذرواژه کارساز است.

مطمئن شوید مسدودسازی به بسته‌ها می‌رسد

Fail2ban تنها فرمانی بیرونی را فرا می‌خواند. اگر banaction با آنچه واقعاً ترافیک را فیلتر می‌کند همخوان نباشد، گزارش از سطرهای شادمانه Ban 198.51.100.7 پر می‌شود در حالی که بسته‌ها همچنان می‌رسند. Debian 12 به‌صورت پیش‌فرض از nftables استفاده می‌کند، و با UFW فعال گزینه درست banaction = ufw است. برای بررسی:

sudo nft list ruleset | grep -c f2b
sudo iptables -S | grep f2b

دست‌کم یکی از این دو باید قواعدی نشان دهد. و خود فیلتر را می‌توانید بدون انتظار برای حمله بیازمایید:

sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

در پایین خروجی نوشته شده چند سطر همخوان شده‌اند. صفر یعنی فیلتر و گزارش به هم نمی‌رسند، و تنظیم چیزی فراتر از آن معنایی ندارد.

آنچه Fail2ban انجام نمی‌دهد

از حدس‌زدن توزیع‌شده محافظت نمی‌کند: هزار نشانی با یک تلاش هرکدام با هیچ تنظیمی به آستانه نمی‌رسند. علت را برطرف نمی‌کند — نشانی مسدودشده گذرواژه ضعیف را باطل نمی‌کند. و درباره اعتبار چیزی نمی‌داند: نشانی‌ای که دیروز را به نفوذ در سرورهای دیگران گذرانده برای او پاک است تا وقتی سراغ سرور شما بیاید. از همین‌جاست ترکیبی که در عمل به کار می‌رود: کلیدها به‌جای گذرواژه‌ها، Fail2ban همچون محدودکننده نویز، و فهرست مسدودسازی مشترک (CrowdSec) همچون دانشی از تجربه دیگران.

مسئله‌ای جداگانه هم هست: همه اینها گاه‌به‌گاه به نگاهی نیاز دارند. کسی هفته‌ها پیاپی fail2ban-client status را برای هر زندان تایپ نمی‌کند، و افزایش شمار مسدودسازی‌ها وقتی دیده می‌شود که چیزی از پیش خراب شده باشد. در صفحه‌های نمایشی پایین همان داده‌ها در یک صفحه گرد آمده‌اند: فهرست زندان‌ها، اینکه هم‌اکنون چه کسی مسدود است، و تلاش‌ها از کجا می‌آیند.