SOGo не пускает после переноса mailcow: разбор MD5
АйТи Фреш
Linux, Docker и DevOps

После переноса mailcow IMAP пускает по паролю, а SOGo — нет: разбираем MD5-хеши и SQL-вид пользователей

Автор: , директор ООО «АйТи-Фреш» · · ~14 мин чтения
Иллюстрация: один и тот же пароль mailcow открывает почтовый протокол, но не подходит к веб-почте SOGo из-за старого MD5-хеша
Один пароль, два разных способа проверки — Dovecot и SOGo читают унаследованный MD5-хеш по-разному

После переноса или восстановления mailcow иногда возникает странная асимметрия: почтовый клиент по IMAP и SMTP принимает пароль сотрудника без единой ошибки, а веб-почта SOGo этого же человека не пускает вовсе. Разбираю, почему в этом чаще всего виноваты старые MD5-хеши паролей, доставшиеся при переносе, как увидеть проблему в базе одним SQL-запросом и как починить это без сброса паролей всем сотрудникам разом.

Симптом: часть сотрудников входит по почте, но не в веб-почту

Хакерспейс «Мастерская изобретателя» (23 рабочих места) перенёс корпоративную почту на новый сервер mailcow из резервной копии старого. Сразу после восстановления администратор проверил базовую работоспособность: почтовые клиенты подключались по IMAP, письма отправлялись по SMTP — всё выглядело так, будто перенос прошёл идеально. Проблему обнаружили не сразу, а когда часть сотрудников пожаловалась, что не может войти в веб-почту SOGo через браузер — при том же самом пароле, который спокойно принимали и Outlook, и телефон.

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

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

Как mailcow хранит пароли и при чём тут MD5

mailcow хранит пароли пользователей в виде хешей в базе MySQL/MariaDB, и алгоритм хеширования для новых и изменённых паролей задаётся переменной MAILCOW_PASS_SCHEME в mailcow.conf. Для новых паролей по умолчанию используется BLF-CRYPT (Blowfish) — он считается основной полностью поддерживаемой схемой и для чтения, и для записи; наравне с ним полностью поддерживаются SSHA, SSHA256 и SSHA512. Но документация mailcow отдельно перечисляет ещё около двух десятков схем, которые сервер умеет читать (то есть проверять по ним пароль при входе), даже если сам он больше не создаёт хеши в этом формате, — и среди них MD5 и LDAP-MD5.

Это и есть источник проблемы после переноса: если старый сервер (или ещё более ранняя система до него) хранил пароли в виде MD5-хешей, они переносятся в новую базу mailcow как есть — mailcow не переписывает существующие хеши автоматически просто потому, что заработал новый сервер. Формат MD5 в списке читаемых, значит, стандартная авторизация Dovecot (IMAP и POP3 он проверяет сам, а Postfix при SMTP-аутентификации отдаёт проверку ему же) успешно проверяет пароль сотрудника по такому хешу и пускает его — с точки зрения почтового протокола всё корректно.

Важно различать два похожих, но разных сценария переноса: перенос через официальный backup_and_restore.sh (штатный инструмент бэкапа и восстановления mailcow) и ручной перенос данных из старой почтовой системы другого типа (не mailcow) при миграции на новый сервер. В первом случае, как в issue #5586, хеши переносятся как есть из базы в базу, потому что backup_and_restore.sh не занимается их конвертацией. Во втором случае формат хеша зависит от того, какой инструмент использовался для переноса самих учётных данных — imapsync переносит письма, а не пароли, и пароли на новом сервере обычно приходится создавать заново, что как раз исключает проблему MD5 сразу для всех, кто прошёл через такую миграцию с нуля.

Схема: один и тот же хеш пароля по-разному обрабатывается Dovecot/Postfix и представлением _sogo_static_view для SOGo
IMAP и SMTP спокойно читают унаследованный MD5-хеш, а вход в SOGo через него — источник избирательных отказов

Почему SOGo видит тот же хеш иначе, чем Dovecot

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

