MAATRIX / Блог / Как найти сервисы, которые никто не запускал уже год, и выключить их

Как найти сервисы, которые никто не запускал уже год, и выключить их

MAATRIX

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

Почему это не «просто лишний процесс»

Забытый сервис — это не только чуть более высокая нагрузка на CPU и память, хотя на серверах с ограниченными ресурсами и это уже повод. Главная проблема в другом: он открыт для атаки, но его никто не патчит и не проверяет. Никто не подписан на security-advisory для библиотеки, которую он тянет, никто не следит за версией, никто не заметит, что в логине по умолчанию всё ещё стоит пароль из документации. Такой сервис — идеальная точка входа: он висит на порту месяцами, отвечает на запросы, но выпадает из всех процессов патч-менеджмента, потому что формально «его как бы нет» — просто никто не включил его в список того, за чем нужно следить. Именно так чаще всего и выглядят реальные истории взлома: не сложная атака на актуальный сервис, а вход через порт, о котором забыли.

Вторая проблема — операционная. Забытый сервис путает картину при инцидентах: вы разбираете аномальную нагрузку и тратите время на то, чтобы понять, что это старый мониторинг ходит куда-то раз в минуту, а не что-то новое и опасное. Чем больше процессов, о смысле которых приходится гадать, тем медленнее реакция на реальный инцидент.

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

Первый круг: что вообще запущено

Начинать нужно не с гипотез, а с полного списка. На системах с systemd (а это подавляющее большинство современных Linux-серверов) это делается так:

# всё, что сейчас загружено и активно
systemctl list-units --type=service --state=running

# вообще все unit-файлы сервисов, включая выключенные
systemctl list-unit-files --type=service

# то же самое для таймеров — частый источник забытых задач
systemctl list-timers --all

Сразу сверьте этот список с тем, что вы ожидаете увидеть. На типичном сервере после года эксплуатации в списке running обычно оказывается на 15-30% больше сервисов, чем можно назвать с ходу — это не точная цифра, а ориентир, у вас может быть меньше или больше, но сам факт расхождения почти гарантирован.

Для каждого неочевидного сервиса сразу смотрите, когда он был запущен и с какими параметрами:

systemctl status имя-сервиса
systemctl show имя-сервиса -p FragmentPath,ExecStart,ActiveEnterTimestamp

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

Отдельно проверьте cron и at — не всё живёт в systemd:

crontab -l -u каждый_пользователь
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/
atq

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

Отдельно стоит проверить и то, что вообще не показывается в стандартных списках — замаскированные под системные имена процессы, майнеры и прочее, что специально прячется от беглого взгляда. Об этом отдельно — в разборе как искать скрытые процессы на сервере.

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

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

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

Второй круг: кто слушает порты и на них реально приходят соединения

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

# кто слушает TCP/UDP порты и какой процесс за это отвечает
ss -tulnp

# то же, но с активными соединениями, не только LISTEN
ss -tunp state established

Здесь важен второй шаг — не просто «кто слушает», а «кто реально этим пользуется». Наличие LISTEN ничего не говорит о трафике: сервис может слушать порт третий год и ни разу не получить соединение. Проверить это можно двумя способами.

Быстрый — снять счётчик пакетов на конкретный порт через tcpdump на короткое окно:

sudo tcpdump -i any port 8081 -c 20 -w /tmp/check_8081.pcap &
# подождать характерный цикл нагрузки — сутки или неделю, смотря что за сервис

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

Более системный способ — завести временное правило подсчёта в firewall без блокировки трафика, просто с логированием и счётчиком:

# nftables: отдельная цепочка-наблюдатель, ничего не дропает
sudo nft add rule inet filter input tcp dport 8081 counter
sudo nft list ruleset | grep -A2 'dport 8081'

Через 2-4 недели смотрите значение счётчика. Ноль — кандидат в очередь на отключение. Нюанс: некоторые сервисы вызываются редко и предсказуемо — раз в квартал для отчётности, раз в год для продления сертификата, — так что прежде чем судить по короткому окну, спросите себя и команду, не из таких ли это случаев.

