Несоответствие имени хоста сертификата электронной почты вызывает перегрузку очереди Sidekiq и серьезные сбои в работе сайта

Я занимаюсь самостоятельным хостингом Discourse уже много лет и имел несколько экземпляров, которые успешно были настроены и работали на довольно мощной машине.

Сегодня я заметил, что один из моих форумов перестал работать. Первичной причиной, как казалось, было отсутствие места на диске, что я и исправил. После этого я перезапустил экземпляр Discourse.

Однако с тех пор он продолжает регулярно падать. Каждый раз при запуске я сразу вижу, что sidekiq начинает работать некорректно, и возникает огромное количество неудачных задач по отправке электронной почты. Это также приводит к тому, что redis хранит огромный объем состояния, что, по моему мнению, и стало реальной причиной проблемы с нехваткой места на диске. (В следующий раз, когда мне удастся запустить машину, я планирую выполнить очистку, так как если я этого не сделаю, место на машине быстро закончится, и я даже не смогу запустить Discourse для выполнения очистки. Однако очистка, похоже, мало влияет на использование дискового пространства redis.)

Сообщение об ошибке указывает на несоответствие имени сертификата, что меня немного удивляет, поскольку используемый мной почтовый сервер является внутренним и не требует TLS или аутентификации. Я смог проверить на одном из своих других экземпляров (с той же конфигурацией почты), что отправка электронной почты перестала работать. В основных логах production я вижу только ошибку 422, но при отправке, например, запроса на сброс пароля в логах sidekiq появляется аналогичная ошибка:

Jobs::HandledExceptionWrapper: Wrapped OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

Я смог проверить, что отправку электронной почты можно выполнить через командную строку, поэтому проблема, похоже, не в самом почтовом сервере, а в чем-то сломанном в конфигурации Discourse.

Вот исходная конфигурация почты, которая работала до недавнего времени:

DISCOURSE_SMTP_ADDRESS: outbound-relays.techservices.illinois.edu
DISCOURSE_SMTP_PORT: 25
DISCOURSE_SMTP_ENABLE_START_TLS: false

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

Буду признателен за любую помощь! На данный момент я даже с трудом могу быть уверен в том, что именно не так, или как двигаться дальше, поскольку пересборка контейнера занимает много времени, а сообщение об ошибке в логах production содержит только ошибку 422, и я не могу понять, где искать реальную первопричину. (Она должна быть где-то, верно? Я уверен, что просто упускаю её.)

В качестве обновления: следуя совету из другой ветки, эта команда успешно отправляет письмо изнутри контейнера Docker:

echo message | s-nail -r "noreply@myforum.com" -s testing -S "smtp=same.email-service.com:25" my@address.com

Это соответствует конфигурации электронной почты, которую я использовал, когда возникла эта проблема. Обратите внимание, что я также выполнил обновление до последней версии Discourse с помощью обязательной команды pull в командной строке в пятницу, что заставляет меня задуматься, не внес ли недавний коммит эту проблему.

Когда вы в последний раз пересоздавали контейнер?

Также вы очистили очередь Redis?

В пятницу утром, насколько я помню. Обычное обновление через интерфейс вызвало необходимость в пересборке приложения launcher. Когда я позже изучил логи Sidekiq, оказалось, что очередь начала накапливаться примерно в момент пересборки контейнера, но логам Redis потребовалось около 24 часов, чтобы занять всё доступное хранилище на хосте и фактически вызвать простой. Однако, учитывая, что Sidekiq отчаянно пытался повторно отправить растущее количество неудачных задач по отправке электронной почты при 100% загрузке процессора, форум, вероятно, работал медленно уже до этого момента.

Да.

Однако меня беспокоит, что это, похоже, не снизило использование дискового пространства Redis. У меня есть папка redis_data, которая сейчас занимает 29 ГБ, даже после очистки. Возможно, Redis, как и MongoDB, неохотно освобождает выделенное дисковое пространство? Поскольку это составляет 1/3 всего доступного дискового пространства на машине, это станет проблемой, но я пока отложу это решение, чтобы сначала снова наладить работу электронной почты.

