MAATRIX / Блог / Нагрузка выросла ночью, а трафика нет: куда смотреть первым делом

Нагрузка выросла ночью, а трафика нет: куда смотреть первым делом

MAATRIX

Алерт из мониторинга приходит в три часа ночи: CPU держится у 90-100%, load average в графике встал столбиком. Вы открываете логи веб-сервера — а там тишина, обычный ночной минимум запросов, никакого наплыва посетителей. Это одна из самых характерных картин компрометации: нагрузка есть, а легитимной причины для неё нет. Дальше — порядок действий, который отделяет ложную тревогу от реального инцидента и указывает, куда бить дальше.

Почему это тревожный паттерн, а не совпадение

Прежде чем паниковать, стоит понять, почему именно рассинхрон нагрузки и трафика — сигнал, а не шум. У обычного веб-проекта нагрузка привязана к активности: пользователи заходят, генерируют запросы, база отрабатывает выборки, процессор считает. Профиль нагрузки почти всегда пилообразный — пики в рабочие часы или вечером по местному времени аудитории, спад ночью. Если у вас аудитория в одном часовом поясе, ночью объективно должно быть тихо и на сервере, и в логах.

Когда нагрузка растёт именно в тот час, когда трафика меньше всего, а не вместе с ним — это разрыв причинно-следственной связи, которую вы привыкли видеть на графиках. Варианта, по сути, два. Либо на сервере запустилась легитимная фоновая задача — бэкап, переиндексация, batch-обработка, — и это тоже стоит проверить в первую очередь, потому что бывает чаще, чем хочется думать. Либо кто-то посторонний получил доступ и запустил свой процесс: майнер криптовалюты, который ест CPU круглосуточно, брутфорс чужих сервисов с вашей машины, сканирование сети или задачу, поставленную в расписание уже после взлома. Ночь для таких вещей — удобное время: меньше шанс, что администратор в этот момент смотрит на экран.

Отдельно стоит учитывать умение некоторых зловредов маскироваться: часть из них отслеживает запуск top или htop и на несколько секунд снижает активность, пока вы «смотрите». Если по графикам нагрузка была явно высокой, а прямо сейчас top спокоен — это повод свериться с историческими данными, а не закрывать вопрос по текущему снимку.

Шаг первый: сверяем нагрузку с сетевым трафиком

Первая развилка — легитимная ли это активность вообще, просто не в вебе. Прежде чем подозревать взлом, проверьте, не запущен ли на сервере cron-бэкап, ротация больших логов, переиндексация базы или другая тяжёлая фоновая задача по расписанию — это самая частая причина ночных всплесков, и следующие шаги как раз покажут её так же явно, как и постороннего.

Дальше смотрите на сетевую картину отдельно от логов веб-сервера — «нет трафика в логах» и «нет сетевой активности» не одно и то же. Веб-сервер логирует только HTTP(S)-запросы к вашим виртуальным хостам, а исходящий трафик — DNS-запросы майнера к пулу, соединения брутфорс-скрипта к чужим серверам, передача данных сканера — в access-логи не попадает вообще.

Посмотрите суммарный трафик интерфейса за прошедшую ночь:

vnstat -h

Это покажет почасовую статистику, если vnstat уже стоял и собирал данные до инцидента — обратный отсчёт по истории тут ценнее, чем текущий снимок. Если нужно посмотреть, что происходит прямо сейчас, по соединениям и по процессам:

iftop -P
nload
ss -tunp

ss -tunp покажет активные TCP/UDP-соединения с указанием PID процесса-владельца — это сразу связывает сетевую активность с конкретным процессом, даже если веб-сервер тут ни при чём. Обратите внимание на исходящие соединения к незнакомым IP, особенно массовые (десятки-сотни коротких соединений подряд — типичный почерк брутфорса или сканирования) и на нестандартные порты, которые не относятся ни к одному вашему сервису.

Если сетевой трафик тоже в норме, а нагрузка вся — в вычислениях (CPU), это сужает круг подозреваемых до майнера или тяжёлой локальной задачи без сетевой составляющей. Если трафик, наоборот, аномально вырос вместе с CPU — это скорее брутфорс, сканирование или эксфильтрация данных, и сетевой лог даст более быстрые зацепки, чем процессы.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Шаг второй: кто грузит CPU в момент всплеска

Дальше — прямой вопрос: какой процесс потребляет ресурсы. Если инцидент уже случился и вы читаете алерт постфактум, а процесс мог замаскироваться или исчезнуть, — сначала посмотрите исторические данные, если мониторинг их хранит с разбивкой по процессам (Netdata, Prometheus с node_exporter и process-exporter, Zabbix с элементами данных по процессам). Если такой детализации нет — это тоже вывод на будущее: голая метрика CPU без разбивки по процессам в момент инцидента бесполезна, разбивку стоит настроить заранее.

Если процесс всё ещё активен, смотрите топ по нагрузке напрямую:

ps aux --sort=-%cpu | head -n 20
top