Порты без исходящего трафика проверяются иначе — через ss с фильтром по PID и разбор /proc/<pid>/fd, но на практике для сервера с несколькими сервисами хватает того же tcpdump, направленного на исходящие соединения конкретного процесса. Если вы ещё не делали базовую сверку — какие порты вообще открыты и зачем — начните с неё, это отдельная и более широкая задача, чем поиск забытых сервисов: как проверить и закрыть открытые порты на сервере.

Третий круг: тишина в логах за долгий период

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

Если сервис живёт под systemd, journald хранит его историю:

# последняя запись в журнале конкретного сервиса
journalctl -u имя-сервиса -n 1 --no-pager

# сколько строк вообще было за последние 90 дней
journalctl -u имя-сервиса --since "90 days ago" | wc -l

Тут есть грабля: по умолчанию journald может хранить журнал не бесконечно — глубина зависит от SystemMaxUse и ротации в /etc/systemd/journald.conf. Если сервис не писал в лог полгода, а глубина хранения journald — три месяца, вы увидите пустой результат и ошибочно решите, что сервис вообще не логирует. Перед выводами проверьте реальную глубину:

journalctl --disk-usage
cat /etc/systemd/journald.conf | grep -i maxuse

Для сервисов со своими файлами логов (nginx, приложения на своём стеке) смотрите время модификации файла — это грубо, но быстро:

find /var/log -name "*.log" -mtime +90 -exec ls -la {} \;

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

«Никто не может объяснить, зачем это» — отдельная категория риска

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

Практический способ довести это до решения:

  • Заведите список всех процессов и сервисов, для которых при инвентаризации не нашлось однозначного владельца или назначения.
  • По каждому — минимальное расследование: ExecStart и рабочий каталог сервиса, содержимое конфига, дата последнего изменения бинарника или кода (stat на файл).
  • Проверьте, не ссылается ли на него что-то ещё в системе — nginx upstream, запись в cron, systemd-зависимость (systemctl list-dependencies --reverse имя-сервиса), переменная окружения в другом сервисе.
  • Если после этого расследования назначение всё ещё не понятно и явного владельца в команде нет — это кандидат на отключение с тем же протоколом, что и «мёртвые» по логам и трафику сервисы, только с более длинным окном наблюдения перед финальным решением: не 2-4 недели, а 1-2 месяца, потому что риск ошибиться выше.

Важно не путать «непонятно, зачем» с «непонятно мне лично». Прежде чем считать сервис бесхозным, стоит явно спросить у команды, а не полагаться на то, что вы просто не в курсе. Один короткий вопрос экономит часы разбора инцидента после ошибочного отключения.

Безопасное отключение: сначала stop, не rm

Главное правило всего процесса — необратимые действия идут последними и только после периода наблюдения. Порядок такой:

  1. Stop, не disable и не удаление. Остановите сервис, но оставьте автозапуск как есть — это даёт возможность откатиться одной командой, если что-то вдруг сломается сразу.
sudo systemctl stop имя-сервиса
  1. Период наблюдения. От нескольких дней до месяца в зависимости от того, насколько редко сервис мог использоваться. Смотрите не только на сам сервис — проверьте, не посыпались ли ошибки в других частях системы, которые могли на него неявно опираться (это особенно важно для внутренних API и очередей).
  1. Disable, если наблюдение прошло чисто. Теперь можно убрать автозапуск:
sudo systemctl disable имя-сервиса
  1. Mask — если есть риск, что что-то попытается его перезапустить. Некоторые сервисы имеют зависимости Wants= или Requires= от других unit-ов, которые могут поднять их повторно даже после disable. mask жёстко блокирует запуск:
sudo systemctl mask имя-сервиса

Откатить mask так же просто — systemctl unmask имя-сервиса, дальше enable --now при необходимости.

  1. Архивирование и удаление файлов — отдельный, самый поздний шаг. Только после того, как сервис промаскирован и прошёл ещё один, более длинный период спокойствия (речь о месяцах, а не днях), можно архивировать конфиги и данные сервиса в отдельное хранилище и только потом удалять пакет:
