Малі атаки на автентифікацію пошти непомітні. Помічаєш їх, коли журнал IMAP перетворюється на інструмент відмови в обслуговуванні, вентилятори ЦП починають гудіти як дрони, а користувачі клянуться, що «нічого не змінювали», поки Outlook нескінченно пробує той самий пароль.
Fail2ban може допомогти. Він також може нашкодити — мовчки — заблокувавши вашого CEO посеред засідання ради, бо поштовий додаток на телефоні зберіг некоректний пароль на вісім годин. Різниця не в «встановити fail2ban». Різниця в правилах, джерелах логів і поступовому впровадженні, що відповідає реальному продакшену.
Що ви фактично захищаєте
Поштові сервери привертають атакувальників з нудних причин: облікові дані цінні, SMTP поширений, а повторне використання паролів — невичерпне джерело. Наймасовішими «атаками», які ви побачите, зазвичай є не витончені операції. Вони гучні, повторювані і прибуткові, бо оператори ставлять на одну слабку обліковку із тисячі.
Поширені шаблони атак на пошту, які варто банити
- Brute force автентифікації IMAP/POP (Dovecot, Courier): повторні невдалі входи на реальні імена користувачів.
- Brute force SMTP AUTH (Postfix SASL, Exim): повторні збої SASL, часто з ботнетів.
- Brute force веб-адмінок/інтерфейсів (Roundcube, Rspamd WebUI, mailcow admin, кастомні панелі): підбір паролів і перевірка сесій.
- Зловживання протоколом SMTP: некоректні HELO, зловживання pipelining, словникові атаки «RCPT TO». Іноді це сканування на спам; іноді — прелюдія до зловживання.
- Credential stuffing: небагато спроб із кожної IP-адреси. Саме тут наївні конфігурації fail2ban зазнають поразки, бо кожна IP залишається нижче порога.
За що fail2ban добре (а за що ні)
Fail2ban найкраще підходить для обмеження темпу по IP на основі логів. Якщо атакувальник використовує одну IP для «перебивання» автентифікації, ви можете швидко його відключити. Якщо ж спроби розпорошені по тисячах IP, fail2ban стає менш дієвим; тоді потрібні заходи на рівні провайдера або upstream (greylisting, репутація, обмеження швидкості, CAPTCHA для веб‑інтерфейсів, MFA або фільтрація на рівні провайдера).
Також: fail2ban не замінює правильну поштову безпеку. Потрібні сильні паролі, MFA де можливо, відключення plaintext auth, і розумне скорочення експозиції (не публікуйте адмін‑панелі, якщо це можна уникнути).
Цікаві факти й історія (атаки на пошту існували не вчора)
- SMTP старший за сучасну автентифікацію. SMTP був створений на початку 1980-х для кооперативних мереж; додавання auth і TLS з’явилося значно пізніше.
- Колись «open relay» були нормою. У 1990-х багато MTA просто ретранслювали пошту; спам зробив це liability і привів до обмежень ретрансляції.
- Greylisting набув популярності на початку 2000-х. Він експлуатував факт, що легітимні MTA повторно надсилають доставку; багато спам‑ботів цього не робили.
- SASL старіший, ніж багато хто думає. Simple Authentication and Security Layer походить з кінця 1990-х і створений для стандартизації автентифікації в різних протоколах.
- fail2ban з’явився в середині 2000-х. Він став частиною хвилі «лог‑керованої автоматизації» на Linux — простий, ефективний і небезпечно легкий для неправильного налаштування.
- Ботнети перейшли від одиничних джерел до розподілених атак. Сьогодні credential stuffing часто використовує багато IP із низьким обсягом спроб, знижуючи ефективність наївних IP‑банів.
- Journald змінив правила гри для парсингу логів. Коли системи перейшли від плоских файлів до структурованих логів, інструменти, що припускали /var/log/*, мусили адаптуватися.
- IPv6 зробив «банити /24» застарілим. Атакувальники можуть ротаціювати адреси у великих діапазонах, а необачне блокування IPv6 може вивести з ладу легітимні мережі.
- Пошта лишається топовим вектором компрометації. Не тому, що SMTP магічний, а тому, що облікові дані дають доступ до скидання паролів, рахунків і внутрішньої довіри.
Спочатку налаштуйте логи (інакше fail2ban — плацебо)
Fail2ban може діяти лише на те, що він бачить. Більшість заяв «fail2ban не працює» зводяться до однієї з трьох проблем:
- Сервіс не логує збої автентифікації у форматі, що парситься.
- Логи йдуть туди, куди fail2ban не дивиться (journald vs files, контейнери, chroot, розподілений syslog).
- Regex не збігається з реальними рядками (бо формат логів у вашому дистрибутиві відрізняється від очікуваного).
Визначте бекенд: file чи systemd/journald
У сучасних дистрибутивах часто варто використовувати бекенд systemd, щоб не ганятися за ротованими файлами й проблемами з правами. Але якщо ваші MTA пишуть у класичні syslog‑файли, tail файлів теж підходить. Виберіть один підхід на хост і тримайтеся його; гібридні конфіги — це місце, куди йдуть надії на просту діагностику.
Також: врахуйте, що поштові системи часто розподілені по контейнерах або окремих ВМ. Якщо Postfix працює в одному контейнері, а Dovecot в іншому, fail2ban у третьому контейнері не побачить логи, якщо ви їх не пересилаєте. Повідомлення «jail enabled» нічого не означає, якщо воно дивиться в порожню кімнату.
Жарт №1: Єдина річ, що надійніша за brute‑force бота — це керівник, який «нічого не змінював» одразу перед інцидентом.
Jails для пошти, що ловлять реальні атаки
Нижче — jails, що працюють у реальних стосунках Postfix + Dovecot, а також кілька цілей, пов’язаних із веб‑інтерфейсом. Мета не в «забанити все». Мета: швидко банити з високою ймовірністю зловживань і обережно ставитися до неоднозначних сигналів.
Базові припущення
- Ви використовуєте fail2ban 0.11+ (новіше краще, особливо для покращень systemd бекенду).
- Дії фаєрволу послідовні: nftables на сучасних Debian/Ubuntu, firewalld на RHEL‑подібних, iptables на старих установках.
- Ваші поштові сервіси логують IP клієнта в тому ж рядку, що й помилка (або в корельованому рядку, який підтримує фільтр).
Postfix SASL auth failures (SMTP AUTH brute force)
Цей jail банить повторні помилки SASL автентифікації, що є сигналом високої якості. Він ловить класичну атаку «спробувати 10 паролів для user@domain» швидко.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/postfix-sasl.local
[postfix-sasl]
enabled = true
backend = systemd
filter = postfix[mode=auth]
maxretry = 6
findtime = 10m
bantime = 4h
bantime.increment = true
bantime.factor = 2
bantime.multipliers = 1 2 4 8 16 32
action = nftables-multiport[name=postfix-sasl, port="smtp,submission,submissions"]
journalmatch = _SYSTEMD_UNIT=postfix.service
Чому це працює: Воно прив’язане до помилок автентифікації, а не до загальної протокольної багатослівності. Використовується зростаючий bantime, тож повторні порушники отримують довші блокування, не караючи назавжди того, хто один раз невдало ввів пароль.
Dovecot auth failures (IMAP/POP brute force)
Dovecot‑логи, як правило, прості та містять віддалену IP. Це робить чудовий jail — знову ж таки подія високого сигналу.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/dovecot.local
[dovecot]
enabled = true
backend = systemd
filter = dovecot
maxretry = 5
findtime = 10m
bantime = 6h
bantime.increment = true
bantime.factor = 2
bantime.multipliers = 1 2 4 8 16
action = nftables-multiport[name=dovecot, port="imap,imaps,pop3,pop3s"]
journalmatch = _SYSTEMD_UNIT=dovecot.service
Думка: Якщо ви тримаєте IMAP/POP у публічному інтернеті, вам потрібен цей jail. «У нас лише кілька користувачів» — не стратегія; це розклад вашого наступного інциденту.
Roundcube (brute force входу в вебпошту)
Логи Roundcube різняться в залежності від налаштувань, і багато хто забуває ввімкнути корисне логування. Fail2ban все одно може допомогти, якщо у вас є послідовні рядки про невдалі входи в syslog або логах Roundcube.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/roundcube.local
[roundcube]
enabled = true
backend = auto
filter = roundcube-auth
logpath = /var/log/roundcube/errors.log
maxretry = 5
findtime = 15m
bantime = 12h
action = nftables-multiport[name=roundcube, port="http,https"]
Ключова деталь: Brute force вебпошти часто походить з невеликої кількості IP, але credential stuffing може не бути таким. Цей jail допомагає при першому сценарії.
Rspamd WebUI (brute force адмін‑панелі)
Якщо ви відкрили Rspamd WebUI в інтернеті — ви вибираєте проблему. Якщо ж цього не можна уникнути, захистіть принаймні інтерфейс.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/rspamd.local
[rspamd]
enabled = true
backend = systemd
filter = rspamd
maxretry = 4
findtime = 10m
bantime = 24h
action = nftables-multiport[name=rspamd, port="http,https"]
journalmatch = _SYSTEMD_UNIT=rspamd.service
Recidive: ловіть повторних порушників у всіх jails
Recidive відстежує сам лог fail2ban. Якщо IP повторно банять з часом, він отримує довший бан. Це одна з небагатьох функцій «ввімкнув і забув», яка насправді економить час.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/recidive.local
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
backend = auto
bantime = 7d
findtime = 1d
maxretry = 3
action = nftables-allports[name=recidive]
Коли не банити: шум «SMTP rejected»
Вас спокушатиме банити за рядками Postfix «NOQUEUE: reject». Починайте з цього лише в останню чергу. Багато reject — це легітимні некоректні налаштування від реальних відправників, і їх бан може створити дивні проблеми з доставкою, які важко буде пояснити.
Якщо ви робите jail для протокольного зловживання, тримайте його консервативним і пильнуйте. Розглядайте це як «зменшення шуму логів», а не як повноцінну безпеку.
Майданчик для regex: перевіряйте збіг перед баном
Ваші фільтри настільки ж хороші, як і ваш regex. Практичний метод такий:
- Зберіть репрезентативні рядки з логів (правильні, хибні й дивні).
- Використайте
fail2ban-regexпроти реальних логів. - Налаштовуйте до тих пір, поки збіги будуть коректні, а хибні спрацьовування — рідкісні.
- Тільки тоді вмикайте jail.
Одна цитата, яку операційники повторно вивчають нелегким шляхом:
«Сподівання — не стратегія.» — перефразована ідея, часто згадувана в операційних колах
Жарт №2: Regex — як бензопила: потужний, галасливий, і рано чи пізно ви поріжетеся, якщо махатимете ним без нагляду.
Практичні завдання: команди, виводи, рішення (12+)
Завдання 1: Підтвердити, що fail2ban працює і не перезапускається
cr0x@server:~$ systemctl status fail2ban --no-pager
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-01-04 08:11:22 UTC; 2h 14min ago
Docs: man:fail2ban(1)
Main PID: 1047 (fail2ban-server)
Tasks: 5 (limit: 18963)
Memory: 64.3M
CPU: 2min 18.541s
Що це означає: «active (running)» зі стабільним аптаймом натякає, що демона не падає й не перезапускається постійно.
Рішення: Якщо він перезапускається або неактивний — вирішіть це першочергово. Жодне тонке налаштування regex не допоможе, якщо демон мертвий.
Завдання 2: Перелічити включені jails (перевірка реальності)
cr0x@server:~$ sudo fail2ban-client status
Status
|- Number of jail: 4
`- Jail list: dovecot, postfix-sasl, recidive, rspamd
Що це означає: Це єдині jails, що щось роблять.
Рішення: Якщо потрібного jail немає в списку, він не увімкнений або не завантажився. Читайте journalctl -u fail2ban.
Завдання 3: Перевірити лічильники одного jail
cr0x@server:~$ sudo fail2ban-client status postfix-sasl
Status for the jail: postfix-sasl
|- Filter
| |- Currently failed: 12
| |- Total failed: 981
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 7
|- Total banned: 103
`- Banned IP list: 198.51.100.23 203.0.113.14 203.0.113.77
Що це означає: «Currently failed» — кількість помилок у вікні; «Currently banned» — активні блокування.
Рішення: Якщо «Total failed» росте, а банів нуль, можливо, maxretry занадто високий, findtime занадто короткий, або фільтр збігається, але дія не працює.
Завдання 4: Підтвердити інтеграцію з фаєрволом (приклад nftables)
cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
tcp dport { 22, 25, 465, 587, 993 } accept
}
}
table inet f2b-table {
set f2b-postfix-sasl {
type ipv4_addr
flags timeout
}
chain f2b-postfix-sasl {
ip saddr @f2b-postfix-sasl drop
}
}
Що це означає: Є таблиця/сет fail2ban для jail. Якщо її нема — дія не застосувала правила.
Рішення: Якщо fail2ban каже, що банить IP, але nftables не має сетів/ланок, ви використовуєте неправильну action або бракує прав/можливостей.
Завдання 5: Підтвердити, що Postfix логуватиме SASL збої там, де їх бачить fail2ban
cr0x@server:~$ sudo journalctl -u postfix.service -S "30 min ago" | grep -E "SASL|authentication failed" | tail -n 5
Jan 04 10:12:43 mail postfix/smtpd[22901]: warning: unknown[203.0.113.77]: SASL LOGIN authentication failed: authentication failure
Jan 04 10:12:45 mail postfix/smtpd[22901]: warning: unknown[203.0.113.77]: SASL LOGIN authentication failed: authentication failure
Що це означає: Ви бачите очікувані рядки з видимими IP.
Рішення: Якщо їх немає, можливі варіанти: SASL логін у іншому unit/фасиліті, або помилки автентифікації приглушені. Виправте логування перш ніж налаштовувати фільтри.
Завдання 6: Підтвердити формат помилки автентифікації Dovecot
cr0x@server:~$ sudo journalctl -u dovecot.service -S "30 min ago" | grep -i "auth failed" | tail -n 3
Jan 04 10:06:12 mail dovecot: auth: passwd-file(jdoe,203.0.113.14): Password mismatch
Jan 04 10:06:15 mail dovecot: imap-login: Aborted login (auth failed, 1 attempts): user=<jdoe>, method=PLAIN, rip=203.0.113.14, lip=192.0.2.10, TLS
Що це означає: Є rip= (віддалена IP), на що орієнтуються багато стандартних фільтрів.
Рішення: Якщо у ваших рядках немає IP, потрібен інший фільтр або інші налаштування логування Dovecot.
Завдання 7: Протестувати фільтр на реальних логах перед увімкненням
cr0x@server:~$ sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/postfix.conf --print-all-matched
Running tests
=============
Use failregex file : /etc/fail2ban/filter.d/postfix.conf
Use log file : /var/log/auth.log
Results
=======
Failregex: 18 total
|- #) [# of hits] regular expression
| 1) [18] warning: .*?\[<HOST>\]: SASL .* authentication failed
`-
Lines: 12458 lines, 0 ignored, 18 matched, 12440 missed
Що це означає: Regex відпрацьовує саме ті рядки, яких ви очікуєте. «Missed» — усе інше.
Рішення: Якщо збігів нуль — виправте regex або logpath. Якщо збігів забагато — ви могли б підхоплювати дружні рядки й потрібно звузити вираз.
Завдання 8: Прокрутити параметри бану в сухому прогоні через fail2ban-client get
cr0x@server:~$ sudo fail2ban-client get postfix-sasl maxretry
6
cr0x@server:~$ sudo fail2ban-client get postfix-sasl findtime
600
cr0x@server:~$ sudo fail2ban-client get postfix-sasl bantime
14400
Що це означає: Значення в секундах для деяких запитів. 600 секунд = 10 хв; 14400 = 4 години.
Рішення: Якщо у вас ненадійні мобільні клієнти або NAT‑офіси, подумайте про трохи вищий maxretry або коротший bantime спочатку, потім збільшуйте, коли помилкові спрацьовування під контролем.
Завдання 9: Перевірити логи fail2ban на помилки дій (мовчазний вбивця)
cr0x@server:~$ sudo tail -n 50 /var/log/fail2ban.log
2026-01-04 10:12:49,381 fail2ban.actions [1047]: NOTICE [postfix-sasl] Ban 203.0.113.77
2026-01-04 10:12:49,512 fail2ban.actions [1047]: ERROR Failed to execute ban jail 'postfix-sasl' action 'nftables-multiport': returned 127
2026-01-04 10:12:49,513 fail2ban.actions [1047]: ERROR Invariant check failed. Trying again...
Що це означає: Fail2ban «забанив» у своїй базі, але дія не виконалася (exit 127 часто означає відсутній бінарник або неправильну команду).
Рішення: Виправте інструментарій дій (шлях до nft, права, визначення action) перед тим, як довіряти лічильникам банів.
Завдання 10: Перевірити, чи ви не баните NAT (офіс) і не шкодите багатьом користувачам
cr0x@server:~$ sudo fail2ban-client status dovecot
Status for the jail: dovecot
|- Filter
| |- Currently failed: 2
| |- Total failed: 204
| `- File list: /var/log/mail.log
`- Actions
|- Currently banned: 1
|- Total banned: 9
`- Banned IP list: 198.51.100.10
Що це означає: Одна IP зараз заблокована. Якщо це корпоративний NAT, ви щойно заблокували всіх позаду нього.
Рішення: Якщо так сталося, додайте цільовий список ігнорів для відомих egress IP офісів, але лише після перевірки, що ви не вносите до білого списку атакувальника за NAT‑ом офісу.
Завдання 11: Додати ignore IP безпечно (і зберегти аудиторію)
cr0x@server:~$ sudo sed -n '1,120p' /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.0.2.0/24 198.51.100.10
Що це означає: Ці джерела ніколи не будуть банитися жодним jail.
Рішення: Утримуйте списки ігнорів мінімальними. Бажано білити тільки фіксовані egress IP, якими ви керуєте й які моніторите. Не додавайте величезні діапазони ISP тільки тому, що один VIP поскаржився.
Завдання 12: Розбанити IP (і потім розібратися, чому він був забанений)
cr0x@server:~$ sudo fail2ban-client set dovecot unbanip 198.51.100.10
1
Що це означає: «1» означає успіх (один бан видалено).
Рішення: Розбаньте, а потім негайно розберіться: помилка користувача, credential stuffing чи клієнт, що зламався? Якщо ви не відповісте на це питання, завтра ви повернетесь сюди знову.
Завдання 13: Підтвердити, що jail дивиться на потрібне джерело (systemd backend)
cr0x@server:~$ sudo fail2ban-client get postfix-sasl backend
systemd
cr0x@server:~$ sudo fail2ban-client get postfix-sasl journalmatch
_SYSTEMD_UNIT=postfix.service
Що це означає: Jail читає логи з journald, відфільтровані по unit Postfix.
Рішення: Якщо journalmatch порожній і система галаслива, ви можете парсити не пов’язані рядки й отримувати абсурдні бани. Додайте відповідний match.
Завдання 14: Виміряти швидкість атаки для налаштування порогів
cr0x@server:~$ sudo journalctl -u postfix.service -S "1 hour ago" | grep -c "SASL LOGIN authentication failed"
482
Що це означає: 482 помилки за годину — це не «фонове радіаційне» явище. Це активне зловживання або відмова клієнта.
Рішення: Якщо швидкість висока, тримайте findtime коротким (5–15 хв), щоб бани спрацьовували швидко. Якщо швидкість низька і ви боїтесь хибних позитивів, подовжіть findtime і підвищте maxretry.
Швидкий план діагностики
Коли «пошта повільна» або «люди не можуть увійти» і ви підозрюєте fail2ban, ви потребуєте швидкості. Не досконалості. Ось найкоротший шлях до істини.
По‑перше: чи справді fail2ban блокує трафік?
- Перевірте активні бани в релевантному jail (
fail2ban-client status <jail>). - Перевірте, чи існують правила/сети фаєрволу та чи містять заблоковані IP (вивід nftables/iptables).
- Якщо ви використовуєте зворотний проксі або балансувальник навантаження, підтвердьте, що source IP у логах — реальний клієнт, а не проксі.
По‑друге: чи jail збігається з правильними рядками логів?
- Візьміть один недавній рядок помилки з journald/syslog.
- Запустіть
fail2ban-regexпроти нього (або невеликої частини логу) з точним фільтром, що використовує jail. - Перевірте, чи витягнуто правильний хост (особливо з IPv6, адресами в дужках або оболонками «unknown»).
По‑третє: чи це проблема клієнта, що маскується під атаку?
- Шукайте одного користувача, що генерує повторні помилки з одного NAT IP.
- Перевірте, чи недавно змінювався пароль (логі helpdesk, синхронізація директорії, відкликання OAuth токена).
- Якщо це мобільна пошта, припускайте застарілі облікові дані і агресивну логіку повторних спроб, поки не доведено протилежне.
По‑четверте: чи «атака» розподілена?
- Порахуйте унікальні IP, що спричинили помилки автентифікації за останню годину.
- Якщо число велике і кожна IP мала мало спроб, fail2ban лише трохи зачепить краєчки.
- Перемкніться на обмеження швидкості, фільтрацію upstream, сильнішу автентифікацію або тимчасово відключайте відкриті ендпоїнти автентифікації, що не потрібні.
Типові помилки: симптом → причина → виправлення
1) «fail2ban каже, що забанив, але атакувальник продовжує спроби»
Симптом: Jail показує бани; логи продовжують демонструвати помилки від тієї ж IP.
Причина: Помилкова конфігурація action (неправильний backend action, відсутні nft/iptables, firewalld не запущено), або бани застосовуються до IPv4, а трафік йде по IPv6.
Виправлення: Перевірте наявність правил фаєрволу та що chain підключений в INPUT. Переконайтеся, що action підтримує inet/IPv6; використовуйте nftables inet table або dual‑stack дії.
2) «Користувачі за офісним NAT не можуть перевірити пошту»
Симптом: Декілька користувачів повідомляють про тайм‑аути IMAP/SMTP; один IP заблоковано.
Причина: Один некоректний клієнт за NAT спричиняє бани для всіх.
Виправлення: Трохи підвищте maxretry для Dovecot/Postfix auth, увімкніть інкрементальні бани і додайте вузько окреслений ignoreip лише якщо ви можете моніторити та довіряти цьому egress.
3) «Ніколи не відбувається банів, але логи показують помилки»
Симптом: Total failed залишається нулем; логи fail2ban мовчать.
Причина: Неправильний backend/logpath. Наприклад: jail читає /var/log/auth.log, але система логівує лише в journald.
Виправлення: Перейдіть на backend = systemd з journalmatch, або налаштуйте rsyslog, щоб він писав очікуваний файл.
4) «Бани вибухнули після оновлення»
Симптом: Тисячі банів, в тому числі легітимні клієнти.
Причина: Змінився формат логів (оновлення пакету, нова деталізація), і regex тепер підхоплює більше, ніж потрібно.
Виправлення: Запустіть fail2ban-regex на зразку нових логів; звузьте вираз; додайте ignoreregex для відомих дружніх рядків.
5) «Ми забанили балансувальник»
Симптом: Все відпало одночасно; логи показують один і той же внутрішній IP із повторними помилками автентифікації.
Причина: X-Forwarded-For не передається або поштовий проксі ховає IP клієнта, тож усі помилки виглядають від проксі.
Виправлення: Виправте логування, щоб включати реальний IP клієнта, або запускайте fail2ban на периферії, де ви бачите клієнтів. Не гадьте.
6) «recidive банить хороші мережі на тиждень»
Симптом: Довгі блокування після коротких спалахів помилок.
Причина: Первинні jails були надто агресивно налаштовані, спричинивши хибні бани; recidive їх підсилює.
Виправлення: Пом’якште первинні jails (підніміть maxretry, скоротіть bantime), потім знову увімкніть recidive, коли хибні спрацьовування стануть рідкісними.
7) «Надсилання пошти з мобільних мереж нестабільне»
Симптом: Випадкова неможливість підключитися з LTE, але по Wi‑Fi все працює.
Причина: Надто широкі бани за SMTP rejects або протокольні аномалії; мобільні оператори широко використовують NAT.
Виправлення: Уникайте банів за загальними SMTP rejects. Баньте за помилками автентифікації та явними зловживаннями, а не за «клієнт сказав дивний HELO».
Три корпоративні міні-історії (як це ламається в реальних компаніях)
Міні-історія 1: Інцидент через неправильне припущення
Середня компанія мігрувала пошту з старої ВМ на новий дистрибутив. Вони скопіювали стару конфігурацію fail2ban дослівно: ті самі jails, ті самі шляхи логів, ті самі фільтри. Навіть раділи: «Все ідентично, отже безпечно.»
Що змінилося — нудне: логування перейшло до journald, і rsyslog більше не писав /var/log/auth.log за замовчуванням. Fail2ban відстежував файл, що існував, але по суті був порожнім. Тим часом Postfix SASL‑помилки накопичувалися в journald, непомічені.
Першим сигналом був не «нашу пошту атакують». Першим сигналом був CPU: воркери Dovecot були зайняті відхиленням входів увесь день. Другим сигналом — захоплення облікового запису: один повторно використаний пароль, один скомпрометований поштовий ящик, а потім спалах вихідного спаму, що вдарив по репутації їх IP.
Виправлення не було героїчним. Вони переключилися на backend = systemd, додали journalmatch для кожного сервісу, протестували fail2ban-regex, і раптом бани почали з’являтися з потрібних причин. Урок не в «використовувати journald». Урок — «ніколи не припускайте, що ваші логи лишилися там, де були».
Міні-історія 2: Оптимізація, що дала зворотний ефект
Інша організація мала геніальну ідею: зменшити обсяг логів. Логи пошти були величезні, дисковий простір «занадто дорогий», і хтось вирішив знизити деталізацію логування автентифікацій. Менше диска, менше алертів — всі щасливі.
Через два тижні вони помітили нову картину: користувачі періодично блокувалися. Система директорії показувала дивні спроби входу, але поштові хости не мали достатньої деталізації, щоб надійно атрибутувати джерела. Бани fail2ban стали хаотичними, бо залишкові логи не завжди містили віддалену IP у рядках помилок.
Вони «оптимізували» ще далі, знизивши maxretry і збільшивши bantime для компенсації. Так вони опинилися з банами готельних Wi‑Fi та конференц‑мереж на цілий день. Тікети підтримки зросли. До керівництва дійшли розмови. Ви знаєте далі.
Вони повернули логування з контекстом автентифікації, зберегли розумну ротацію логів і перемістили дискусію про вартість у правильну площину: зберігання дешевше за інциденти. Потім налаштували fail2ban на підставі виміряних швидкостей помилок, а не відчуттів.
Міні-історія 3: Нудна, але правильна практика, що врятувала вечір
Регульована компанія запускала пошту в сегментованому середовищі: окремий front‑end SMTP, окремий IMAP і мережа управління. Їх конфіг fail2ban був неяскравий. Кожен jail тестували з fail2ban-regex під час огляду змін. Кожен запис у білому списку мав посилання на тікет. Всі дії використовували один бекенд фаєрволу (nftables) на всіх хостах.
Одного п’ятничного вечора на їх IMAP націлився credential stuffing. Атака була розподілена й «low‑and‑slow» по кожній IP. Fail2ban не зупинив усіх спроб, бо не може банити те, що ніколи не переходить поріг. Але він швидко зупинив гучну частину, завдяки чому сервіс залишився відзивним і логи — читабельними.
Справжній виграш прийшов від їх «нудних» панелей: вони відстежували швидкість помилок автентифікації та кількість унікальних IP. За годину вони розпізнали підпис stuffing. Тимчасово посилили ліміти на периферії, примусили скидання паролів для кількох цільових акаунтів і вмикнули додаткове MFA для вебпошти.
У понеділок було спокійно. Ніяких героїчних нічних вахт. Звіт по інциденту був майже нудно простим: протестовані правила, послідовне логування і метрики. Успіх операцій часто виглядає так, ніби ніхто не помітив, що ви взагалі щось робили.
Чек‑листи / покроковий план
Крок 1: Встановіть видимість (перед тим, як банити)
- Виберіть джерело логів: journald або файли. Не змішуйте без потреби.
- Підтвердьте, що бачите рядки помилок Postfix і Dovecot з IP.
- Увімкніть логування fail2ban у відомий файл (
/var/log/fail2ban.log— типовий варіант).
Крок 2: Почніть з jails з високим сигналом
- Увімкніть Postfix SASL auth jail.
- Увімкніть Dovecot auth jail.
- Опційно увімкніть веб‑UI jails (Roundcube, Rspamd) тільки якщо вони доступні з інтернету.
Крок 3: Налаштуйте пороги на основі вимірів
- Виміряйте помилки автентифікації за годину і кількість унікальних IP.
- Встановіть
maxretry, щоб ловити боти, а не помилки при наборі (почніть з 5–6). - Використайте
findtime10–15 хв, щоб ловити спалахи. - Використайте інкрементальний bantime, щоб карати повторних зловмисників без сталих помилок для легітимних користувачів.
Крок 4: Розгортайте обережно
- Вмикайте один jail за раз.
- Слідкуйте за банами 24 години.
- Аудитуйте перші десяток заблокованих IP: підтвердіть, що це реальне зловживання.
- Лише після цього вмикайте recidive.
Крок 5: Зробіть процес життєздатним для on‑call
- Документуйте як розбанити і де дивитися логи.
- Тримайте списки ігнорів мінімальними і піддайте їх перевірці.
- Переконайтеся, що бекенд фаєрволу послідовний на всіх хостах (nftables або firewalld; оберіть один).
Питання й відповіді
1) Де запускати fail2ban: на поштовому сервері чи на фаєрволі?
Запускайте там, де ви надійно бачите реальний IP клієнта і де бан справді блокує трафік. Якщо логи показують IP проксі — запускайте fail2ban на проксі/на периферії або виправте логування.
2) Які стартові значення для maxretry/findtime/bantime розумні?
Для помилок автентифікації: maxretry=5–6, findtime=10m, bantime=4–12h, плюс інкрементальні бани. Під’єднайте тонкі налаштування після вивчення хибних спрацьовувань і темпу атак.
3) Чому бачу багато «failed», але мало банів?
Або помилки розподілені по багатьох IP (розподілена атака), або ваші пороги занадто лояльні. Порахуйте унікальні IP за годину; якщо їх багато, fail2ban не буде панацеєю.
4) Чи зупинить fail2ban credential stuffing?
Частково. Він зупиняє гучну частину атак. Для справжнього stuffing (багато IP, небагато спроб від кожного) потрібні додаткові заходи: обмеження швидкості, MFA, кращі паролі і іноді фільтрація upstream по репутації.
5) Чи банити по рядках Postfix «NOQUEUE: reject»?
Не починайте з цього. Ці рядки містять багато дружніх невдач. Почніть з помилок автентифікації. Якщо пізніше додаєте bans за протокольне зловживання — робіть це консервативно і під моніторингом.
6) Як уникнути банів цілих офісів за NAT?
Використовуйте інкрементальний bantime, тримайте maxretry трохи вищим для IMAP, якщо у вас багато мобільних користувачів, і розгляньте білінг лише для стабільних egress IP, якими ви володієте і моніторите. Краще: освітіть користувачів і застосовуйте MFA де можливо.
7) Чи змінює IPv6 щось?
Так. Переконайтеся, що ваші дії підтримують IPv6 і що фільтри правильно витягують IPv6‑адреси. Також уникайте необережного «бану діапазону» — IPv6 робить це ризикованим дуже швидко.
8) Чи варто вмикати recidive?
Так, але не в перший день. Спочатку доведіть, що базові jails мають низький рівень хибних спрацьовувань. Recidive підсилює ваші налаштування — в хорошому чи поганому сенсі.
9) Який найбезпечніший спосіб тестувати нові фільтри?
Використовуйте fail2ban-regex проти реальних логів і перевіряйте знайдені рядки. Не розгортайте фільтр, який не перевірили на вашому форматі логів.
10) Як зрозуміти, чи fail2ban — вузьке місце?
Зазвичай ні. Вузьке місце — це бекенди автентифікації (LDAP/SQL), I/O диска через надмірне логування або CPU від TLS/auth воркерів. Fail2ban часто лише месенджер — і часом козел відпущення.
Висновок: наступні кроки, що не призведуть до фіаско
Якщо ви хочете, щоб fail2ban для пошти справді допомагав, ставтеся до нього як до продакшн‑коду: спостережуваного, протестованого й розгортаного поетапно.
- Підтвердьте логування спочатку (unit сервісу, джерело логів, наявність IP у рядках помилок).
- Увімкніть лише jails з високим сигналом (Postfix SASL, Dovecot auth) і доведіть збіги за допомогою
fail2ban-regex. - Використовуйте інкрементальний bantime, щоб карати повторні зловживання й зменшувати побічні ушкодження.
- Перевірте дію фаєрволу (nftables/iptables — правила існують і справді впливають на трафік).
- Додавайте recidive останнім, коли довіряєте рівню хибних спрацьовувань.
- Опишіть процедуру розбану і тримайте білі списки маленькими та під звітністю.
Зробіть це — і fail2ban стане тим, чим має бути: не «театром безпеки», а корисним, малопідтримуваним відбійником для найочевидніших кривдників.