Ищите три признака одновременно, а не по отдельности — по одному любой из них может оказаться ложной тревогой: непонятное или похожее на системное имя процесса (kworker, systemd-something, случайный набор символов), стабильно высокая загрузка без спадов (легитимные задачи почти всегда чем-то ограничены и колеблются, ровная полка у потолка — подозрительно) и пользователь, от которого процесс запущен — особенно если это www-data, nobody или учётка, которую вы не заводили.

Для конкретного PID проверьте, откуда он реально запущен:

ls -l /proc/PID/exe
cat /proc/PID/cmdline
ls -l /proc/PID/cwd

Путь в /tmp, /dev/shm, /var/tmp или скрытую папку в домашнем каталоге — почти всегда признак постороннего процесса: легитимный софт устанавливается через пакетный менеджер и запускается из системных директорий, а не из временных. Если ls -l /proc/PID/exe выдаёт (deleted) в конце пути — процесс запущен из файла, который потом удалили с диска, чтобы его нельзя было найти обычным поиском. Это отдельный тревожный признак сам по себе, даже если имя процесса выглядит безобидно.

Если top и ps показывают низкую нагрузку, а по внешним метрикам (со стороны гипервизора или облачной панели) она была высокой — вероятна маскировка под мониторинг, о которой шла речь выше. В этом случае снимайте данные средствами, которые зловред не ожидает: atop при включённом сохранении истории (если стоял заранее — покажет картину именно на момент инцидента, а не текущую), либо просто зафиксируйте время всплеска и вернитесь к нему позже, если нагрузка повторится.

Шаг третий: cron и systemd timers — чужое расписание

Ночная задача по расписанию — второй по частоте вариант после майнера, который жрёт CPU постоянно. Если нагрузка возникает не непрерывно, а именно в конкретный час — это почерк cron или systemd timer, свой или чужой.

Проверьте все источники расписаний, а не только один — задача может быть добавлена в любой из них:

crontab -l
crontab -l -u www-data
for u in $(cut -f1 -d: /etc/passwd); do crontab -l -u "$u" 2>/dev/null && echo "^ $u"; done
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/
systemctl list-timers --all

Цикл по всем пользователям из /etc/passwd важен отдельно: злоумышленник может поставить задачу в crontab не root, а любого другого пользователя системы, в том числе системной учётки, у которой обычно нет заданий вообще — и такую задачу легко пропустить, если проверять только crontab -l от своего имени и от root.

Для systemd timers смотрите не только список, но и что конкретно они запускают:

systemctl list-timers --all
systemctl cat имя.timer
systemctl cat имя.service

Обращайте внимание на timer'ы и unit-файлы с недавней датой изменения, особенно если она не совпадает с датой ваших последних деплоев или обновлений:

find /etc/systemd/system /lib/systemd/system -newer /etc/hostname -type f

Команда покажет unit-файлы, изменённые позже условной точки отсчёта (замените /etc/hostname на файл с известной вам датой, например последний плановый апдейт системы) — свежий unit, который вы не создавали, стоит разобрать построчно. То же самое касается файлов в /etc/cron.d/ — сравните список с тем, что действительно ставили ваши пакеты и деплой-скрипты.

Шаг четвёртый: процессы-потомки от неожиданных родителей

Даже если конкретный процесс уже не виден в top, у него остаётся след — кто его породил. Это особенно важно, если подозрительный процесс завершился сам к моменту вашей проверки: его родитель, скорее всего, всё ещё на месте и рано или поздно породит следующего потомка.

Постройте дерево процессов и смотрите, что от чего запущено:

pstree -p
ps -ef --forest

Ключевой вопрос: логично ли для этого родителя иметь такого потомка? Веб-сервер (nginx, apache) в норме порождает только свои воркеры и, возможно, PHP-FPM или проксируемое приложение — если у nginx в потомках висит bash, curl, wget, python или сетевой инструмент, это почти всегда след эксплуатации уязвимости в самом приложении: атакующий получил RCE через веб-приложение и запустил шелл или загрузчик прямо из-под его процесса.

То же самое касается PID 1 (systemd) или init-подобных процессов с потомками, которых там быть не должно, и сервисных аккаунтов (postgres, redis, mysql), у которых внезапно появился потомок вроде shell или сетевого клиента — субд не должна порождать интерактивные шеллы сама по себе.

Для конкретного PID можно посмотреть родителя напрямую:

cat /proc/PID/status | grep PPid
ps -o pid,ppid,user,cmd -p PID

Если родитель — уже неактивный или зомби-процесс, а сам факт запуска подозрительного потомка зафиксирован в аудит-логах (см. следующий шаг), это уже конкретная цепочка событий для расследования, а не догадка.

Шаг пятый: auth-логи за этот же промежуток времени

Если нагрузка — следствие постороннего доступа, где-то в логах аутентификации должен остаться вход или попытка входа. Точное время всплеска CPU из мониторинга — это якорь, вокруг которого стоит искать записи авторизации, а не просматривать логи целиком.

Для SSH и системной аутентификации:

journalctl -u ssh --since "2026-08-27 02:00" --until "2026-08-27 04:00"
grep "Accepted\|Failed" /var/log/auth.log
lastb | head -n 30
last -a | head -n 30