sudo tar czf /srv/archive/decommissioned/имя-сервиса-$(date +%F).tar.gz /etc/имя-сервиса /var/lib/имя-сервиса
sudo apt remove имя-сервиса   # или yum/dnf remove — смотря по дистрибутиву

Не выполняйте remove и purge в один заход с первой остановкой сервиса — это самая частая ошибка. Удалённый пакет и стёртые данные — это уже не «включить обратно одной командой», а восстановление из бэкапа, если он вообще есть. Тот же принцип поэтапности касается и firewall: если сервис слушал порт, который был открыт наружу, не закрывайте его синхронно с остановкой сервиса — сначала убедитесь, что молчание порта никого не беспокоит, и только потом убирайте разрешающее правило.

Документация — без неё вся процедура теряет смысл

Весь смысл аккуратного отключения теряется, если через полгода кто-то (включая вас самих) увидит остановленный сервис и не поймёт, специально он выключен или упал. Минимальный набор документации:

  • Файл или запись в системе тикетов с датой, именем сервиса, причиной отключения (что именно проверяли — логи, трафик, опрос команды) и именем того, кто принял решение.
  • Комментарий в самом unit-файле или рядом с ним — не все будут смотреть в тикет-систему, когда наткнутся на процесс при следующем разборе инцидента:
# /etc/systemd/system/имя-сервиса.service.d/decommission.conf
# Остановлен 2026-08-14, причина: нет трафика 60+ дней, нет владельца в команде.
# Архив конфигов: /srv/archive/decommissioned/имя-сервиса-2026-08-14.tar.gz
# Ответственный: см. тикет OPS-482
[Unit]

(Файл создаётся просто как заметка рядом с юнитом — systemd его не потребует и не изменит поведение сервиса, drop-in без директив ни на что не влияет.)

  • Единый список отключённых сервисов на сервере — таблица или файл, куда попадает каждый такой случай, чтобы через полгода не пересобирать историю по обрывкам тикетов.
Что зафиксироватьЗачем
Дата остановки и дата маскировкиПонимать, сколько времени прошло и когда можно двигаться к удалению
На основании чего решили (лог/трафик/опрос)Чтобы не пересобирать доказательную базу заново при вопросах
Где лежит архив конфигов и данныхБыстрый откат без восстановления из полного бэкапа сервера
Кто принял решениеЕсть к кому обратиться с уточняющим вопросом

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

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

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

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

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

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

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

Сколько ждать перед окончательным disable, если сервис явно не используется?

Общего числа нет — ориентируйтесь на цикл нагрузки. Для веб-сервисов и API обычно достаточно 2-4 недель наблюдения после stop. Для сервисов с сезонной или редкой нагрузкой (годовая отчётность, продление лицензий) разумнее подождать хотя бы один полный цикл, то есть иногда до года — здесь mask с чёткой пометкой в документации безопаснее, чем спешка.

А что если сервис после stop сразу перезапустился сам?

Значит, у него Restart=always в связке с тем, что его кто-то или что-то дёргает извне — другой unit через зависимость, watchdog-скрипт в cron, внешний оркестратор. Проверьте systemctl list-dependencies --reverse и поищите упоминания имени сервиса в cron и других unit-файлах, прежде чем повторять stop.

Можно ли автоматизировать весь процесс поиска кандидатов?

Частично — да, скрипт, который раз в месяц собирает список running-сервисов, сверяет с prev-снимком и подсвечивает новые или без активности в логах за N дней, экономит время. Но финальное решение «отключать или нет» всё равно требует человека — особенно шаг с опросом команды про назначение сервиса автоматизировать нельзя.

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

Это отдельный, более тяжёлый случай — не отключение, а восстановление знаний: снимайте strace/ss профиль его реальной работы, ищите исходники или образ, из которого он был собран, прежде чем вообще думать про отключение. Такие сервисы обычно перемещают в отдельную зону повышенного внимания, а не сразу в очередь на выключение.

Стоит ли сразу закрывать порт в firewall, если сервис остановлен?

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

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

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

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