Це третя частина невеликої практичної історії про захист ICanUp.
Спочатку був аналізу трафіку, який виглядав людським, але поводився як бот. Потім я описала налаштування захисту Laravel від сканування чутливих шляхів через Nginx і Fail2ban.
Після цього залишилося найцікавіше питання: що покаже захист не в контрольованій перевірці, а після ночі на реальному серверному трафіку?
Я нічого нового не додавала перед цією перевіркою. Просто залишила сервер працювати, а вранці подивилася на фактичні журнали Nginx і Fail2ban.
Що саме я хотіла перевірити після запуску
Локальна перевірка вже показала, що правила реагують на чутливі шляхи.
Але production traffic відповідає на інші питання:
- чи приходять такі запити без моєї участі;
- чи Nginx реально повертає очікуваний
403; - чи Fail2ban бачить ці події у фактичному журналі;
- чи накопичуються спрацювання до реального ban;
- чи після запуску не проявилися сценарії, яких не було в початковій перевірці.
У журналах уже були реальні спроби читати чутливі шляхи
GET /.env -> 403GET /.git/config -> 403GET /... -> 403Журнали підтвердили, що зовнішні клієнти справді намагаються звертатися до /.env, /.git/config та подібних шляхів.
Nginx зупиняв ці запити і повертав 403, тобто вони не проходили далі як звичайний application request.
Результат першої перевірки: 13 спрацювань і 5 блокувань
Fail2ban filter hits: 13 Total bans: 5 Test bans: 2Real bans: 3 Real IPs still banned: 3Ban duration: 24 hours At least one real banhappened overnight.На момент перевірки Fail2ban зафіксував 13 спрацювань фільтра і 5 блокувань загалом.
Два блокування були моїми тестовими перевірками. Три стосувалися реального зовнішнього трафіку.
Усі три реальні адреси залишалися заблокованими на 24 години, а одне з цих блокувань відбулося безпосередньо вночі.
Я навмисно не публікую самі IP. Для висновку важлива поведінка системи, а не конкретні адреси.
Ці цифри підтвердили ланцюжок Nginx -> log -> Fail2ban -> ban
scanner request | vNginx matchessensitive path | v403 response | vrequest appearsin log | vFail2ban detects it |Для мене це важливіше за окремий успішний тест.
Підтвердилася вся послідовність: Nginx розпізнає запит, повертає 403, подія з’являється в журналі, Fail2ban її знаходить і після потрібної кількості спрацювань додає адресу до ban.
Тобто захист не просто мав правильний вигляд у конфігурації. Він реально працював на трафіку, який прийшов без мого втручання.
13 спрацювань не означають 13 заблокованих адрес
Filter hit означає, що подія відповідала шаблону. Ban означає, що для конкретної адреси виконалися умови блокування.
Тому я дивлюся на ці показники окремо: кількість підозрілих подій показує активність, а bans показують, скільки джерел реально перетнули встановлений поріг.
Аналіз одночасно показав прогалину на DEV
production /.env/app/.env/.../.env blocked bysensitive-path protection DEV before the fix /.env -> blocked /app/.envПід час додаткового аналізу я побачила, що production protection працював, але DEV мав прогалину для вкладених шляхів на кшталт /app/.env.
Такий запит міг потрапити до proxy замість того, щоб зупинитися тим самим захисним правилом.
Проблему пізніше виправили і окремо підтвердили перевірками. Тут я не розбираю реалізацію виправлення, тому що важливий сам operational lesson: реальний запуск може показати різницю між середовищами.
Позитивний результат і знайдена прогалина не суперечать одне одному
Було б неправильно сказати або "захист спрацював, отже все ідеально", або "знайшли DEV-gap, отже захист не працює".
Факти були точніші: production rules реально зупиняли scanner requests і Fail2ban реально блокував джерела. Одночасно перевірка допомогла знайти окрему невідповідність у DEV.
Саме така картина для мене і є корисним результатом Build in Public: показати не тільки успішний реліз, а й те, що стало видно після нього.
Що ця перша ніч не доводить
Ці результати не означають, що сервер тепер повністю захищений.
- Вони не доводять, що в застосунку немає інших вразливостей.
- Вони не доводять, що всі можливі scanner paths уже покриті.
- Fail2ban не є повноцінним DDoS protection.
- Application-level authorization та інші security boundaries залишаються окремими шарами.
- Один успішний день не замінює подальший аналіз журналів.
Реальні журнали дали більше, ніж ще один ручний тест
controlled check known pathknown timeknown sourceknown expected result real traffic unknown sourceunknown timingreal scanner behaviorreal ban lifecycleenvironment differencesРучний test request корисний, щоб перевірити конкретний expected result.
Ніч на реальному трафіку показала інше: що такі запити справді приходять, що ban lifecycle запускається без моєї участі і що різні середовища можуть поводитися не однаково.
Тому для security-змін я вважаю post-release observation окремим етапом перевірки.
Для Build in Public важливий і день після релізу
Легко написати статтю в момент, коли feature щойно завершена і всі контрольні перевірки зелені.
Набагато корисніше повернутися до неї після реального використання і відповісти: що сталося далі?
У цьому випадку відповідь хороша саме тому, що вона не ідеалізована: захист реально спрацював, були реальні bans, і водночас ми знайшли ще одну прогалину, яку початковий сценарій не показав.
Що я винесла з першої ночі
Мої висновки після ранкової перевірки:
- Scanner traffic не був теоретичним. Запити до чутливих шляхів реально приходили.
- Nginx protection спрацьовував до application layer. Для відомих шляхів журнал показував
403. - Fail2ban працював на реальному потоці подій. Було не лише тестове, а й реальне нічне блокування.
- Filter hits і bans треба читати окремо.
- Перевіряти треба всі середовища. DEV-gap для вкладеного шляху показав окрему проблему.
- Після security deploy варто дивитися на фактичну поведінку. Саме журнали дали найцінніший зворотний зв’язок.
Перший реальний трафік підтвердив захист і одночасно зробив його кращим
Після першої ночі я отримала саме той результат, заради якого й залишила захист працювати без додаткового втручання.
Nginx реально повертав 403 на scanner requests. Fail2ban реально накопичував спрацювання і блокував адреси. На момент перевірки було 13 filter hits, 5 bans загалом, 2 тестові та 3 реальні.
Одночасно аналіз виявив DEV-gap для вкладених sensitive paths, який потім був виправлений і перевірений.
Для мене це сильніший результат, ніж просто "тест пройшов": система підтвердила свою користь на реальному трафіку і одразу дала наступний конкретний сигнал для покращення.
Security-зміна стає набагато цікавішою після deploy: саме реальний трафік показує, що справді працює і що ще залишилося непоміченим.



