После переноса mailcow IMAP пускает по паролю, а SOGo — нет: разбираем MD5-хеши и SQL-вид пользователей
После переноса или восстановления 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 сразу для всех, кто прошёл через такую миграцию с нуля.
Почему 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
Самое надёжное и самое простое решение — попросить сотрудника (или администратора от его имени) задать пароль заново через интерфейс 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
Когда часть сотрудников не может войти в веб-почту, а остальные — могут, при этом IMAP/SMTP у всех работает одинаково, я прохожу короткую последовательность проверок:
Такой порядок экономит время именно потому, что визуально проблема выглядит одинаково для всех непопавших пользователей, а причины на практике встречаются две принципиально разные — формат унаследованного хеша и изменившееся поведение самого SOGo между версиями mailcow.
После того как доступ восстановлен, я рекомендую клиентам включить проверку хешей паролей в регламент эксплуатации mailcow — рядом с обновлениями, бэкапами и антиспамом: разовая выборка пользователей со старыми схемами хеширования раз в квартал занимает пару минут, а находит проблему до того, как на неё пожалуется сотрудник, а не после.
- Проверить версию mailcow (`git describe --tags`) — если 2025-03 и новее, сначала исключить причину с отключённым прямым входом в SOGo
- Сверить дату последней смены пароля у проблемных пользователей с датой миграции или восстановления сервера
- Запросом к `_sogo_static_view` посмотреть префикс хеша (`{MD5}`, `{LDAP-MD5}` — подозрительно; `{BLF-CRYPT}` — норма)
- Найти в логе SOGo строку «Login … might not have worked» в момент неудачного входа — это признак неудавшегося входа, не политики паролей
- Пересохранить пароль через Mailboxes → Edit mailbox → Password для затронутых пользователей
- Выполнить `docker compose restart sogo-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.
Источники
- GitHub — SOGo login fails after migrate via backup_and_restore.sh (Issue #5586) — Проверен исходный кейс (11–12.12.2023): перенос через backup_and_restore.sh на mailcow 2023-11, SMTP/IMAP работали, пользователи с {MD5} (base64) не входили в SOGo, с {BLF-CRYPT} входили; в логе стандартная строка «might not have worked - password policy: 65535»; закрыт со ссылкой на рассылку SOGo. https://github.com/mailcow/mailcow-dockerized/issues/5586
- mailcow docs — Password hashing — Проверено: MAILCOW_PASS_SCHEME, BLF-CRYPT по умолчанию, полностью поддерживаемые BLF-CRYPT/SSHA/SSHA256/SSHA512; MD5 и LDAP-MD5 — в списке read-only схем, совместимых с SOGo; docker compose restart sogo-mailcow — после ручного изменения хешей в таблице mailbox. https://docs.mailcow.email/models/model-passwd/
- mailcow.email — Release notes 2025-03 — Проверено изменение поведения SOGo: прямой вход в SOGo отключён, неавторизованные запросы к /SOGo перенаправляются на страницу входа mailcow (/), администратор настраивает перенаправление после входа индивидуально по пользователю. https://mailcow.email/posts/2025/release-2025-03/
- GitHub — mailcow-dockerized, data/Dockerfiles/sogo/bootstrap-sogo.sh — Проверено точное имя SQL-представления _sogo_static_view, которое SOGo использует для чтения c_uid и c_password при аутентификации (в отличие от неверно указываемого в некоторых старых обсуждениях sogo_view). https://github.com/mailcow/mailcow-dockerized/blob/master/data/Dockerfiles/sogo/bootstrap-sogo.sh
- SOGo users mailing list — Authentication using ldap-md5 password fails — Проверено: тот же случай, SOGo обновился с ~5.8.0 до 5.9.0, хеш {MD5} в base64 в _sogo_static_view не принимается, BLF-CRYPT работает. https://www.mail-archive.com/users@sogo.nu/msg32872.html