Заметка по отладке: существует ли способ отправить тестовое письмо из командной строки внутри контейнера, используя тот же поток кода, что и Discourse? (Имею в виду не отправку через командную строку с помощью другого инструмента, что я уже проверил и он работает.) Это было бы полезно для отладки, так как в настоящее время отправка тестового письма требует манипуляций с веб-интерфейсом, а затем изучения логов, чтобы понять, что пошло не так. (Пока что я вижу только ошибки 422 и ничего более полезного, кроме как в логах Sidekiq, которые не создаются при использовании потока отправки тестового письма.) Или, возможно, интерфейс отправки тестового письма мог бы предоставлять больше информации для отладки?

В целом я подозреваю, что большинство людей настраивают Discourse и не доходят до этой точки, пока почта не заработает, поскольку она необходима для отправки первоначальных приглашений и так далее. Однако я обнаруживаю, что возможности отладки ограничены в случае, когда почта работала и внезапно перестала. (Также, возможно, потребуется настроить логику повторных попыток, поскольку в данном случае повторные попытки кажутся слишком быстрыми. Ошибка сертификата, скорее всего, не будет исправлена через несколько секунд после первой попытки…)

Возможно, стоит посмотреть Устранение неполадок с электронной почтой на новой установке Discourse. Думаю, вам нужно

 rake emails:test[user@domain]

Спасибо! Это полезно. Вот результат:

Testing sending to user@domain using outbound-relays.techservices.illinois.edu:25, username: with plain auth.
======================================== ERROR ========================================
                                    UNEXPECTED ERROR

SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)
=======================================================================================

Я сейчас пересоберу контейнер, чтобы убедиться, что он и app.yml синхронизированы. Но в целом меня немного сбивает с толку сообщение о том, что используется обычная аутентификация (plain auth), поскольку в файле конфигурации app.yml не указаны ни имя пользователя, ни пароль.

Стоит ли перекатегоризировать это как ошибку (баг)? Изначально я колебался, так как речь об электронной почте, и здесь множество причин некорректной работы, многие из которых могут быть результатом моих действий или внешних изменений. Но насколько я могу судить, это конфигурация, которая работала несколько лет, и внезапно перестала работать после обновления до последней версии discourse_docker. Возможно, недавно изменился способ обработки файлов конфигурации?

Что касается самого сообщения об ошибке — я смог получить сертификат для этого сервера, и действительно, в сертификате указан другой хостнейм (другой CNAME для той же машины). Однако сам сертификат несколько лет назад, и он истёк примерно год назад, но эта ошибка стала возникать только недавно. Это заставляет меня думать, что проблема не в изменении сертификата.

При подключении к этому хосту и тестировании STARTTLS я получаю сертификат, который не соответствует имени хоста:

Цепочка сертификатов
 0 s:/C=US/ST=California/L=Sunnyvale/O=Proofpoint, Inc./OU=ESP/CN=*.pphosted.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=Thawte RSA CA 2018
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=Thawte RSA CA 2018
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA

При этом срок его действия ещё не истёк:

notBefore=Jun 12 00:00:00 2020 GMT
notAfter=Sep 14 12:00:00 2022 GMT

Прямой и обратный поиск показывают, что почтовые серверы на самом деле называются mx0a-00007101.pphosted.com и mx0b-00007101.pphosted.com:

outbound-relays.techservices.illinois.edu. 22 IN A 148.163.139.28
outbound-relays.techservices.illinois.edu. 22 IN A 148.163.135.28

28.139.163.148.in-addr.arpa name = mx0b-00007101.pphosted.com.
28.135.163.148.in-addr.arpa name = mx0a-00007101.pphosted.com.

Попробуйте изменить имя хоста, к которому вы подключаетесь, на одно из этих, вместо имени в домене .edu. Это не обязательно должно быть изменение сертификата; возможно, было изменено имя хоста или код. Однако ошибка верна: действительно имеется несоответствие между именем хоста и сертификатом.