В зафиксированном на GitHub случае (issue #5586, декабрь 2023 года, перенос через backup_and_restore.sh на mailcow 2023-11) администратор столкнулся ровно с этой асимметрией: SMTP и IMAP работали у всех после восстановления, а пользователи с хешем вида {MD5}ZVN1…== (MD5 в base64) не могли войти в SOGo, тогда как пользователи с {BLF-CRYPT} проходили без проблем. Смена путей установки и томов на стандартные /opt и /var/lib как причина не подтвердилась. В параллельной переписке в рассылке SOGo автор уточнил, что вместе с переездом SOGo обновился примерно с 5.8.0 до 5.9.0, — то есть сломалось не хранение хешей, а то, как новая сборка SOGo их проверяет. Issue закрыли со ссылкой на обсуждение в рассылке SOGo, без правки в mailcow.

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

Как продиагностировать: SQL-запрос и лог password policy

Первый шаг диагностики — посмотреть, как именно хранится пароль проблемного пользователя, прямо в представлении, которое использует SOGo. Подключаюсь к MariaDB внутри контейнера mysql-mailcow штатным способом из документации mailcow — с учётными данными из mailcow.conf — и выполняю запрос:

cd /opt/mailcow-dockerized && source mailcow.conf
docker compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME} \
  -e "SELECT c_uid, c_password FROM _sogo_static_view WHERE c_password LIKE '{MD5}%' OR c_password LIKE '{LDAP-MD5}%';"

Если в результате есть строки с префиксом {MD5} или {LDAP-MD5} — это список кандидатов, и обычно он совпадает со списком жалующихся. Второй сигнал — строка в логе SOGo в момент неудачного входа: SOGoRootPage Login from '…' for user '…' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0. Важно не прочитать её неправильно: это стандартная запись SOGo о неудавшемся входе, «password policy: 65535» здесь не означает, что сработала какая-то политика паролей, — это просто код «вход не состоялся». Сама по себе строка причину не называет; ценна она в связке с SQL-выборкой: если пользователь с {MD5} в той же минуте успешно проходит по IMAP, а в логе SOGo у него такая запись, диагноз почти однозначен. Если хотите видеть в логе и сам SQL-запрос SOGo к _sogo_static_view, как в issue, — временно включите отладку SQL в data/conf/sogo/sogo.conf и не забудьте выключить её после разбора.

Пятишаговый процесс диагностики и исправления входа в SOGo при старом MD5-хеше пароля
От SQL-запроса до восстановленного доступа — пять шагов без сброса пароля всем сотрудникам

Как починить: пересохранить пароль и обновить представление SOGo

Самое надёжное и самое простое решение — попросить сотрудника (или администратора от его имени) задать пароль заново через интерфейс mailcow: Mailboxes → Edit mailbox → Password. При сохранении нового пароля mailcow хеширует его уже по актуальной схеме, заданной в MAILCOW_PASS_SCHEME (по умолчанию BLF-CRYPT), и старый MD5-хеш перестаёт использоваться для этого ящика — переустанавливать сам пароль пользователю на тот же самый не обязательно, можно оставить прежнее значение, если политика компании это допускает, главное — пересохранить его через штатный механизм, а не оставлять унаследованный хеш нетронутым.

При смене пароля через интерфейс mailcow сам обновляет данные для SOGo. Документация mailcow отдельно требует перезапуска SOGo в другом случае — если хеши в таблице mailbox меняли вручную SQL-запросом, в обход интерфейса: тогда представление нужно обновить командой ниже. Я выполняю её и после смены через интерфейс — это минута простоя веб-почты, зато исключает сомнения:

docker compose restart sogo-mailcow

Для «Мастерской изобретателя» это выглядело так: администратор выгрузил список пользователей с хешами через SQL-запрос, отфильтровал тех, у кого префикс {MD5} или {LDAP-MD5}, — таких оказалось 6 из 23, — и разослал каждому короткую инструкцию сменить пароль через веб-панель самообслуживания mailcow (двоим, кто не справился, пароль пересохранил администратор в Mailboxes → Edit mailbox). После этого выполнил docker compose restart sogo-mailcow, и все шесть учётных записей получили доступ к веб-почте без дополнительных действий.

