Кейс
Заказ был один — интерфейс к записям звонков. Нашли ещё четыре отказа
Заказчик попросил простой веб-интерфейс, чтобы слушать записи разговоров и смотреть детализацию. Пока разворачивали — обнаружили, что на станции четыре месяца не пишутся журналы, 10 ГБ диска заняты невидимым файлом, защита SSH от подбора паролей не срабатывала ни разу, а средства автоматизации вообще не могли зайти. Ни один из отказов не сообщал об ошибке.
Система сообщала о 27 ГБ занятого пространства, тогда как сумма файлов давала 17 ГБ. Разницу удерживал файл, удалённый четырьмя месяцами ранее: процесс не отпустил дескриптор, и место не освободилось.
Ни один из отказов не выдавал ошибки. Все отчитывались об успешном выполнении, поэтому и оставались незамеченными.
Общая черта: отсутствие сообщения об ошибке. Отказ, который отчитывается об успехе, живёт до первого разбора
Задача звучала просто: у заказчика есть телефонная станция, она пишет разговоры, и руководителю нужно уметь их послушать. Не выгружать файлы по SSH, не просить админа, а открыть в браузере, найти звонок по номеру и дате и нажать «play».
Работы на вечер. Но станция была на обслуживании давно, а вблизи её никто не разглядывал — и вечер получился длиннее.
Что получил заказчик
Веб-интерфейс к журналу звонков: детализация за всё время (110 тысяч звонков с 2023 года), поиск по номеру, направлению, статусу и длительности, прослушивание записи прямо в браузере с перемоткой, выгрузка в CSV.
Несколько решений, которые стоит назвать явно, потому что они не про удобство.
Доступ к базе — только на чтение. Интерфейс ходит в базу под отдельной учётной
записью с правом SELECT на одну таблицу. Не под той, которой станция пишет звонки.
Проверили прямо: запрос на удаление возвращает «отказано», обращение к другим базам —
тоже.
Кнопки удаления убраны. У готового интерфейса они есть: удалить запись разговора, удалить строку из журнала. Записи разговоров — это в том числе доказательная база в спорах с клиентами и подрядчиками. Возможность снести их из браузера в два клика не нужна никому.
Отключена «полезная» функция, которая отправляла номера на сторону. В интерфейсе по умолчанию включён поиск информации о номере через внешний сервис: клик по номеру — и он уходит на чужой сервер. Для телефонии заказчика это утечка, поэтому выключено.
Порт открыт только офису и нам. Не «наружу с паролем», а адресными правилами: из офисной сети и с нашего узла администрирования. Публичный интерфейс станции для интерфейса закрыт совсем.
Установка оформлена как код, а не как набор ручных шагов: на второй такой станции это один запуск.
Дальше начинается попутное
Перед установкой мы всегда смотрим, куда ставим: сколько места, что в журналах, чем занят процессор. Обычно это формальность на пять минут.
Диска нет, а файлов нет тоже
Свободно 2,5 ГБ из 30. Первая мысль — записи разговоров, их там почти 10 ГБ. Посчитали скорость роста: около двух недель до полной остановки. Стали проверять — и гипотеза рассыпалась: очистка старше ста дней работает по расписанию, объём давно стабилен.
А расхождение нашлось в другом месте: система сообщала, что занято 27 ГБ, тогда как сумма размеров всех файлов давала 17. Десять гигабайт занимал файл, которого в файловой системе уже не было — удалённый, но всё ещё открытый работающим процессом. Причина — опечатка в настройке ротации журналов, из-за которой станция четыре месяца писала «в никуда».
Подробный разбор с командами — в отдельной статье: Диск занят на 92%, а файлов — на 17 ГБ.
Журналов не было четыре месяца
Это следствие той же опечатки, и оно оказалось неприятнее нехватки места. Все текущие журналы станции были нулевого размера с апреля. То есть при любой жалобе «звонок не прошёл», «связь оборвалась», «не дозвонились» смотреть было некуда.
Вернули запись — и в первых же строках увидели непрерывный перебор паролей к телефонии из интернета. Подобранный пароль внутреннего номера означает звонки за счёт владельца станции, и суммы там измеряются не гигабайтами.
Оговорка, чтобы не преувеличивать: невидим перебор был для человека — открывать было нечего, файлы журналов пустые. Автоматическая блокировка по телефонии при этом за всё время работы закрыла около трёх тысяч адресов, и сколько из потока после апреля она успела обработать, по её счётчикам уже не установить.
Защита от подбора была включена и не работала
На станции стоит средство блокировки: заметил перебор — закрыл адрес. По телефонии оно работало и заблокировало почти три тысячи адресов. А по SSH — ноль блокировок за девять месяцев, при десятках тысяч попыток входа.
Три независимые причины, каждой достаточно: путь к журналу указан от другого дистрибутива (файла просто нет), шаблон распознавания рассчитан на старую версию сервера и не видит строки новой, а сами записи об отказах попадают в другой файл, чем предполагает стандартная настройка. Исправили все три; первая блокировка прилетела через три секунды.
И отдельно — то, что делают до включения, а не после: внесли в список исключений наш узел администрирования. Иначе штатная ситуация «сотрудник ошибся с правами доступа» пять раз подряд заблокировала бы единственный канал управления станцией. Такие вещи выясняют заранее, а не после того, как перестал открываться доступ.
Средства автоматизации не могли зайти
Обслуживание у нас идёт скриптами: раскатать настройку, собрать отчёт, проверить состояние. На эту станцию они не заходили — сертификат, которым скрипты предъявляют себя, сервер отклонял. Три дефекта, каждый в своём слое:
- Корневые сертификаты не попали в системное хранилище доверия. Раскладывались в подкаталог, который системная утилита на этой ОС не просматривает — она читает только файлы, лежащие непосредственно в каталоге. Хранилище при этом честно перестраивалось, просто без наших сертификатов.
- Проверка «жива ли учётная запись» отклоняла всех. Сервер запускает небольшую программу-проверку, а имя пользователя ей не передавалось — она получала пустой ввод и возвращала пустой ответ. Пустой ответ означает «подходящих учётных записей нет», то есть отклонялся любой вход по сертификату, не только наш.
- Уже написанное исправление не было доставлено. Оно лежало в коде, но на этот сервер не приезжало.
Почему установка при этом отчитывалась об успехе: каждый шаг проверял себя, а не результат. Файл скопирован — успех. Обработчик перестройки хранилища запущен — успех. Конфигурация синтаксически верна — успех. Ни один шаг не спрашивал «а сертификаты действительно оказались в хранилище?» и «а проверка действительно возвращает имя?». Разница между «шаг выполнен» и «получен нужный результат» — ровно та щель, в которую провалились все три дефекта.
Разобрали, исправили в коде и добавили проверки результата, а не только шага — на следующих станциях не повторится.
Почему это прожило так долго
Общая черта у всех четырёх находок одна, и она важнее любой из них по отдельности: ничего не падало с ошибкой. Ротация журналов отрабатывала и отчитывалась успехом. Диск заполнялся, и мониторинг занятости честно показывал проценты — только причина в них не видна. Средство блокировки было запущено и в статусе «работает». Установка настроек проходила без единого предупреждения.
Отказ, который сообщает о себе, находят быстро — на него есть алерт, письмо, красный индикатор. Отказ, который отчитывается об успехе, живёт до того дня, когда кто-нибудь посмотрит на систему вблизи и с вопросом «а это правда работает?».
Поэтому в обслуживании ценна не только реакция на заявки. Половина находок этого вечера не имела отношения к заказу — их принесла привычка смотреть по сторонам, пока делаешь что-то другое.
Что стоит проверить у себя
Даже без подрядчика эти четыре проверки занимают минут пятнадцать:
- Сравните «занято» с суммой размеров файлов. Расхождение — признак удалённого, но открытого файла. Занятое место мониторинг видит и покажет рост; чего он не покажет — так это причину: в обычной разбивке занятого места по файлам такого файла нет.
- Проверьте, куда сервис пишет журнал и появляются ли там новые записи. Не только размер файла: сервис может писать в системный журнал или в другой файл, и нулевой размер сам по себе ещё ни о чём не говорит. Смотреть надо, растёт ли то, что он действительно использует.
- Проверьте, сколько адресов заблокировала защита от подбора. Ноль при открытом в интернет доступе означает не тишину, а то, что защита не срабатывает.
- Убедитесь, что автоматизация действительно заходит. «Установка прошла успешно» и «настройка применилась» — разные утверждения.