lastb показывает неудачные попытки входа — если там сотни строк за короткий промежуток перед всплеском нагрузки, это явный брутфорс, и вопрос смещается с «есть ли атака» на «был ли подобран пароль». last -a показывает успешные входы с указанием IP — сверьте их с вашим кругом администраторов: любой вход не с вашего обычного IP или в нетипичное время требует объяснения.

Если у вас настроен auditd, картина получается точнее — он логирует не только вход, но и запуск процессов, изменение файлов, повышение привилегий:

ausearch -ts today -k exec
ausearch -ua UID --start "08/27/2026 02:00:00"

Без предварительной настройки auditd такие запросы просто ничего не найдут — если это ваш случай, это тоже полезный вывод: возможность разобрать инцидент постфактум определяется тем, что было настроено заранее, а не в момент, когда алерт уже пришёл.

Обязательно проверьте и логи веб-приложения отдельно от access-лога веб-сервера, если приложение ведёт своё логирование аутентификации — панель администратора CMS, API-ключи, форма входа. Подбор пароля к панели администратора сайта не всегда попадает в auth.log системы, но обычно попадает в лог самого приложения.

Что делать по итогам: три типовых сценария

По совокупности предыдущих шагов картина обычно складывается в один из трёх сценариев.

СценарийПризнакиЧто делать
Легитимная фоновая задачаПроцесс узнаваемый, путь запуска штатный, нет чужих входов, cron/timer — ваш собственныйНичего критичного: перенести задачу на менее чувствительное время или ослабить алерт-порог для этого часа
Майнер / посторонний процессНагрузка ровная без спадов, странный путь в /tmp или /dev/shm, нет заметного всплеска сетевого трафикаИзолировать сервер от сети, снять образ диска для разбора, искать вектор входа, полная переустановка предпочтительнее «лечения»
Брутфорс / сканирование с вашего сервераАномальный исходящий сетевой трафик, много коротких соединений, чужой процесс в потомках сетевого сервисаЗаблокировать исходящие соединения зловреда, найти точку входа (уязвимое приложение, слабый пароль), сменить все учётные данные

Для второго и третьего сценария важно не ограничиваться убийством найденного процесса. kill -9 PID уберёт симптом на несколько минут, но если механизм повторного запуска (cron, systemd timer, initscript) остался на месте, процесс вернётся — иногда в буквальном смысле в течение той же минуты. Сначала находите и убираете точку персистентности, потом завершаете процесс, а не наоборот.

Если у вас нет уверенности, что вычистили всё до конца — а после реального взлома такой уверенности почти никогда не бывает полностью, — честнее и быстрее поднять сервер заново из чистого образа, перенести данные (с проверкой, что сами данные не заражены) и сменить все пароли, ключи и токены, чем бесконечно гоняться за скрытыми копиями зловреда по системе. Подробный разбор того, как ищут и вычищают майнер конкретно, — в статье как проверить сервер на майнер и вирусы, а разбор типичного пути заражения через cron с выводом наружу — в статье reverse shell в cron у пользователя, которого не заводили.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нагрузка выросла один раз и больше не повторяется — стоит ли беспокоиться?

Стоит, но без паники. Разовый всплеск может быть легитимной фоновой задачей, которая просто раньше не давала такой нагрузки (выросла база, увеличился объём бэкапа). Проверьте по шагам выше хотя бы поверхностно и настройте алерт с разбивкой по процессам, чтобы при повторе сразу видеть виновника, а не гадать заново.

Я убил подозрительный процесс, нагрузка упала — можно считать инцидент закрытым?

Нет, если не нашли и не убрали механизм его запуска. Проверьте cron, systemd timers, автозагрузку (systemctl list-unit-files --state=enabled), возможные SSH-ключи в ~/.ssh/authorized_keys, которые вы не добавляли, и только после этого считайте вопрос закрытым — а лучше пройдите по общему плану в статье если сервер взломали: пошаговый план.

Как отличить майнер от легитимной тяжёлой задачи вроде переиндексации базы?

По совокупности признаков, а не по одному. Легитимная задача обычно запускается из штатного пути (пакет, ваш деплой), от ожидаемого пользователя, логируется самим приложением и рано или поздно завершается. Майнер обычно живёт постоянно, стартует из нетипичной директории и не оставляет следов в логах вашего софта.

Стоит ли сразу обрывать сеть на сервере, если подозреваю взлом?

Если нагрузка сопровождается аномальным исходящим трафиком — да, изоляция сети остановит вред другим быстрее, чем kill процесса. Если трафика нет и нагрузка чисто локальная, можно сначала снять данные для разбора, не отключая сеть.

Как узнать, что именно грузило CPU, если алерт пришёл утром, а сейчас всё уже спокойно?

Без исторических данных по процессам — почти никак, разве что по косвенным следам в cron, systemd и auth-логах. Это главный аргумент в пользу того, чтобы настроить мониторинг с разбивкой по процессам заранее, а не после первого непонятного инцидента — подробнее в статье как узнать, кто нагружает сервер.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →