Логи сервера: як читати сліди зломщиків до того, як вони щось зламали
Уявіть собі ситуацію: ви заходите до квартири і бачите, що хтось переставив ваші кросівки біля дверей. Нічого не вкрали, замок цілий, але щось не так. Саме так працюють серверні логи - вони фіксують кожен "слід" ще до того, як зламано хоча б один файл. Проблема в тому, що 78% адміністраторів дивляться в логи тільки після інциденту. А треба було - до нього. Давайте розберемося, як перетворити гори нечитабельного тексту на вашу першу лінію серверної оборони.
Чому логи - це камери спостереження вашого сервера
Коли ви встановлюєте камеру в офісі, ви ж не чекаєте, поки хтось обчистить сейф, щоб подивитися запис? З логами має бути та сама логіка. Кожен запит до сервера, кожна невдала спроба авторизації, кожна підозріла зміна конфігурації - все це фіксується автоматично. Безкоштовно. Без додаткових плагінів.
Серверні логи - це єдине джерело правди про те, що відбувається на вашій машині прямо зараз. Не моніторинг (він реагує із затримкою), не файрвол (він блокує, але не пояснює), а саме логи розкажуть повну історію.
Ось що фіксують основні лог-файли:
- access.log - кожен HTTP-запит: хто прийшов, звідки, що хотів і що отримав
- error.log - помилки сервера, зокрема спроби доступу до неіснуючих ресурсів
- auth.log (secure) - всі спроби входу через SSH, FTP, панель керування
- syslog - системні події: перезапуски служб, зміни конфігурації, cron-задачі
- mail.log - вся поштова активність, включаючи спроби розсилки спаму з вашого сервера
Анатомія підозрілого запису: що шукати і де
Відкрийте auth.log на будь-якому VPS, що простояв хоча б тиждень у відкритому інтернеті. Гарантую - ви здивуєтесь. Сотні, а то й тисячі спроб підібрати пароль до SSH. Це не персональна атака на вас. Це автоматичні боти, що сканують весь інтернет 24/7.
Ось як виглядає типовий слід брутфорс-атаки в auth.log:
"Failed password for root from 185.234.xx.xx port 45322 ssh2" - якщо ви бачите 50+ таких записів за хвилину з однієї IP-адреси, хтось активно ламає ваш SSH. Якщо з різних IP - це розподілений ботнет, і тут потрібна інша стратегія."
Але брутфорс - це очевидно. Набагато небезпечніше те, що ховається в access.log. Ось типові маркери розвідки перед серйозною атакою:
- Масові запити до /wp-admin, /admin, /phpmyadmin - бот шукає панелі керування
- Запити з параметрами типу ?id=1' OR '1'='1 - спроба SQL-ін'єкції
- GET-запити до /.env, /config.php, /wp-config.php.bak - полювання на конфіги з паролями
- Незвичний User-Agent (python-requests, sqlmap, nikto) - інструменти автоматичного зламу
- Код відповіді 200 на запит, який мав дати 404 - можливо, зловмисник вже щось знайшов
Остання точка - найстрашніша. Якщо хтось запитує /backup.zip і отримує 200, це означає, що ваш бекап лежить у відкритому доступі. Прямо зараз.
Інструменти аналізу: від grep до SIEM
Читати логи очима - це як шукати голку в стозі сіна вручну. Можна, але навіщо, коли існують магніти? Вибір інструменту залежить від масштабу вашої інфраструктури та, будемо чесними, вашого бюджету.
| Інструмент | Для кого | Вартість | Складність |
|---|---|---|---|
| grep + awk + cron | Один VPS, один адмін | Безкоштовно | Середня |
| GoAccess | Візуалізація access.log | Безкоштовно | Низька |
| Fail2Ban | Автоблокування брутфорсу | Безкоштовно | Низька |
| ELK Stack (Elasticsearch + Logstash + Kibana) | 5+ серверів, команда | Безкоштовно (self-hosted) | Висока |
| Graylog | Середній бізнес | Від $0 до $1500/міс | Висока |
| Splunk / Datadog | Корпорації, складна інфраструктура | Від $100/міс | Висока |
Для більшості невеликих проєктів зв'язка Fail2Ban + базові grep-скрипти в cron вирішує 80% задач. Наприклад, простий скрипт, що щоранку відправляє вам на пошту топ-20 IP-адрес з найбільшою кількістю невдалих входів - це 15 хвилин роботи, яка замінює години ручного перегляду.
П'ять сценаріїв, коли логи рятують бізнес
Теорія - це чудово. Але я хочу розповісти про реальні випадки, де вчасний аналіз логів врятував ситуацію.
Сценарій 1: Тихий майнер. Клієнт помітив, що сервер працює повільніше за звичне. CPU завантажений на 95%. У syslog знайшли процес, який запускався через cron кожну хвилину під користувачем www-data. Зловмисник залив криптомайнер через вразливість у плагіні WordPress ще три тижні тому. Лог access.log чітко показав момент зламу - POST-запит до застарілого плагіна з IP-адреси в Бразилії.
Сценарій 2: Витік бази даних. У error.log з'явились дивні повідомлення MySQL про надто довгі запити. Аналіз показав - хтось повільно витягував базу через time-based SQL-ін'єкцію. По одному символу за раз. Атака тривала два дні, і без логів її б не помітили взагалі.
Сценарій 3: Інсайдер. Колишній співробітник зберіг SSH-ключ і заходив на сервер о 3 ранку. auth.log показав авторизацію з його домашньої IP-адреси. Без логів - ніяких доказів.
Сценарій 4: DDoS перед Чорною п'ятницею. access.log зафіксував різке зростання запитів з 200 до 50 000 за хвилину за 4 години до піку продажів. Вчасне виявлення дозволило підключити CDN і налаштувати rate limiting до того, як сайт "ліг".
Сценарій 5: Зараження поштою. mail.log показав, що за ніч з сервера відправлено 12 000 листів. Спамер використав незахищену контактну форму. Ще день - і IP потрапила б у чорні списки, а всі легітимні листи полетіли б у спам.
Налаштування ротації та зберігання: не дайте логам з'їсти ваш диск
Логи мають неприємну особливість - вони ростуть. Швидко. Сайт із 10 000 відвідувачів на день генерує access.log на 500 МБ за місяць. Без стиснення. А якщо ввімкнено детальне логування - множте на три.
Правило номер один: logrotate має бути налаштований і перевірений, а не просто "встановлений за замовчуванням".
Ось мінімальна конфігурація, яка врятує і диск, і нерви:
- Ротація щодня, зберігання 90 днів стиснених архівів
- Компресія gzip (або zstd для швидшого пошуку)
- Відправка старих логів у окреме сховище (S3, NFS, окремий диск)
- Моніторинг розміру /var/log - алерт при заповненні на 80%
Чому 90 днів? Більшість атак виявляють у середньому через 72 дні (дані IBM X-Force за 2024 рік). Якщо ви зберігаєте логи тільки за тиждень - ви гарантовано втратите докази. А без доказів немає ні розслідування, ні можливості зрозуміти, як саме вас зламали, і закрити діру.
Автоматизація реагування: коли логи самі кличуть на допомогу
Найкращий лог - той, який не просто фіксує проблему, а запускає захист автоматично. Це не фантастика. Це стандартна практика навіть для невеликих серверів.
Ось мінімальний набір автоматичних реакцій, який варто налаштувати:
- Fail2Ban - автоматичний бан IP після N невдалих спроб входу (рекомендація: 3 спроби за 10 хвилин - бан на 24 години)
- Скрипт моніторингу нових cron-задач - будь-яка нова задача в crontab будь-якого користувача = миттєвий email адміну
- Алерт при появі нового користувача - якщо в auth.log з'являється "new user", а ви його не створювали, це червоний прапор
- Сповіщення при сплеску 4xx/5xx помилок - різке зростання помилок часто означає початок атаки або збій після несанкціонованих змін
- Перевірка цілісності лог-файлів - якщо зловмисник отримав root, перше, що він зробить, - зітре сліди з логів
Останній пункт критично важливий. Професійні зломщики завжди чистять логи. Тому централізоване зберігання логів на окремому сервері - це не розкіш, а необхідність. Відправляйте копії логів через rsyslog або Filebeat на окрему машину, до якої основний сервер має доступ тільки на запис. Навіть якщо атакуючий отримає повний контроль над вашим VPS, він не зможе дотягнутися до копій.
А хто аналізує ваші логи прямо зараз?
Ось вам проста вправа: зайдіть на свій сервер і виконайте cat /var/log/auth.log | grep "Failed" | wc -l. Число, яке ви побачите, скоріш за все вас здивує. Тисяча? Десять тисяч? Це нормально для інтернету. Ненормально - якщо ви побачили це число вперше.
Серверна безпека - це не файрвол і не SSL-сертифікат. Це щоденна звичка, як чистити зуби. Логи - це ваші очі та вуха на сервері. Вони говорять з вами кожну секунду. Питання лише в тому, чи ви слухаєте. Якщо після цієї статті ви налаштуєте хоча б Fail2Ban і щоденний email-звіт з auth.log - ви вже випередите 80% адміністраторів, які дізнаються про злам з листа від Google: "Ваш сайт може бути зламаний". Погодьтеся, неприємний спосіб почати понеділок.