Транспортная компания в Хамовниках, 27 рабочих мест, октябрь 2019-го. В бизнес-центре в четверг вечером обесточили этаж — работали электрики, предупредить забыли. Сервер выключился жёстко, вместе с кондиционером и половиной свитчей. Утром всё подняли, кроме почты: Zimbra не стартовала целиком, а в консоли висела ошибка проверки сертификата при подключении к каталогу. Логисты сидели без заявок. Разбираю, почему виноват оказался не LDAP и как я потратил полтора часа не туда.
LDAP Zimbra не стартует: error:14090086 и старый сертификат
Свет дали, почта не вернулась
Отключение питания — самая недооценённая авария для почтового сервера. Все готовятся к дискам, к взлому, к вирусу-шифровальщику. А ломается всё после банального «в здании меняли автоматы».
Механика простая и всегда одинаковая. Сервер годами не перезагружался. За эти годы в нём накопились изменения, которые ни разу не проверялись стартом: истёкшие сертификаты, снесённые вручную пакеты, правки в конфигурации, оставшиеся неприменёнными. Пока процессы живут, всё это спит. Перезагрузка — момент истины, и она случается не тогда, когда вы её планировали, а когда электрик выкрутил рубильник.
Если ваш сервер работает без перезагрузки больше года — вы не знаете, поднимется ли он. Это не пугалка, это арифметика: вы просто ни разу не проверяли. У логистов из Хамовников аптайм был 486 дней.
Что показала консоль в первые пять минут
Сервер загрузился, операционная система живая, диски на месте, сеть есть. Zimbra — нет.
su - zimbra
zmcontrol status
# Host mail.tk-logistic.ru
# ERROR: Unable to start TLS: SSL connect attempt failed
# error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
# when connecting to ldap master.
zmcontrol start
# Starting ldap...Done.
# Starting zmconfigd...Failed.
# ...
ps -u zimbra -o pid,etime,comm | grep slapd
# 2214 00:03:41 slapdВот эта деталь и определила весь дальнейший разбор: slapd живой. Процесс каталога поднялся и работает. Не поднимается всё остальное — потому что каждая служба Zimbra при старте идёт в каталог за своей конфигурацией, а соединение с ним обязано пройти через TLS. И вот проверка сертификата на этом соединении не проходит.
То есть формулировка «LDAP не стартует», с которой ко мне обратились, была неточной с самого начала. LDAP стартовал. К нему не могли подключиться.
Ложная версия: битая база после жёсткого выключения
Я пошёл по опыту, и опыт меня подвёл. Жёсткое обесточивание — классическая причина порчи базы каталога. Я такое видел: демон поднимается, а привязка с валидными учётными данными не проходит, в логе invalid credentials, и лечится это долго и неприятно. Симптом «не стартует после потери питания» лёг на эту версию идеально.
Полтора часа я потратил на её проверку: снял копию каталога данных, разметил план на восстановление, размонтировал том и прогнал проверку файловой системы под данными LDAP.
# копия до любых действий
systemctl stop zimbra 2>/dev/null; su - zimbra -c 'zmcontrol stop'
tar czf /backup/ldap-data-20191018.tgz /opt/zimbra/data/ldap
# проверка ФС под каталогом после аварийного выключения
umount /opt/zimbra/data 2>/dev/null || echo 'том занят, смотрим что держит'
fsck -n /dev/mapper/vg0-zimbradata
# clean, 205618/13107200 files, 2104883/52428800 blocksФайловая система чистая. Проверка целостности базы каталога тоже прошла. Версия не подтвердилась.
Задним числом видно, где я срезал угол: текст ошибки прямым текстом говорил про сертификат, а я читал его как «что-то не так с LDAP». В аварии так бывает — читаешь не то, что написано, а то, что ожидаешь прочитать. Копию каталога, впрочем, снял не зря: дальше я работал спокойнее, зная, что есть куда вернуться. И проверку файловой системы после жёсткого выключения я всё равно считаю обязательной, независимо от диагноза.
Настоящая причина: сертификат истёк двенадцать дней назад
Читаем ошибку буквально. certificate verify failed — не удалось проверить сертификат. Значит, смотрим сертификат и смотрим часы, потому что «просроченный» и «часы уехали вперёд» дают один и тот же результат.
# что за сертификат реально развёрнут (s_client -starttls ldap на здешнем
# OpenSSL 1.0.2 не поддерживается, поэтому читаем файл напрямую)
openssl x509 -in /opt/zimbra/ssl/zimbra/server/server.crt -noout -dates -subject -issuer
# notBefore=Jul 8 04:11:22 2019 GMT
# notAfter=Oct 6 04:11:22 2019 GMT
# subject=CN = mail.tk-logistic.ru
# issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
# и что на часах у сервера
date; timedatectl | grep -E 'NTP|synchronized'
# Fri Oct 18 09:42:11 MSK 2019Сертификат истёк 6 октября. Авария случилась 18-го. Двенадцать дней сервер прекрасно работал с просроченным сертификатом — и это, кстати, главное, что сбивает с толку владельца: «до выключения же всё было нормально». Соединения служб с каталогом были установлены давно и жили дальше; проверка сертификата происходит в момент установления нового соединения, а после перезагрузки все соединения новые.
Почему сертификат не продлился. У них стоял бесплатный сертификат на 90 дней, продление делал скрипт по расписанию. Скрипт получал новый сертификат исправно — файлы лежали свежие, от 4 октября. А вот шаг, который забирает эти файлы в хранилище Zimbra и перезапускает службы, был написан для предыдущей версии, тихо падал и никому об этом не сообщал. Классика: автоматизация работает наполовину, и эта половина невидима.
Как поднять почту прямо сейчас
Мне нужно было вернуть логистам почту, а не сделать красиво. Правильный путь — перевыпустить и разложить сертификат — занимает время, а половина сотрудников уже стояла у стола коммерческого директора. Поэтому первым шагом я снял требование TLS на соединении служб с каталогом.
su - zimbra
zmlocalconfig -e ldap_starttls_required=false
zmlocalconfig -e ldap_starttls_supported=0
zmlocalconfig -s ldap_starttls_required ldap_starttls_supported
zmcontrol start
zmcontrol status | head -15
# всё RunningПочта поднялась за четыре минуты. Очередь из 185 писем, накопившаяся с ночи, разошлась по ящикам за десять.
Теперь честно про цену этого решения, потому что в интернете этот рецепт лежит без единого предупреждения. Вы отключаете шифрование канала между службами Zimbra и каталогом. На однохостовой установке, где каталог слушает петлевой интерфейс, риск умеренный: трафик не покидает машину, а тот, кто уже получил доступ к машине, и так имеет всё. На многосерверной инсталляции — совсем другая история: пароли и содержимое каталога поедут между узлами открытым текстом по вашей сети.
Поэтому одновременно с этой правкой я всегда проверяю, кто вообще может достучаться до порта каталога:
ss -tlnp | grep ':389\|:636'
# LISTEN 0 128 127.0.0.1:389 users:(("slapd",pid=2214,fd=7))
iptables -S | grep -E '389|636'У логистов каталог слушал только петлевой интерфейс — это и позволило мне спокойно оставить временную конфигурацию до вечера. Если бы он торчал в сеть, я бы закрыл порт правилом на фаерволе прежде, чем снимать TLS.
Проверьте у себя за 2 минуты
Эта проверка отвечает на вопрос «поднимется ли мой сервер, если его сейчас выключить». Выполняйте на работающем сервере, ничего не ломая.
openssl x509 -in /opt/zimbra/ssl/zimbra/server/server.crt -noout -dates -subject
openssl x509 -in /etc/letsencrypt/live/ВАШ-ДОМЕН/cert.pem -noout -dates
su - zimbra -c '/opt/zimbra/bin/zmcertmgr viewdeployedcrt' | head -20
uptime -p
ss -tlnp | grep -E ':389|:636'
su - zimbra -c 'zmlocalconfig -s ldap_starttls_required ldap_starttls_supported'| Что увидели | Трактовка |
|---|---|
| notAfter уже прошёл, а сервер работает | Вы живёте на одолженном времени. Ближайшая перезагрузка — по питанию, по обновлению ядра, по чему угодно — уронит Zimbra целиком |
| До notAfter меньше 20 дней | Проверьте, чем именно продлевается сертификат и доходит ли результат до хранилища Zimbra. Свежий файл на диске ещё не значит, что он развёрнут |
| Аптайм больше 300 дней | Стартовая последовательность ни разу не проверялась. Плановая перезагрузка в согласованное окно дешевле, чем внеплановая в четверг вечером |
| Порт 389 слушает не только 127.0.0.1 | Каталог доступен по сети. Временное снятие TLS для вас — не безобидная мера, сначала закройте порт |
| ldap_starttls_required уже false | Кто-то до вас чинил эту аварию и не вернул как было. Проверьте дату правки и верните TLS |
| Даты в развёрнутом server.crt и в свежем файле от Let's Encrypt разные | Продлилось одно, работает другое. Ровно та ситуация, из-за которой сервер не встал у моего клиента |
Последняя строка — самая коварная. Именно она объясняет, почему администратор искренне уверен, что сертификат продлевается, а сервер считает иначе.
Как вернуть всё как надо: цепочка и деплой
Вечером того же дня, после окончания рабочего дня, я привёл сертификаты в порядок и вернул TLS. Порядок действий такой.
# 1. свежий сертификат и полная цепочка в один файл
cat /etc/letsencrypt/live/mail.tk-logistic.ru/chain.pem > /tmp/chain.crt
# корневой сертификат УЦ добавляем в конец цепочки
cat /opt/zimbra/ssl/letsencrypt/root.pem >> /tmp/chain.crt
cp /etc/letsencrypt/live/mail.tk-logistic.ru/cert.pem /tmp/server.crt
cp /etc/letsencrypt/live/mail.tk-logistic.ru/privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key
chown zimbra:zimbra /tmp/server.crt /tmp/chain.crt /opt/zimbra/ssl/zimbra/commercial/commercial.key
# 2. проверка ДО деплоя — если тут ошибка, дальше идти нельзя.
# zmcertmgr из-под root не работает: "no longer runs as root!"
su - zimbra -c '/opt/zimbra/bin/zmcertmgr verifycrt comm /opt/zimbra/ssl/zimbra/commercial/commercial.key /tmp/server.crt /tmp/chain.crt'
# 3. деплой и рестарт
su - zimbra -c '/opt/zimbra/bin/zmcertmgr deploycrt comm /tmp/server.crt /tmp/chain.crt'
su - zimbra -c 'zmcontrol restart'
# 4. возвращаем TLS на соединение с каталогом
su - zimbra -c 'zmlocalconfig -e ldap_starttls_required=true'
su - zimbra -c 'zmlocalconfig -e ldap_starttls_supported=1'
su - zimbra -c 'zmcontrol restart'Место, где спотыкаются чаще всего, — цепочка. Проверка обязана видеть путь от корневого сертификата удостоверяющего центра через промежуточные к вашему серверному. Если промежуточный устарел или его вообще нет в файле, verifycrt ругнётся, и это не формальность: развёрнутый без полной цепочки сертификат даёт ровно ту же ошибку проверки, с которой всё началось. Я видел, как люди кладут сертификат без цепочки, получают тот же certificate verify failed и делают вывод «значит, дело не в сертификате».
После возврата TLS обязательно проверьте, что сервер переживёт перезагрузку. Не на словах — перезагрузкой. Мы сделали это в 22:10 той же пятницы: полный ребут, сервер поднялся сам за 3 минуты 20 секунд.
Крайние меры и чего они стоят
Два инструмента, которые в форумных советах предлагают вторым сообщением, а применять их надо последними.
Восстановление прав. После аварийного выключения или после того, как кто-то запускал команды Zimbra от root, владельцы файлов разъезжаются, и часть служб не может прочитать собственные ключи. Чинится штатно, от root:
/opt/zimbra/libexec/zmfixperms
# и только после этого
su - zimbra -c 'zmcontrol restart'Инструмент безопасный, но не бесплатный по времени: на дереве с большим store он идёт долго, у меня на 140 ГБ отработал 6 минут. И он не чинит сертификаты — он чинит права. Не путайте.
Пересоздание корневого сертификата. Команда /opt/zimbra/bin/zmcertmgr createca -new создаёт новый внутренний удостоверяющий центр. Она действительно решает ситуацию, когда самоподписанная инфраструктура развалилась полностью. Но последствия надо понимать заранее: на многосерверной инсталляции после этого придётся заново разложить сертификаты по всем узлам, иначе узлы перестанут доверять друг другу и вы получите аварию шире исходной. Один раз я видел, как эту команду выполнили на двухнодовой почте в качестве первого шага — вместо одной сломанной ноды получили две.
Правило, которое я вывел: сначала читаем текст ошибки буквально, потом смотрим часы и сертификат, потом права, и только затем трогаем удостоверяющий центр. Обратный порядок превращает часовую работу в суточную.
Цифры и что из этого следует
Итог того дня. Этаж запитали в 07:30, почта заработала в 14:10 — простой 6 часов 40 минут, из них полтора часа я потратил на неверную версию. Ящиков 31, store 140 ГБ, в очереди на момент восстановления лежало 185 писем, все доехали. Мои работы — 7 часов, счёт 31 000 ₽ вместе с вечерним визитом и приведением сертификатов в порядок.
Что стоил простой клиенту. Транспортная компания принимает заявки на перевозку почтой — в тот день их было бы около 40, средняя маржа с заявки 4 800 ₽. Из-за паузы четыре клиента ушли к конкурентам с формулировкой «вы не отвечаете», это примерно 19 000 ₽ упущенной маржи плюс два постоянных заказчика, которые в следующем месяце дали меньше объёма. Диспетчеры полдня работали по телефону и в мессенджерах, часть заявок потом пришлось переносить в систему руками — ещё 5 человеко-часов.
Три вывода, которые я бы забрал на месте владельца.
Аптайм в 486 дней — это не достижение. Это отложенная проверка стартовой последовательности. Плановая перезагрузка раз в квартал, в согласованное окно, с человеком у консоли, — дешёвая страховка.
Автоматическое продление сертификата надо проверять по результату, а не по факту запуска. Файл на диске обновился — это половина дела. Вопрос в том, доехал ли он до хранилища Zimbra. Сравнение дат в свежем файле от удостоверяющего центра и в развёрнутом server.crt занимает десять секунд и ловит эту ошибку целиком.
Быстрое лечение и правильное лечение — разные работы. Снять TLS и поднять почту можно за пять минут. Оставить так навсегда — значит поменять аварию на тихий риск, о котором через год никто не вспомнит. Разделяйте эти два шага явно, записывайте временную правку туда, где её точно увидят.
Хотите понять, переживёт ли ваш сервер ближайшее отключение света, — пришлите мне вывод команд из блока самопроверки: даты сертификата из server.crt и из файла удостоверяющего центра, аптайм и что слушает порт 389. За день отвечу, что сломается при перезагрузке и в каком порядке это чинить, чтобы не в четверг вечером.
Частые вопросы
Сервер работал с просроченным сертификатом. Почему сломалось только после перезагрузки?
Потому что проверка сертификата происходит в момент установления соединения, а не постоянно. Службы Zimbra подключились к каталогу когда-то давно и держали эти соединения. Пока процессы живы, никто ничего заново не проверяет. Перезагрузка обнуляет всё: соединения новые, проверка новая, и просроченный сертификат немедленно даёт certificate verify failed. У логистов сертификат истёк 6 октября, а сервер лёг 18-го — двенадцать дней разрыва. Отсюда и убеждение владельца, что до аварии всё было в порядке.
Можно оставить ldap_starttls_required=false навсегда, раз всё работает?
Технически можно, и именно так делают многие после аварии — потому что почта поднялась и все выдохнули. Оценивайте по одному признаку: слушает ли каталог только петлевой интерфейс. Если да и установка однохостовая, трафик не покидает машину, и риск умеренный. Если у вас несколько узлов, содержимое каталога и учётные данные пойдут между ними по сети открытым текстом — так оставлять нельзя. Проверить: ss -tlnp | grep ':389'. И в любом случае запишите временную правку туда, где её найдут: через год никто не вспомнит, почему TLS выключен.
Как понять, что дело в сертификате, а не в повреждении базы каталога?
По двум признакам. Первый: жив ли процесс slapd. Если он поднялся и работает, каталог как таковой в порядке, проблема на подключении к нему. Второй: текст ошибки. certificate verify failed — это про сертификат, а повреждение базы даёт другие сообщения, чаще про невалидные учётные данные при привязке. Я в первый час читал ошибку не буквально и полтора часа проверял файловую систему и целостность базы. Проверка после жёсткого выключения нужна в любом случае, но как отдельная гигиеническая процедура, а не как основная версия.
Мы обновляем сертификат скриптом. Как убедиться, что он реально работает?
Сравните две даты: notAfter в свежем файле от удостоверяющего центра (openssl x509 -in .../cert.pem -noout -dates) и notAfter в развёрнутом /opt/zimbra/ssl/zimbra/server/server.crt. Если даты расходятся — скрипт получает новый сертификат, но не доносит его до хранилища Zimbra. Это была ровно ситуация клиента: файлы на диске свежие, от 4 октября, а развёрнут был старый. Шаг деплоя падал молча, потому что писался под предыдущую версию. Добавьте в скрипт проверку кода возврата и уведомление на почту или в мессенджер — иначе про поломку вы узнаете при перезагрузке.
Стоит ли сразу выполнить zmcertmgr createca -new, если ничего не помогает?
Это последний шаг, а не первый. Команда пересоздаёт внутренний удостоверяющий центр, и на многосерверной установке после неё придётся заново разложить сертификаты по всем узлам — иначе узлы перестанут доверять друг другу. Я видел случай, когда её выполнили в самом начале на двухнодовой почте и вместо одной сломанной ноды получили две. Порядок такой: буквально прочитать текст ошибки, проверить системное время, проверить даты сертификата и полноту цепочки, восстановить права через zmfixperms, и только если ничего из этого не объясняет картину — думать про пересоздание центра сертификации.
Оставить комментарий