Частый вопрос — нельзя ли сменить MAILCOW_PASS_SCHEME и «перехешировать» всех разом. Нельзя: хеш необратим, пересчитать его в BLF-CRYPT без исходного пароля невозможно, а переменная влияет только на пароли, которые задают или меняют после её изменения. Поэтому при десятках затронутых учётных записей путь тот же — смена паролей, только организованная массово: объявление, срок, принудительная смена для тех, кто не успел. Для 6 пользователей из 23 точечная смена через интерфейс быстрее и не трогает тех, у кого всё работает.

Отдельная деталь для новых версий: SOGo больше не пускает напрямую

При диагностике на актуальных версиях mailcow важно учитывать ещё одно изменение, не связанное напрямую с хешами: начиная с релиза mailcow 2025-03 (25 марта 2025 года) прямой вход в SOGo отключён — все неавторизованные запросы к пути /SOGo перенаправляются на общую страницу входа mailcow (/), а уже оттуда, после успешной аутентификации, администратор может настроить, куда именно перенаправлять конкретного пользователя после входа: в основной веб-интерфейс mailcow или сразу в SOGo.

Если вы разбираете подобную проблему на сервере с версией mailcow 2025-03 и новее, а старая инструкция или скриншот из интернета показывают прямой адрес входа в SOGo — это уже не рабочий сценарий, и попытка зайти по старой прямой ссылке будет выглядеть как ещё одна форма «SOGo не пускает», хотя причина совершенно другая и к MD5-хешам отношения не имеет. Я всегда сначала уточняю версию mailcow командой git describe --tags в каталоге mailcow-dockerized, прежде чем разбирать, какая из двух причин актуальна в конкретном случае. Как именно в вашей сборке SOGo проверяет пароль после входа через страницу mailcow, лучше подтвердить на тестовом ящике с {MD5}-хешем, а не переносить вывод из 2023 года на 2026-й вслепую.

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

Чек-лист из шести шагов диагностики избирательного отказа входа в SOGo после переноса mailcow
Первый пункт — версия mailcow — сразу разводит две разные причины одинакового симптома

Чек-лист: диагностика избирательного отказа входа в SOGo

Когда часть сотрудников не может войти в веб-почту, а остальные — могут, при этом IMAP/SMTP у всех работает одинаково, я прохожу короткую последовательность проверок:

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

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

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

Почему пароль работает в Outlook по IMAP, но не пускает в веб-почту SOGo?

Чаще всего пароль хранится в виде старого MD5-хеша, унаследованного при переносе. Dovecot проверяет такой хеш для IMAP и SMTP-аутентификации, а SOGo проверяет пароль своим кодом, и некоторые его сборки (в issue #5586 — SOGo 5.9.0) такие хеши не принимают.

Как проверить, в каком формате хранится пароль конкретного пользователя в mailcow?

SQL-запросом к базе mailcow в контейнере mysql-mailcow: SELECT c_uid, c_password FROM _sogo_static_view WHERE c_uid = 'user@example.com'; (логин и пароль БД — DBUSER и DBPASS из mailcow.conf). Префикс {MD5} или {LDAP-MD5} указывает на устаревший формат.

Нужно ли менять пароль пользователю на новый, чтобы починить вход в SOGo?

Нет, достаточно пересохранить прежний пароль через Mailboxes → Edit mailbox → Password в интерфейсе mailcow — при сохранении хеш пересчитывается по актуальной схеме (по умолчанию BLF-CRYPT), а значение пароля можно оставить тем же.

Почему после смены пароля вход в SOGo всё равно не сразу заработал?

Если хеш меняли вручную в базе, документация mailcow требует обновить представление командой docker compose restart sogo-mailcow. После смены пароля через интерфейс это не обязательно, но и не вредит.

После обновления mailcow пропала возможность войти в SOGo по прямой ссылке — это тоже проблема с хешами?

Нет. Начиная с релиза mailcow 2025-03 прямой вход в SOGo отключён: все неавторизованные запросы к /SOGo перенаправляются на общую страницу входа mailcow. Это отдельное изменение поведения, не связанное с MD5-хешами.

Что означает запись password policy: 65535 в логе SOGo при неудачном входе?

Это стандартная запись SOGo о том, что вход не удался («might not have worked»); значение 65535 не означает срабатывания политики паролей. Причину строка не называет — смотрите префикс хеша этого пользователя в _sogo_static_view.

Столкнулись с похожей задачей? Обращайтесь — решим

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

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи