Вопрос обычно возникает не на ровном месте. Сервер стал медленнее, хостер прислал письмо про исходящий трафик, или в почте нашлось уведомление о входе, которого вы не делали. Дальше начинается самое неприятное: непонятно, что смотреть и в каком порядке, а первое желание — снести и поставить заново — почти всегда преждевременно.

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

Шаг первый: кто входил

Начинайте со входа. Если чужой попал внутрь, он почти наверняка попал через SSH, и след остался.

last -20
lastb | head -20
who

last покажет последние успешные входы, lastb — неудачные, who — кто сидит прямо сейчас. Смотреть надо не на количество, а на форму. Тысячи неудачных попыток с адресов, которые больше не возвращаются, — это обычный фоновый перебор, он идёт на любом публичном адресе непрерывно и ничего не значит.

Тревожно другое:

  • успешный вход с адреса, где никого из ваших нет;
  • вход под именем пользователя, которого вы не заводили;
  • неудачные попытки под именем, которое на этой машине действительно есть — значит, кто-то узнал состав пользователей, а не бьёт по словарю;
  • сессия, открытая сейчас, которую вы не открывали.

Отдельно проверьте, не появилось ли чужих ключей. Файл ~/.ssh/authorized_keys — самый частый способ закрепиться: пароль потом можно сменить сколько угодно раз, ключ останется.

cat ~/.ssh/authorized_keys
sudo cat /root/.ssh/authorized_keys

Каждая строка — это чей-то доступ. Если вы не можете сказать, чей именно, считайте, что чужой.

Шаг второй: что изменилось в системе

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

На Debian и Ubuntu эталон уже есть: каждый пакет знает контрольные суммы своих файлов.

sudo apt install debsums
sudo debsums -c

Команда выведет файлы, которые отличаются от того, что положил дистрибутив. Часть находок будет законной — конфигурационные файлы под /etc для того и существуют, чтобы их править. А вот изменённый исполняемый файл в /usr/bin, /usr/sbin или /bin на сервере, который вы не трогали руками, — это уже разговор.

Второй источник — свежие файлы там, где их быть не должно. Веб-шелл обычно лежит в каталоге загрузок и выглядит как безобидный .php:

find /var/www -type f -name '*.php' -mtime -14 -ls

Четырнадцать дней — просто отправная точка; подставьте срок, в течение которого вы точно ничего не выкладывали.

Шаг третий: что уходит наружу

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

ss -tulpn
ss -tp state established

Первая команда покажет, что слушает входящие, вторая — что установлено сейчас. Читать надо колонку с процессом. Вопросы вызывают: незнакомый процесс, слушающий на 0.0.0.0; исходящие соединения на высокие порты к адресам, с которыми вашему приложению нечего делать; и особенно процесс, запущенный из /tmp или /dev/shm — из этих каталогов ничего легального не запускается.

Заодно посмотрите на нагрузку. Майнер выдаёт себя тем, что процессор занят постоянно, а сайт при этом никакой популярностью не пользуется.

Если признаки нашлись

Первое побуждение — быстро всё почистить: удалить чужой ключ, убить процесс, стереть файл. Так делать не надо, потому что вы уничтожите то, по чему потом можно было бы понять, как он вошёл. А если не понять — он войдёт снова, и уже завтра.

Порядок, который бережёт и данные, и картину:

  1. Сделать снимок диска у хостера, если такая возможность есть. Это единственный шаг, который потом нельзя повторить.
  2. Отрезать машину от сети или закрыть всё, кроме своего IP, — но не выключать. При выключении вы потеряете список процессов и открытые соединения, а это половина улик.
  3. Сохранить наружу логи: /var/log/auth.log, логи веб-сервера, вывод трёх команд выше.
  4. Только теперь разбираться, как вошли.

Переустановка с нуля — правильный финал, если доступ был получен с правами root. Никакая чистка не даёт гарантии, что не осталось закладки. Но переустанавливать, не поняв причину, бессмысленно: вы вернёте ту же дыру на свежую систему.

Как сделать, чтобы вопрос не возникал внезапно

Всё перечисленное — это разовая проверка вручную, и она отвечает на вопрос «что происходит прямо сейчас». Беда в том, что задают его обычно поздно: когда уже написал хостер или упал сайт.

Каждая из этих проверок существует как отдельный инструмент, который умеет следить постоянно: неудачные входы — fail2ban, изменения файлов — AIDE, целостность пакетов — debsums, открытые порты — регулярный снимок ss. Поставить их по отдельности несложно; сложнее приучиться каждый день заходить и читать шесть разных выводов, поэтому на практике их не читают.

Смысл собранной панели ровно в этом: те же самые данные, но на одной странице и с историей, чтобы «стало не так, как вчера» было видно без специального похода за этим. Ниже — страницы демо, где показано, как это выглядит в собранном виде.