Спасибо, @RGJ! Я попробую.

Однако я немного нервничаю из-за использования этих имён, так как они могут измениться в будущем и не совпадают с именем хоста, предоставляемым для использования в кампусе для этой цели. Есть ли способ отключить эту ошибку через настройки app.yml или каким-либо другим способом?

Мой подход заключался в том, чтобы сначала восстановить работоспособность, а затем разобраться, как улучшить ситуацию.

Вы должны иметь возможность установить DISCOURSE_SMTP_OPENSSL_VERIFY_MODE в false, но вы сказали, что уже пробовали это сделать.

Да, конечно! Это имеет смысл.

Кажется, я пробовал установить это значение в none, но не в false. Попробую false.

ОК, подтверждаю, что false не работает. Попробую снова none.

Также можно убедиться, что none не работает.

Я немного растерян, является ли это разумным поведением. DISCOURSE_SMTP_ENABLE_START_TLS установлен в false, что, по крайней мере для таких неэкспертов в области электронной почты, как я, делает непонятным, почему сертификат играет роль в этом сбое. Если бы на машине вообще не было сертификата, возникла бы та же проблема? (Очевидно, я не могу это проверить.) Если нет, то это кажется ещё более странным.

В любом случае, пока я воспользуюсь временным решением, но что-то в этом кажется мне странным.

Конечно. Я могу представить, что если почтовый сервер требует STARTTLS, он переопределит настройку starttls, но DISCOURSE_SMTP_OPENSSL_VERIFY_MODE всё ещё должен предотвращать ошибку.

Кто-нибудь может воспроизвести это?

@Geoffrey_Challen, как вы это исправили?

Сегодня я обновил свой форум до версии 2.9.0.beta4 (c99a6b10fb), и теперь у меня та же ошибка: Discourse не может отправлять письма:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

Я не менял конфигурацию VPS и почты!

Мой файл app.yml:

  DISCOURSE_SMTP_ADDRESS: smtp.mydomain.info
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: info@mydomain.info
  DISCOURSE_SMTP_PASSWORD: "mypassword"
  DISCOURSE_SMTP_ENABLE_START_TLS: false           # (опционально, по умолчанию true)
  DISCOURSE_SMTP_DOMAIN: mydomain.info             # (требуется некоторыми провайдерами)
  #DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.example.com    # (адрес для отправки уведомлений)

Пробовал, но ничего не изменилось…

Теперь я не могу отправлять письма и не могу использовать TLS. Что мне делать?

Выполните эту команду и посмотрите, для какого имени хоста предназначен сертификат:

openssl s_client -connect smtp.mydomain.info:25 -starttls smtp -showcerts 2>&1 | grep "depth=0"

Конечно, заменив smtp.mydomain.info на адрес вашего SMTP-сервера.

Затем проверьте, можете ли вы подключиться к SMTP-серверу, используя это имя хоста.

Спасибо за помощь @RGJ

Имя хоста — CN = *.aruba.it, поэтому оно отличается от mydomain.info, и да, я могу подключиться к SMTP-серверу, используя имя хоста и telnet.

Всё работало идеально до ./launcher rebuild app.

Но… у меня установлено DISCOURSE_SMTP_ENABLE_START_TLS: false, почему система продолжает искать сертификат?

Вы можете получить доступ к хосту, используя имя, соответствующее сертификату. Вы можете попросить администратора сервера добавить желаемое имя хоста в сертификат.

Это хороший вопрос, но, как мне кажется, его ответ можно сделать неактуальным, следуя советам выше.

Другой вопрос, который, по-моему, возникает: почему администратор почты всё сломал для вас?

Возможно, эта настройка работала раньше, а теперь нет. Неясно, будет ли проще найти и исправить эту ошибку или изменить имя хоста и посмотреть, решит ли это вашу проблему.

Никто ничего не менял, я уверен. Я просто выполнил ./launcher rebuild для установки этого плагина.

Значит, мне следует изменить имя хоста VPS на что-то, заканчивающееся на .aruba.it?

Похоже, что именно так.

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